示例#1
0
void MWWorld::InventoryStore::autoEquipArmor (const MWWorld::Ptr& actor, TSlots& slots_)
{
    // Only NPCs can wear armor for now.
    // For creatures we equip only shields.
    if (!actor.getClass().isNpc())
    {
        autoEquipShield(actor, slots_);
        return;
    }

    const MWBase::World *world = MWBase::Environment::get().getWorld();
    const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();

    static float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat();
    static float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat();

    int unarmoredSkill = actor.getClass().getSkill(actor, ESM::Skill::Unarmored);
    float unarmoredRating = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill);

    for (ContainerStoreIterator iter (begin(ContainerStore::Type_Clothing | ContainerStore::Type_Armor)); iter!=end(); ++iter)
    {
        Ptr test = *iter;

        if (!canActorAutoEquip(actor, test))
            continue;

        switch(test.getClass().canBeEquipped (test, actor).first)
        {
            case 0:
                continue;
            default:
                break;
        }

        if (iter.getType() == ContainerStore::Type_Armor &&
                test.getClass().getEffectiveArmorRating(test, actor) <= std::max(unarmoredRating, 0.f))
        {
            continue;
        }

        std::pair<std::vector<int>, bool> itemsSlots =
            iter->getClass().getEquipmentSlots (*iter);

        // checking if current item pointed by iter can be equipped
        for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin());
            iter2!=itemsSlots.first.end(); ++iter2)
        {
            // if true then it means slot is equipped already
            // check if slot may require swapping if current item is more valuable
            if (slots_.at (*iter2)!=end())
            {
                Ptr old = *slots_.at (*iter2);

                if (iter.getType() == ContainerStore::Type_Armor)
                {
                    if (old.getTypeName() == typeid(ESM::Armor).name())
                    {
                        if (old.get<ESM::Armor>()->mBase->mData.mType < test.get<ESM::Armor>()->mBase->mData.mType)
                            continue;

                        if (old.get<ESM::Armor>()->mBase->mData.mType == test.get<ESM::Armor>()->mBase->mData.mType)
                        {
                            if (old.getClass().getEffectiveArmorRating(old, actor) >= test.getClass().getEffectiveArmorRating(test, actor))
                                // old armor had better armor rating
                                continue;
                        }
                    }
                    // suitable armor should replace already equipped clothing
                }
                else if (iter.getType() == ContainerStore::Type_Clothing)
                {
                    // if left ring is equipped
                    if (*iter2 == Slot_LeftRing)
                    {
                        // if there is a place for right ring dont swap it
                        if (slots_.at(Slot_RightRing) == end())
                        {
                            continue;
                        }
                        else // if right ring is equipped too
                        {
                            Ptr rightRing = *slots_.at(Slot_RightRing);

                            // we want to swap cheaper ring only if both are equipped
                            if (old.getClass().getValue (old) >= rightRing.getClass().getValue (rightRing))
                                continue;
                        }
                    }

                    if (old.getTypeName() == typeid(ESM::Clothing).name())
                    {
                        // check value
                        if (old.getClass().getValue (old) >= test.getClass().getValue (test))
                            // old clothing was more valuable
                            continue;
                    }
                    else
                        // suitable clothing should NOT replace already equipped armor
                        continue;
                }
            }

            if (!itemsSlots.second) // if itemsSlots.second is true, item can stay stacked when equipped
            {
                // unstack item pointed to by iterator if required
                if (iter->getRefData().getCount() > 1)
                {
                    unstack(*iter, actor);
                }
            }

            // if we are here it means item can be equipped or swapped
            slots_[*iter2] = iter;
            break;
        }
    }
}
示例#2
0
void MWWorld::InventoryStore::autoEquip (const MWMechanics::NpcStats& stats)
{
    TSlots slots;
    initSlots (slots);

    for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
    {
        Ptr test = *iter;
        int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test);

        std::pair<std::vector<int>, bool> itemsSlots =
            MWWorld::Class::get (*iter).getEquipmentSlots (*iter);

        for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin());
            iter2!=itemsSlots.first.end(); ++iter2)
        {
            bool use = false;

            if (slots.at (*iter2)==end())
                use = true; // slot was empty before -> skill all further checks
            else
            {
                Ptr old = *slots.at (*iter2);

                if (!use)
                {
                    // check skill
                    int oldSkill =
                        MWWorld::Class::get (old).getEquipmentSkill (old);

                    if (testSkill!=-1 || oldSkill!=-1 || testSkill!=oldSkill)
                    {
                        if (stats.mSkill[oldSkill].getModified()>stats.mSkill[testSkill].getModified())
                            continue; // rejected, because old item better matched the NPC's skills.

                        if (stats.mSkill[oldSkill].getModified()<stats.mSkill[testSkill].getModified())
                            use = true;
                    }
                }

                if (!use)
                {
                    // check value
                    if (MWWorld::Class::get (old).getValue (old)>=
                        MWWorld::Class::get (test).getValue (test))
                    {
                        continue;
                    }

                    use = true;
                }
            }

            /// \todo unstack, if reqquired (itemsSlots.second)

            slots[*iter2] = iter;
            break;
        }
    }

    bool changed = false;

    for (std::size_t i=0; i<slots.size(); ++i)
        if (slots[i]!=mSlots[i])
        {
            changed = true;
        }

    if (changed)
    {
        mSlots.swap (slots);
        flagAsModified();
    }
}