mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 06:35:30 +00:00
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.
This commit is contained in:
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…
x
Reference in New Issue
Block a user