@ -62,6 +62,7 @@ ActorAnimation::~ActorAnimation()
}
mScabbard . reset ( ) ;
mHolsteredShield . reset ( ) ;
}
PartHolderPtr ActorAnimation : : attachMesh ( const std : : string & model , const std : : string & bonename , bool enchantedGlow , osg : : Vec4f * glowColor )
@ -83,6 +84,163 @@ PartHolderPtr ActorAnimation::attachMesh(const std::string& model, const std::st
return PartHolderPtr ( new PartHolder ( instance ) ) ;
}
std : : string ActorAnimation : : getShieldMesh ( MWWorld : : ConstPtr shield ) const
{
std : : string mesh = shield . getClass ( ) . getModel ( shield ) ;
std : : string holsteredName = mesh ;
holsteredName = holsteredName . replace ( holsteredName . size ( ) - 4 , 4 , " _sh.nif " ) ;
if ( mResourceSystem - > getVFS ( ) - > exists ( holsteredName ) )
{
osg : : ref_ptr < osg : : Node > shieldTemplate = mResourceSystem - > getSceneManager ( ) - > getInstance ( holsteredName ) ;
SceneUtil : : FindByNameVisitor findVisitor ( " Bip01 Sheath " ) ;
shieldTemplate - > accept ( findVisitor ) ;
osg : : ref_ptr < osg : : Node > sheathNode = findVisitor . mFoundNode ;
if ( ! sheathNode )
return std : : string ( ) ;
}
return mesh ;
}
bool ActorAnimation : : updateCarriedLeftVisible ( const int weaptype ) const
{
static const bool shieldSheathing = Settings : : Manager : : getBool ( " shield sheathing " , " Game " ) ;
if ( shieldSheathing )
{
const MWWorld : : Class & cls = mPtr . getClass ( ) ;
MWMechanics : : CreatureStats & stats = cls . getCreatureStats ( mPtr ) ;
if ( cls . hasInventoryStore ( mPtr ) & & weaptype ! = ESM : : Weapon : : Spell )
{
const MWWorld : : InventoryStore & inv = cls . getInventoryStore ( mPtr ) ;
const MWWorld : : ConstContainerStoreIterator weapon = inv . getSlot ( MWWorld : : InventoryStore : : Slot_CarriedRight ) ;
const MWWorld : : ConstContainerStoreIterator shield = inv . getSlot ( MWWorld : : InventoryStore : : Slot_CarriedLeft ) ;
if ( shield ! = inv . end ( ) & & shield - > getTypeName ( ) = = typeid ( ESM : : Armor ) . name ( ) & & ! getShieldMesh ( * shield ) . empty ( ) )
{
if ( stats . getDrawState ( ) ! = MWMechanics : : DrawState_Weapon )
return false ;
if ( weapon ! = inv . end ( ) )
{
const std : : string & type = weapon - > getTypeName ( ) ;
if ( type = = typeid ( ESM : : Weapon ) . name ( ) )
{
const MWWorld : : LiveCellRef < ESM : : Weapon > * ref = weapon - > get < ESM : : Weapon > ( ) ;
ESM : : Weapon : : Type weaponType = ( ESM : : Weapon : : Type ) ref - > mBase - > mData . mType ;
return ! ( MWMechanics : : getWeaponType ( weaponType ) - > mFlags & ESM : : WeaponType : : TwoHanded ) ;
}
else if ( type = = typeid ( ESM : : Lockpick ) . name ( ) | | type = = typeid ( ESM : : Probe ) . name ( ) )
return true ;
}
}
}
}
return ! ( MWMechanics : : getWeaponType ( weaptype ) - > mFlags & ESM : : WeaponType : : TwoHanded ) ;
}
void ActorAnimation : : updateHolsteredShield ( bool showCarriedLeft )
{
static const bool shieldSheathing = Settings : : Manager : : getBool ( " shield sheathing " , " Game " ) ;
if ( ! shieldSheathing )
return ;
if ( ! mPtr . getClass ( ) . hasInventoryStore ( mPtr ) )
return ;
mHolsteredShield . reset ( ) ;
if ( showCarriedLeft )
return ;
const MWWorld : : InventoryStore & inv = mPtr . getClass ( ) . getInventoryStore ( mPtr ) ;
MWWorld : : ConstContainerStoreIterator shield = inv . getSlot ( MWWorld : : InventoryStore : : Slot_CarriedLeft ) ;
if ( shield = = inv . end ( ) | | shield - > getTypeName ( ) ! = typeid ( ESM : : Armor ) . name ( ) )
return ;
// Can not show holdstered shields with two-handed weapons at all
const MWWorld : : ConstContainerStoreIterator weapon = inv . getSlot ( MWWorld : : InventoryStore : : Slot_CarriedRight ) ;
if ( weapon = = inv . end ( ) )
return ;
const std : : string & type = weapon - > getTypeName ( ) ;
if ( type = = typeid ( ESM : : Weapon ) . name ( ) )
{
const MWWorld : : LiveCellRef < ESM : : Weapon > * ref = weapon - > get < ESM : : Weapon > ( ) ;
ESM : : Weapon : : Type weaponType = ( ESM : : Weapon : : Type ) ref - > mBase - > mData . mType ;
if ( MWMechanics : : getWeaponType ( weaponType ) - > mFlags & ESM : : WeaponType : : TwoHanded )
return ;
}
std : : string mesh = getShieldMesh ( * shield ) ;
if ( mesh . empty ( ) )
return ;
std : : string boneName = " Bip01 AttachShield " ;
osg : : Vec4f glowColor = shield - > getClass ( ) . getEnchantmentColor ( * shield ) ;
std : : string holsteredName = mesh ;
holsteredName = holsteredName . replace ( holsteredName . size ( ) - 4 , 4 , " _sh.nif " ) ;
bool isEnchanted = ! shield - > getClass ( ) . getEnchantment ( * shield ) . empty ( ) ;
// If we have no dedicated sheath model, use basic shield model as fallback.
if ( ! mResourceSystem - > getVFS ( ) - > exists ( holsteredName ) )
mHolsteredShield = attachMesh ( mesh , boneName , isEnchanted , & glowColor ) ;
else
mHolsteredShield = attachMesh ( holsteredName , boneName , isEnchanted , & glowColor ) ;
if ( ! mHolsteredShield )
return ;
SceneUtil : : FindByNameVisitor findVisitor ( " Bip01 Sheath " ) ;
mHolsteredShield - > getNode ( ) - > accept ( findVisitor ) ;
osg : : Group * shieldNode = findVisitor . mFoundNode ;
// If mesh author declared an empty sheath node, use transformation from this node, but use the common shield mesh.
// This approach allows to tweak shield position without need to store the whole shield mesh in the _sh file.
if ( shieldNode & & ! shieldNode - > getNumChildren ( ) )
{
osg : : ref_ptr < osg : : Node > fallbackNode = mResourceSystem - > getSceneManager ( ) - > getInstance ( mesh , shieldNode ) ;
if ( isEnchanted )
SceneUtil : : addEnchantedGlow ( shieldNode , mResourceSystem , glowColor ) ;
}
if ( mAlpha ! = 1.f )
mResourceSystem - > getSceneManager ( ) - > recreateShaders ( mHolsteredShield - > getNode ( ) ) ;
}
bool ActorAnimation : : useShieldAnimations ( ) const
{
static const bool shieldSheathing = Settings : : Manager : : getBool ( " shield sheathing " , " Game " ) ;
if ( ! shieldSheathing )
return false ;
const MWWorld : : Class & cls = mPtr . getClass ( ) ;
if ( ! cls . hasInventoryStore ( mPtr ) )
return false ;
if ( getTextKeyTime ( " shield: equip attach " ) < 0 | | getTextKeyTime ( " shield: unequip detach " ) < 0 )
return false ;
const MWWorld : : InventoryStore & inv = cls . getInventoryStore ( mPtr ) ;
const MWWorld : : ConstContainerStoreIterator weapon = inv . getSlot ( MWWorld : : InventoryStore : : Slot_CarriedRight ) ;
const MWWorld : : ConstContainerStoreIterator shield = inv . getSlot ( MWWorld : : InventoryStore : : Slot_CarriedLeft ) ;
if ( weapon ! = inv . end ( ) & & shield ! = inv . end ( ) & &
shield - > getTypeName ( ) = = typeid ( ESM : : Armor ) . name ( ) & &
! getShieldMesh ( * shield ) . empty ( ) )
{
const std : : string & type = weapon - > getTypeName ( ) ;
if ( type = = typeid ( ESM : : Weapon ) . name ( ) )
{
const MWWorld : : LiveCellRef < ESM : : Weapon > * ref = weapon - > get < ESM : : Weapon > ( ) ;
ESM : : Weapon : : Type weaponType = ( ESM : : Weapon : : Type ) ref - > mBase - > mData . mType ;
return ! ( MWMechanics : : getWeaponType ( weaponType ) - > mFlags & ESM : : WeaponType : : TwoHanded ) ;
}
else if ( type = = typeid ( ESM : : Lockpick ) . name ( ) | | type = = typeid ( ESM : : Probe ) . name ( ) )
return true ;
}
return false ;
}
osg : : Group * ActorAnimation : : getBoneByName ( const std : : string & boneName )
{
if ( ! mObjectRoot )