Allow equipping twohanded weapon and shield at the same time (Fixes #1785)

The shield can be equipped, meaning armor rating and item enchantments apply, but can not be blocked with.
moveref
scrawl 10 years ago
parent bc85bb32c2
commit d034a079e6

@ -205,6 +205,8 @@ namespace MWBase
/// Resurrects the player if necessary
virtual void keepPlayerAlive() = 0;
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
};
}

@ -1554,4 +1554,13 @@ namespace MWMechanics
if (ptr.getClass().isNpc())
calculateNpcStatModifiers(ptr, 0.f);
}
bool Actors::isReadyToBlock(const MWWorld::Ptr &ptr) const
{
PtrControllerMap::const_iterator it = mActors.find(ptr);
if (it == mActors.end())
return false;
return it->second->isReadyToBlock();
}
}

@ -125,6 +125,8 @@ namespace MWMechanics
void clear(); // Clear death counter
bool isReadyToBlock(const MWWorld::Ptr& ptr) const;
private:
PtrControllerMap mActors;

@ -648,7 +648,8 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim
mAnimation->showWeapons(true);
mAnimation->setWeaponGroup(mCurrentWeapon);
}
mAnimation->showCarriedLeft(mWeaponType != WeapType_Spell && mWeaponType != WeapType_HandToHand);
mAnimation->showCarriedLeft(updateCarriedLeftVisible(mWeaponType));
}
if(!cls.getCreatureStats(mPtr).isDead())
@ -836,6 +837,25 @@ bool CharacterController::updateCreatureState()
return false;
}
bool CharacterController::updateCarriedLeftVisible(WeaponType weaptype) const
{
// Shields/torches shouldn't be visible during any operation involving two hands
// There seems to be no text keys for this purpose, except maybe for "[un]equip start/stop",
// but they are also present in weapon drawing animation.
switch (weaptype)
{
case WeapType_Spell:
case WeapType_BowAndArrow:
case WeapType_Crossbow:
case WeapType_HandToHand:
case WeapType_TwoHand:
case WeapType_TwoWide:
return false;
default:
return true;
}
}
bool CharacterController::updateWeaponState()
{
const MWWorld::Class &cls = mPtr.getClass();
@ -850,10 +870,7 @@ bool CharacterController::updateWeaponState()
{
forcestateupdate = true;
// Shields/torches shouldn't be visible during spellcasting or hand-to-hand
// There seems to be no text keys for this purpose, except maybe for "[un]equip start/stop",
// but they are also present in weapon drawing animation.
mAnimation->showCarriedLeft(weaptype != WeapType_Spell && weaptype != WeapType_HandToHand);
mAnimation->showCarriedLeft(updateCarriedLeftVisible(weaptype));
std::string weapgroup;
if(weaptype == WeapType_None)
@ -1818,4 +1835,9 @@ void CharacterController::determineAttackType()
}
}
bool CharacterController::isReadyToBlock() const
{
return updateCarriedLeftVisible(mWeaponType);
}
}

@ -199,6 +199,8 @@ class CharacterController
/// @param num if non-NULL, the chosen animation number will be written here
std::string chooseRandomGroup (const std::string& prefix, int* num = NULL);
bool updateCarriedLeftVisible(WeaponType weaptype) const;
public:
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
virtual ~CharacterController();
@ -224,6 +226,8 @@ public:
void forceStateUpdate();
AiState& getAiState() { return mAiState; }
bool isReadyToBlock() const;
};
void getWeaponGroup(WeaponType weaptype, std::string &group);

@ -62,17 +62,10 @@ namespace MWMechanics
|| blockerStats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0)
return false;
// Don't block when in spellcasting state (shield is equipped, but not visible)
if (blockerStats.getDrawState() == DrawState_Spell)
if (!MWBase::Environment::get().getMechanicsManager()->isReadyToBlock(blocker))
return false;
MWWorld::InventoryStore& inv = blocker.getClass().getInventoryStore(blocker);
// Don't block when in hand-to-hand combat (shield is equipped, but not visible)
if (blockerStats.getDrawState() == DrawState_Weapon &&
inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight) == inv.end())
return false;
MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
if (shield == inv.end() || shield->getTypeName() != typeid(ESM::Armor).name())
return false;

@ -1352,4 +1352,9 @@ namespace MWMechanics
stats.resurrect();
}
}
bool MechanicsManager::isReadyToBlock(const MWWorld::Ptr &ptr) const
{
return mActors.isReadyToBlock(ptr);
}
}

@ -169,6 +169,8 @@ namespace MWMechanics
virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target, int bias=0, bool ignoreDistance=false);
virtual void keepPlayerAlive();
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
};
}

@ -195,6 +195,7 @@ namespace MWRender
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
@ -224,11 +225,15 @@ namespace MWRender
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::Group_All, false, 1.0f, "start", "stop", 0.0f, 0);

@ -143,7 +143,7 @@ public:
virtual void setPitchFactor(float factor) { mPitchFactor = factor; }
virtual void showWeapons(bool showWeapon);
virtual void showCarriedLeft(bool showa);
virtual void showCarriedLeft(bool show);
virtual void attachArrow();
virtual void releaseArrow();

@ -31,11 +31,7 @@ namespace MWWorld
{
case 0:
return;
case 2:
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedLeft, actor);
break;
case 3:
invStore.unequipSlot(MWWorld::InventoryStore::Slot_CarriedRight, actor);
default:
break;
}

@ -255,11 +255,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
{
case 0:
continue;
case 2:
slots_[MWWorld::InventoryStore::Slot_CarriedLeft] = end();
break;
case 3:
// Prefer keeping twohanded weapon
default:
break;
}

Loading…
Cancel
Save