void projectileHit(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, MWWorld::Ptr weapon, const MWWorld::Ptr &projectile, const Ogre::Vector3& hitPosition) { MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>(); MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); const MWWorld::Class &othercls = victim.getClass(); if(!othercls.isActor()) // Can't hit non-actors return; MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim); if(otherstats.isDead()) // Can't hit dead actors return; if(attacker.getRefData().getHandle() == "player") MWBase::Environment::get().getWindowManager()->setEnemy(victim); int weapskill = ESM::Skill::Marksman; if(!weapon.isEmpty()) weapskill = weapon.getClass().getEquipmentSkill(weapon); float skillValue = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); if((::rand()/(RAND_MAX+1.0)) > getHitChance(attacker, victim, skillValue)/100.0f) { victim.getClass().onHit(victim, 0.0f, false, projectile, attacker, false); return; } float damage = 0.0f; float fDamageStrengthBase = gmst.find("fDamageStrengthBase")->getFloat(); float fDamageStrengthMult = gmst.find("fDamageStrengthMult")->getFloat(); const unsigned char* attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop; damage = attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); // Bow/crossbow damage if (weapon != projectile) { // Arrow/bolt damage attack = projectile.get<ESM::Weapon>()->mBase->mData.mChop; damage += attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); } damage *= fDamageStrengthBase + (attackerStats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult * 0.1); if(attacker.getRefData().getHandle() == "player") attacker.getClass().skillUsageSucceeded(attacker, weapskill, 0); bool detected = MWBase::Environment::get().getMechanicsManager()->awarenessCheck(attacker, victim); if(!detected) { damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat(); MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}"); MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f); } if (victim.getClass().getCreatureStats(victim).getKnockedDown()) damage *= gmst.find("fCombatKODamageMult")->getFloat(); // Apply "On hit" effect of the weapon applyEnchantment(attacker, victim, weapon, hitPosition); if (weapon != projectile) applyEnchantment(attacker, victim, projectile, hitPosition); if (damage > 0) MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition); float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->getFloat(); if ((::rand()/(RAND_MAX+1.0)) < fProjectileThrownStoreChance/100.f) victim.getClass().getContainerStore(victim).add(projectile, 1, victim); victim.getClass().onHit(victim, damage, true, projectile, attacker, true); }
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; } if(attacker == getPlayer()) MWBase::Environment::get().getWindowManager()->setEnemy(victim); int weapskill = ESM::Skill::Marksman; if(!weapon.isEmpty()) weapskill = 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, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, attacker); return; } 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); adjustWeaponDamage(damage, weapon, attacker); reduceWeaponCondition(damage, true, weapon, attacker); if(attacker == getPlayer()) attacker.getClass().skillUsageSucceeded(attacker, weapskill, 0); if (victim.getClass().getCreatureStats(victim).getKnockedDown()) damage *= gmst.find("fCombatKODamageMult")->getFloat(); // Apply "On hit" effect of the weapon bool appliedEnchantment = applyEnchantment(attacker, victim, weapon, hitPosition); if (weapon != projectile) appliedEnchantment = applyEnchantment(attacker, victim, projectile, hitPosition); if (damage > 0) MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition); // 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, true); }
void projectileHit(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, MWWorld::Ptr weapon, const MWWorld::Ptr &projectile, const Ogre::Vector3& hitPosition) { MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>(); MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker); 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; } if(attacker.getRefData().getHandle() == "player") MWBase::Environment::get().getWindowManager()->setEnemy(victim); int weapskill = ESM::Skill::Marksman; if(!weapon.isEmpty()) weapskill = weapon.getClass().getEquipmentSkill(weapon); float skillValue = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); if((::rand()/(RAND_MAX+1.0)) > getHitChance(attacker, victim, skillValue)/100.0f) { victim.getClass().onHit(victim, 0.0f, false, projectile, attacker, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, attacker); return; } float damage = 0.0f; float fDamageStrengthBase = gmst.find("fDamageStrengthBase")->getFloat(); float fDamageStrengthMult = gmst.find("fDamageStrengthMult")->getFloat(); const unsigned char* attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop; damage = attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); // Bow/crossbow damage if (weapon != projectile) { // Arrow/bolt damage attack = projectile.get<ESM::Weapon>()->mBase->mData.mChop; damage += attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); } damage *= fDamageStrengthBase + (attackerStats.getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult * 0.1); adjustWeaponDamage(damage, weapon); reduceWeaponCondition(damage, true, weapon, attacker); if(attacker.getRefData().getHandle() == "player") attacker.getClass().skillUsageSucceeded(attacker, weapskill, 0); if (victim.getClass().getCreatureStats(victim).getKnockedDown()) damage *= gmst.find("fCombatKODamageMult")->getFloat(); // Apply "On hit" effect of the weapon applyEnchantment(attacker, victim, weapon, hitPosition); if (weapon != projectile) applyEnchantment(attacker, victim, projectile, hitPosition); if (damage > 0) MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition); // Arrows shot at enemies have a chance to turn up in their inventory if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr()) { float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->getFloat(); if ((::rand()/(RAND_MAX+1.0)) < fProjectileThrownStoreChance/100.f) victim.getClass().getContainerStore(victim).add(projectile, 1, victim); } victim.getClass().onHit(victim, damage, true, projectile, attacker, true); }