std::pair<int, std::string> Light::canBeEquipped(const MWWorld::ConstPtr &ptr, const MWWorld::Ptr &npc) const { const MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>(); if (!(ref->mBase->mData.mFlags & ESM::Light::Carry)) return std::make_pair(0,""); MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if(weapon == invStore.end()) return std::make_pair(1,""); /// \todo the 2h check is repeated many times; put it in a function if(weapon->getTypeName() == typeid(ESM::Weapon).name() && (weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)) { return std::make_pair(3,""); } return std::make_pair(1,""); }
void WeaponAnimation::attachArrow(MWWorld::Ptr actor) { MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor); MWWorld::ContainerStoreIterator weaponSlot = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if (weaponSlot == inv.end()) return; if (weaponSlot->getTypeName() != typeid(ESM::Weapon).name()) return; int weaponType = weaponSlot->get<ESM::Weapon>()->mBase->mData.mType; if (weaponType == ESM::Weapon::MarksmanThrown) { std::string soundid = weaponSlot->getClass().getUpSoundId(*weaponSlot); if(!soundid.empty()) { MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); sndMgr->playSound3D(actor, soundid, 1.0f, 1.0f); } showWeapon(true); } else if (weaponType == ESM::Weapon::MarksmanBow || weaponType == ESM::Weapon::MarksmanCrossbow) { osg::Group* parent = getArrowBone(); if (!parent) return; MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition); if (ammo == inv.end()) return; std::string model = ammo->getClass().getModel(*ammo); osg::ref_ptr<osg::Node> arrow = getResourceSystem()->getSceneManager()->getInstance(model, parent); mAmmunition = PartHolderPtr(new PartHolder(arrow)); } }
std::pair<int, std::string> Armor::canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const { MWWorld::InventoryStore& invStore = npc.getClass().getInventoryStore(npc); if (ptr.getCellRef().getCharge() == 0) return std::make_pair(0, "#{sInventoryMessage1}"); // slots that this item can be equipped in std::pair<std::vector<int>, bool> slots_ = ptr.getClass().getEquipmentSlots(ptr); if (slots_.first.empty()) return std::make_pair(0, ""); if (npc.getClass().isNpc()) { std::string npcRace = npc.get<ESM::NPC>()->mBase->mRace; // Beast races cannot equip shoes / boots, or full helms (head part vs hair part) const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(npcRace); if(race->mData.mFlags & ESM::Race::Beast) { std::vector<ESM::PartReference> parts = ptr.get<ESM::Armor>()->mBase->mParts.mParts; for(std::vector<ESM::PartReference>::iterator itr = parts.begin(); itr != parts.end(); ++itr) { if((*itr).mPart == ESM::PRT_Head) return std::make_pair(0, "#{sNotifyMessage13}"); if((*itr).mPart == ESM::PRT_LFoot || (*itr).mPart == ESM::PRT_RFoot) return std::make_pair(0, "#{sNotifyMessage14}"); } } } for (std::vector<int>::const_iterator slot=slots_.first.begin(); slot!=slots_.first.end(); ++slot) { // If equipping a shield, check if there's a twohanded weapon conflicting with it if(*slot == MWWorld::InventoryStore::Slot_CarriedLeft) { MWWorld::ContainerStoreIterator weapon = invStore.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if(weapon == invStore.end()) return std::make_pair(1,""); if(weapon->getTypeName() == typeid(ESM::Weapon).name() && (weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::LongBladeTwoHand || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoClose || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::BluntTwoWide || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::SpearTwoWide || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::AxeTwoHand || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanBow || weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow)) { return std::make_pair(3,""); } return std::make_pair(1,""); } } return std::make_pair(1,""); }
virtual void execute(Interpreter::Runtime &runtime) { MWWorld::Ptr ptr = R()(runtime); MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); MWWorld::ContainerStoreIterator it = invStore.getSlot (MWWorld::InventoryStore::Slot_CarriedRight); if (it == invStore.end() || it->getTypeName () != typeid(ESM::Weapon).name()) { runtime.push(-1); return; } runtime.push(it->get<ESM::Weapon>()->mBase->mData.mType); }
void InventoryPreview::update(int sizeX, int sizeY) { mAnimation->updateParts(); MWWorld::InventoryStore &inv = mCharacter.getClass().getInventoryStore(mCharacter); MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); std::string groupname; if(iter == inv.end()) groupname = "inventoryhandtohand"; else { const std::string &type = iter->getTypeName(); if(type == typeid(ESM::Lockpick).name() || type == typeid(ESM::Probe).name()) groupname = "inventoryweapononehand"; else if(type == typeid(ESM::Weapon).name()) { MWWorld::LiveCellRef<ESM::Weapon> *ref = iter->get<ESM::Weapon>(); int type = ref->mBase->mData.mType; if(type == ESM::Weapon::ShortBladeOneHand || type == ESM::Weapon::LongBladeOneHand || type == ESM::Weapon::BluntOneHand || type == ESM::Weapon::AxeOneHand || type == ESM::Weapon::MarksmanThrown || type == ESM::Weapon::MarksmanCrossbow || type == ESM::Weapon::MarksmanBow) groupname = "inventoryweapononehand"; else if(type == ESM::Weapon::LongBladeTwoHand || type == ESM::Weapon::BluntTwoClose || type == ESM::Weapon::AxeTwoHand) groupname = "inventoryweapontwohand"; else if(type == ESM::Weapon::BluntTwoWide || type == ESM::Weapon::SpearTwoWide) groupname = "inventoryweapontwowide"; else groupname = "inventoryhandtohand"; } else groupname = "inventoryhandtohand"; } mCurrentAnimGroup = groupname; mAnimation->play(mCurrentAnimGroup, 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0); MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name()) { if(!mAnimation->getInfo("torch")) mAnimation->play("torch", 2, MWRender::Animation::Group_LeftArm, false, 1.0f, "start", "stop", 0.0f, ~0ul); } else if(mAnimation->getInfo("torch")) mAnimation->disable("torch"); mAnimation->runAnimation(0.0f); mViewport->setDimensions (0, 0, std::min(1.f, float(sizeX) / float(512)), std::min(1.f, float(sizeY) / float(1024))); mNode->setOrientation (Ogre::Quaternion::IDENTITY); mRenderTarget->update(); mSelectionBuffer->update(); }
bool blockMeleeAttack(const MWWorld::Ptr &attacker, const MWWorld::Ptr &blocker, const MWWorld::Ptr &weapon, float damage, float attackStrength) { if (!blocker.getClass().hasInventoryStore(blocker)) return false; MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker); if (blockerStats.getKnockedDown() // Used for both knockout or knockdown || blockerStats.getHitRecovery() || blockerStats.isParalyzed()) return false; if (!MWBase::Environment::get().getMechanicsManager()->isReadyToBlock(blocker)) return false; MWWorld::InventoryStore& inv = blocker.getClass().getInventoryStore(blocker); MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if (shield == inv.end() || shield->getTypeName() != typeid(ESM::Armor).name()) return false; if (!blocker.getRefData().getBaseNode()) return false; // shouldn't happen float angleDegrees = osg::RadiansToDegrees( signedAngleRadians ( (attacker.getRefData().getPosition().asVec3() - blocker.getRefData().getPosition().asVec3()), blocker.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0), osg::Vec3f(0,0,1))); const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); if (angleDegrees < gmst.find("fCombatBlockLeftAngle")->getFloat()) return false; if (angleDegrees > gmst.find("fCombatBlockRightAngle")->getFloat()) return false; MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2f * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1f * blockerStats.getAttribute(ESM::Attribute::Luck).getModified(); float enemySwing = attackStrength; float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->getFloat() + gmst.find("fSwingBlockBase")->getFloat(); float blockerTerm = blockTerm * swingTerm; if (blocker.getClass().getMovementSettings(blocker).mPosition[1] <= 0) blockerTerm *= gmst.find("fBlockStillBonus")->getFloat(); blockerTerm *= blockerStats.getFatigueTerm(); int attackerSkill = 0; if (weapon.isEmpty()) attackerSkill = attacker.getClass().getSkill(attacker, ESM::Skill::HandToHand); else attackerSkill = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); float attackerTerm = attackerSkill + 0.2f * attackerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1f * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); attackerTerm *= attackerStats.getFatigueTerm(); int x = int(blockerTerm - attackerTerm); // int iBlockMaxChance = gmst.find("iBlockMaxChance")->getInt(); // int iBlockMinChance = gmst.find("iBlockMinChance")->getInt(); // x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x)); // // if (Misc::Rng::roll0to99() < x) // { // // Reduce shield durability by incoming damage // int shieldhealth = shield->getClass().getItemHealth(*shield); // // shieldhealth -= std::min(shieldhealth, int(damage)); // shield->getCellRef().setCharge(shieldhealth); // if (shieldhealth == 0) // inv.unequipItem(*shield, blocker); // // // Reduce blocker fatigue // const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat(); // const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat(); // const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat(); // MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue(); // float normalizedEncumbrance = blocker.getClass().getNormalizedEncumbrance(blocker); // normalizedEncumbrance = std::min(1.f, normalizedEncumbrance); // float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult; // if (!weapon.isEmpty()) // fatigueLoss += weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueBlockMult; // fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); // blockerStats.setFatigue(fatigue); // // blockerStats.setBlock(true); // // if (blocker == getPlayer()) // blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0); // // return true; // } // manual blocking if (blocker.getClass().getCreatureStats(blocker).getBlockManually()) { // Reduce shield durability by incoming damage int shieldhealth = shield->getClass().getItemHealth(*shield); shieldhealth -= std::min(shieldhealth, int(10 * damage /blockerStats.getAttribute(ESM::Skill::Block).getBase())); shield->getCellRef().setCharge(shieldhealth); if (shieldhealth == 0) inv.unequipItem(*shield, blocker); // Reduce blocker fatigue const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat(); const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat(); const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat(); MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue(); float normalizedEncumbrance = blocker.getClass().getNormalizedEncumbrance(blocker); normalizedEncumbrance = std::min(1.f, normalizedEncumbrance); float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult; if (!weapon.isEmpty()) fatigueLoss += (weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueBlockMult) - x; fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); blockerStats.setFatigue(fatigue); blockerStats.setBlock(true); if (blocker == getPlayer()) blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0); blocker.getClass().getCreatureStats(blocker).setBlockManually(false); return true; } return false; }
void WeaponAnimation::releaseArrow(MWWorld::Ptr actor, float attackStrength) { MWWorld::InventoryStore& inv = actor.getClass().getInventoryStore(actor); MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if (weapon == inv.end()) return; if (weapon->getTypeName() != typeid(ESM::Weapon).name()) return; // The orientation of the launched projectile. Always the same as the actor orientation, even if the ArrowBone's orientation dictates otherwise. osg::Quat orient = osg::Quat(actor.getRefData().getPosition().rot[0], osg::Vec3f(-1,0,0)) * osg::Quat(actor.getRefData().getPosition().rot[2], osg::Vec3f(0,0,-1)); const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); MWMechanics::applyFatigueLoss(actor, *weapon, attackStrength); if (weapon->get<ESM::Weapon>()->mBase->mData.mType == ESM::Weapon::MarksmanThrown) { // Thrown weapons get detached now osg::Node* weaponNode = getWeaponNode(); if (!weaponNode) return; osg::NodePathList nodepaths = weaponNode->getParentalNodePaths(); if (nodepaths.empty()) return; osg::Vec3f launchPos = osg::computeLocalToWorld(nodepaths[0]).getTrans(); float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->getFloat(); float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->getFloat(); float speed = fThrownWeaponMinSpeed + (fThrownWeaponMaxSpeed - fThrownWeaponMinSpeed) * attackStrength; MWBase::Environment::get().getWorld()->launchProjectile(actor, *weapon, launchPos, orient, *weapon, speed, attackStrength); showWeapon(false); inv.remove(*weapon, 1, actor); } else { // With bows and crossbows only the used arrow/bolt gets detached MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition); if (ammo == inv.end()) return; if (!mAmmunition) return; osg::ref_ptr<osg::Node> ammoNode = mAmmunition->getNode(); osg::NodePathList nodepaths = ammoNode->getParentalNodePaths(); if (nodepaths.empty()) return; osg::Vec3f launchPos = osg::computeLocalToWorld(nodepaths[0]).getTrans(); float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->getFloat(); float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->getFloat(); float speed = fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * attackStrength; MWBase::Environment::get().getWorld()->launchProjectile(actor, *ammo, launchPos, orient, *weapon, speed, attackStrength); inv.remove(*ammo, 1, actor); mAmmunition.reset(); } }
bool blockMeleeAttack(const MWWorld::Ptr &attacker, const MWWorld::Ptr &blocker, const MWWorld::Ptr &weapon, float damage) { if (!blocker.getClass().hasInventoryStore(blocker)) return false; if (blocker.getClass().getCreatureStats(blocker).getKnockedDown() || blocker.getClass().getCreatureStats(blocker).getHitRecovery()) return false; MWWorld::InventoryStore& inv = blocker.getClass().getInventoryStore(blocker); MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if (shield == inv.end() || shield->getTypeName() != typeid(ESM::Armor).name()) return false; Ogre::Degree angle = signedAngle (Ogre::Vector3(attacker.getRefData().getPosition().pos) - Ogre::Vector3(blocker.getRefData().getPosition().pos), blocker.getRefData().getBaseNode()->getOrientation().yAxis(), Ogre::Vector3(0,0,1)); const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); if (angle.valueDegrees() < gmst.find("fCombatBlockLeftAngle")->getFloat()) return false; if (angle.valueDegrees() > gmst.find("fCombatBlockRightAngle")->getFloat()) return false; MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker); if (blockerStats.getDrawState() == DrawState_Spell) return false; MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2 * blockerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1 * blockerStats.getAttribute(ESM::Attribute::Luck).getModified(); float enemySwing = attackerStats.getAttackStrength(); float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->getFloat() + gmst.find("fSwingBlockBase")->getFloat(); float blockerTerm = blockTerm * swingTerm; if (blocker.getClass().getMovementSettings(blocker).mPosition[1] <= 0) blockerTerm *= gmst.find("fBlockStillBonus")->getFloat(); blockerTerm *= blockerStats.getFatigueTerm(); float attackerSkill = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); float attackerTerm = attackerSkill + 0.2 * attackerStats.getAttribute(ESM::Attribute::Agility).getModified() + 0.1 * attackerStats.getAttribute(ESM::Attribute::Luck).getModified(); attackerTerm *= attackerStats.getFatigueTerm(); int x = int(blockerTerm - attackerTerm); int iBlockMaxChance = gmst.find("iBlockMaxChance")->getInt(); int iBlockMinChance = gmst.find("iBlockMinChance")->getInt(); x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x)); int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99] if (roll < x) { // Reduce shield durability by incoming damage if (shield->getCellRef().mCharge == -1) shield->getCellRef().mCharge = shield->getClass().getItemMaxHealth(*shield); shield->getCellRef().mCharge -= std::min(shield->getCellRef().mCharge, int(damage)); if (!shield->getCellRef().mCharge) inv.unequipItem(*shield, blocker); // Reduce blocker fatigue const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat(); const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat(); const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat(); MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue(); float normalizedEncumbrance = blocker.getClass().getEncumbrance(blocker) / blocker.getClass().getCapacity(blocker); normalizedEncumbrance = std::min(1.f, normalizedEncumbrance); float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult; fatigueLoss += weapon.getClass().getWeight(weapon) * attackerStats.getAttackStrength() * fWeaponFatigueBlockMult; fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); blockerStats.setFatigue(fatigue); blockerStats.setBlock(true); if (blocker.getClass().isNpc()) blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0); return true; } return false; }
virtual void execute(Interpreter::Runtime &runtime) { MWWorld::Ptr ptr = R()(runtime); Interpreter::Type_Integer location = runtime[0].mInteger; runtime.pop(); int slot; switch (location) { case 0: slot = MWWorld::InventoryStore::Slot_Helmet; break; case 1: slot = MWWorld::InventoryStore::Slot_Cuirass; break; case 2: slot = MWWorld::InventoryStore::Slot_LeftPauldron; break; case 3: slot = MWWorld::InventoryStore::Slot_RightPauldron; break; case 4: slot = MWWorld::InventoryStore::Slot_Greaves; break; case 5: slot = MWWorld::InventoryStore::Slot_Boots; break; case 6: slot = MWWorld::InventoryStore::Slot_LeftGauntlet; break; case 7: slot = MWWorld::InventoryStore::Slot_RightGauntlet; break; case 8: slot = MWWorld::InventoryStore::Slot_CarriedLeft; // shield break; case 9: slot = MWWorld::InventoryStore::Slot_LeftGauntlet; break; case 10: slot = MWWorld::InventoryStore::Slot_RightGauntlet; break; default: throw std::runtime_error ("armor index out of range"); } MWWorld::InventoryStore& invStore = MWWorld::Class::get(ptr).getInventoryStore (ptr); MWWorld::ContainerStoreIterator it = invStore.getSlot (slot); if (it == invStore.end() || it->getTypeName () != typeid(ESM::Armor).name()) { runtime.push(-1); return; } int skill = MWWorld::Class::get(*it).getEquipmentSkill (*it) ; if (skill == ESM::Skill::HeavyArmor) runtime.push(2); else if (skill == ESM::Skill::MediumArmor) runtime.push(1); else if (skill == ESM::Skill::LightArmor) runtime.push(0); else runtime.push(-1); }
void InventoryPreview::update() { if (!mAnimation.get()) return; mAnimation->showWeapons(true); mAnimation->updateParts(); MWWorld::InventoryStore &inv = mCharacter.getClass().getInventoryStore(mCharacter); MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); std::string groupname; bool showCarriedLeft = true; if(iter == inv.end()) groupname = "inventoryhandtohand"; else { const std::string &typeName = iter->getTypeName(); if(typeName == typeid(ESM::Lockpick).name() || typeName == typeid(ESM::Probe).name()) groupname = "inventoryweapononehand"; else if(typeName == typeid(ESM::Weapon).name()) { MWWorld::LiveCellRef<ESM::Weapon> *ref = iter->get<ESM::Weapon>(); int type = ref->mBase->mData.mType; if(type == ESM::Weapon::ShortBladeOneHand || type == ESM::Weapon::LongBladeOneHand || type == ESM::Weapon::BluntOneHand || type == ESM::Weapon::AxeOneHand || type == ESM::Weapon::MarksmanThrown || type == ESM::Weapon::MarksmanCrossbow || type == ESM::Weapon::MarksmanBow) groupname = "inventoryweapononehand"; else if(type == ESM::Weapon::LongBladeTwoHand || type == ESM::Weapon::BluntTwoClose || type == ESM::Weapon::AxeTwoHand) groupname = "inventoryweapontwohand"; else if(type == ESM::Weapon::BluntTwoWide || type == ESM::Weapon::SpearTwoWide) groupname = "inventoryweapontwowide"; else groupname = "inventoryhandtohand"; showCarriedLeft = (iter->getClass().canBeEquipped(*iter, mCharacter).first != 2); } else groupname = "inventoryhandtohand"; } mAnimation->showCarriedLeft(showCarriedLeft); mCurrentAnimGroup = groupname; mAnimation->play(mCurrentAnimGroup, 1, Animation::BlendMask_All, false, 1.0f, "start", "stop", 0.0f, 0); MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name() && showCarriedLeft) { if(!mAnimation->getInfo("torch")) mAnimation->play("torch", 2, Animation::BlendMask_LeftArm, false, 1.0f, "start", "stop", 0.0f, ~0ul, true); } else if(mAnimation->getInfo("torch")) mAnimation->disable("torch"); mAnimation->runAnimation(0.0f); redraw(); }