@ -33,7 +33,7 @@ float signedAngleRadians (const osg::Vec3f& v1, const osg::Vec3f& v2, const osg:
namespace MWMechanics
{
bool applyOnStrikeEnchantment ( const MWWorld : : Ptr & attacker , const MWWorld : : Ptr & victim , const MWWorld : : Ptr & object , const osg : : Vec3f & hitPosition )
bool applyOnStrikeEnchantment ( const MWWorld : : Ptr & attacker , const MWWorld : : Ptr & victim , const MWWorld : : Ptr & object , const osg : : Vec3f & hitPosition , const bool fromProjectile )
{
std : : string enchantmentName = ! object . isEmpty ( ) ? object . getClass ( ) . getEnchantment ( object ) : " " ;
if ( ! enchantmentName . empty ( ) )
@ -42,7 +42,7 @@ namespace MWMechanics
enchantmentName ) ;
if ( enchantment - > mData . mType = = ESM : : Enchantment : : WhenStrikes )
{
MWMechanics : : CastSpell cast ( attacker , victim );
MWMechanics : : CastSpell cast ( attacker , victim , fromProjectile );
cast . mHitPosition = hitPosition ;
cast . cast ( object , false ) ;
return true ;
@ -165,69 +165,69 @@ namespace MWMechanics
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > messageBox ( " #{sMagicTargetResistsWeapons} " ) ;
}
void projectileHit ( const MWWorld : : Ptr & attacker , const MWWorld : : Ptr & victim , MWWorld : : Ptr weapon , const MWWorld : : Ptr & projectile ,
void projectileHit ( const MWWorld : : Ptr & attacker , const MWWorld : : Ptr & victim , MWWorld : : Ptr weapon , const MWWorld : : Ptr & projectile ,
const osg : : Vec3f & hitPosition , float attackStrength )
{
MWBase : : World * world = MWBase : : Environment : : get ( ) . getWorld ( ) ;
const MWWorld : : Store < ESM : : GameSetting > & gmst = world - > getStore ( ) . get < ESM : : GameSetting > ( ) ;
if ( victim . isEmpty ( ) | | ! victim . getClass ( ) . isActor ( ) | | victim . getClass ( ) . getCreatureStats ( victim ) . isDead ( ) )
// Can't hit non-actors or dead actors
{
reduceWeaponCondition ( 0.f , false , weapon , attacker ) ;
return ;
}
bool validVictim = ! victim . isEmpty ( ) & & victim . getClass ( ) . isActor ( ) ;
if ( attacker = = getPlayer ( ) )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setEnemy ( victim ) ;
float damage = 0.f ;
if ( validVictim )
{
if ( attacker = = getPlayer ( ) )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setEnemy ( victim ) ;
int weapskill = ESM : : Skill : : Marksman ;
if ( ! weapon . isEmpty ( ) )
weaps kill = weapon . getClass ( ) . getEquipmentSkill ( weapon ) ;
int weaponS kill = ESM : : Skill : : Marksman ;
if ( ! weapon . isEmpty ( ) )
weaponS kill = weapon . getClass ( ) . getEquipmentSkill ( weapon ) ;
int skillValue = attacker . getClass ( ) . getSkill ( attacker ,
weapon . getClass ( ) . getEquipmentSkill ( weapon ) ) ;
int skillValue = attacker . getClass ( ) . getSkill ( attacker , weapon . getClass ( ) . getEquipmentSkill ( weapon ) ) ;
if ( Misc : : Rng : : roll0to99 ( ) > = getHitChance ( attacker , victim , skillValue ) )
{
victim . getClass ( ) . onHit ( victim , 0.0f , false , projectile , attacker , osg : : Vec3f ( ) , false ) ;
MWMechanics : : reduceWeaponCondition ( 0.f , false , weapon , attacker ) ;
return ;
}
if ( Misc : : Rng : : roll0to99 ( ) > = getHitChance ( attacker , victim , skillValue ) )
{
victim . getClass ( ) . onHit ( victim , damage , false , projectile , attacker , osg : : Vec3f ( ) , false ) ;
MWMechanics : : reduceWeaponCondition ( damage , false , weapon , attacker ) ;
return ;
}
const unsigned char * attack = weapon . get < ESM : : Weapon > ( ) - > mBase - > mData . mChop ;
damage = attack [ 0 ] + ( ( attack [ 1 ] - attack [ 0 ] ) * attackStrength ) ; // Bow/crossbow damage
const unsigned char * attack = weapon . get < ESM : : Weapon > ( ) - > mBase - > mData . mChop ;
float damage = attack [ 0 ] + ( ( attack [ 1 ] - attack [ 0 ] ) * attackStrength ) ; // Bow/crossbow damage
// Arrow/bolt damage
// NB in case of thrown weapons, we are applying the damage twice since projectile == weapon
attack = projectile . get < ESM : : Weapon > ( ) - > mBase - > mData . mChop ;
damage + = attack [ 0 ] + ( ( attack [ 1 ] - attack [ 0 ] ) * attackStrength ) ;
// Arrow/bolt damage
// NB in case of thrown weapons, we are applying the damage twice since projectile == weapon
attack = projectile . get < ESM : : Weapon > ( ) - > mBase - > mData . mChop ;
damage + = attack [ 0 ] + ( ( attack [ 1 ] - attack [ 0 ] ) * attackStrength ) ;
adjustWeaponDamage ( damage , weapon , attacker ) ;
adjustWeaponDamage ( damage , weapon , attacker ) ;
reduceWeaponCondition ( damage , true , weapon , attacker ) ;
if ( attacker = = getPlayer ( ) )
attacker . getClass ( ) . skillUsageSucceeded ( attacker , weaponSkill , 0 ) ;
if ( attacker = = getPlayer ( ) )
attacker . getClass ( ) . skillUsageSucceeded ( attacker , weapskill , 0 ) ;
if ( victim . getClass ( ) . getCreatureStats ( victim ) . getKnockedDown ( ) )
damage * = gmst . find ( " fCombatKODamageMult " ) - > getFloat ( ) ;
}
if ( victim . getClass ( ) . getCreatureStats ( victim ) . getKnockedDown ( ) )
damage * = gmst . find ( " fCombatKODamageMult " ) - > getFloat ( ) ;
reduceWeaponCondition ( damage , validVictim , weapon , attacker ) ;
// Apply "On hit" effect of the weapon
bool appliedEnchantment = applyOnStrikeEnchantment ( attacker , victim , weapon , hitPosition );
// Apply "On hit" effect of the weapon & projectile
bool appliedEnchantment = applyOnStrikeEnchantment ( attacker , victim , weapon , hitPosition , true );
if ( weapon ! = projectile )
appliedEnchantment = applyOnStrikeEnchantment ( attacker , victim , projectile , hitPosition );
appliedEnchantment = applyOnStrikeEnchantment ( attacker , victim , projectile , hitPosition , true );
// Non-enchanted arrows shot at enemies have a chance to turn up in their inventory
if ( victim ! = getPlayer ( )
& & ! appliedEnchantment )
if ( validVictim )
{
float fProjectileThrownStoreChance = gmst . find ( " fProjectileThrownStoreChance " ) - > getFloat ( ) ;
if ( Misc : : Rng : : rollProbability ( ) < fProjectileThrownStoreChance / 100.f )
victim . getClass ( ) . getContainerStore ( victim ) . add ( projectile , 1 , victim ) ;
}
// Non-enchanted arrows shot at enemies have a chance to turn up in their inventory
if ( victim ! = getPlayer ( ) & & ! appliedEnchantment )
{
float fProjectileThrownStoreChance = gmst . find ( " fProjectileThrownStoreChance " ) - > getFloat ( ) ;
if ( Misc : : Rng : : rollProbability ( ) < fProjectileThrownStoreChance / 100.f )
victim . getClass ( ) . getContainerStore ( victim ) . add ( projectile , 1 , victim ) ;
}
victim . getClass ( ) . onHit ( victim , damage , true , projectile , attacker , hitPosition , true ) ;
victim . getClass ( ) . onHit ( victim , damage , true , projectile , attacker , hitPosition , true ) ;
}
}
float getHitChance ( const MWWorld : : Ptr & attacker , const MWWorld : : Ptr & victim , int skillValue )