Ejemplo n.º 1
0
    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);
    }
Ejemplo n.º 2
0
    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);
    }