示例#1
0
    boost::shared_ptr<Action> prepareNextAction(const MWWorld::Ptr &actor, const MWWorld::Ptr &target)
    {
        Spells& spells = actor.getClass().getCreatureStats(actor).getSpells();

        float bestActionRating = 0.f;
        // Default to hand-to-hand combat
        boost::shared_ptr<Action> bestAction (new ActionWeapon(MWWorld::Ptr()));
        if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
        {
            bestAction->prepare(actor);
            return bestAction;
        }

        if (actor.getClass().hasInventoryStore(actor))
        {
            MWWorld::InventoryStore& store = actor.getClass().getInventoryStore(actor);

            for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
            {
                float rating = ratePotion(*it, actor);
                if (rating > bestActionRating)
                {
                    bestActionRating = rating;
                    bestAction.reset(new ActionPotion(*it));
                }
            }

            for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
            {
                float rating = rateMagicItem(*it, actor, target);
                if (rating > bestActionRating)
                {
                    bestActionRating = rating;
                    bestAction.reset(new ActionEnchantedItem(it));
                }
            }

            float bestArrowRating = 0;
            MWWorld::Ptr bestArrow;
            for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
            {
                float rating = rateWeapon(*it, actor, target, ESM::Weapon::Arrow);
                if (rating > bestArrowRating)
                {
                    bestArrowRating = rating;
                    bestArrow = *it;
                }
            }

            float bestBoltRating = 0;
            MWWorld::Ptr bestBolt;
            for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
            {
                float rating = rateWeapon(*it, actor, target, ESM::Weapon::Bolt);
                if (rating > bestBoltRating)
                {
                    bestBoltRating = rating;
                    bestBolt = *it;
                }
            }

            for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
            {
                std::vector<int> equipmentSlots = it->getClass().getEquipmentSlots(*it).first;
                if (std::find(equipmentSlots.begin(), equipmentSlots.end(), (int)MWWorld::InventoryStore::Slot_CarriedRight)
                        == equipmentSlots.end())
                    continue;

                float rating = rateWeapon(*it, actor, target, -1, bestArrowRating, bestBoltRating);
                if (rating > bestActionRating)
                {
                    const ESM::Weapon* weapon = it->get<ESM::Weapon>()->mBase;

                    MWWorld::Ptr ammo;
                    if (weapon->mData.mType == ESM::Weapon::MarksmanBow)
                        ammo = bestArrow;
                    else if (weapon->mData.mType == ESM::Weapon::MarksmanCrossbow)
                        ammo = bestBolt;

                    bestActionRating = rating;
                    bestAction.reset(new ActionWeapon(*it, ammo));
                }
            }
        }

        for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
        {
            const ESM::Spell* spell = it->first;

            float rating = rateSpell(spell, actor, target);
            if (rating > bestActionRating)
            {
                bestActionRating = rating;
                bestAction.reset(new ActionSpell(spell->mId));
            }
        }

        if (bestAction.get())
            bestAction->prepare(actor);

        return bestAction;
    }
示例#2
0
bool AiFollow::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
    MWWorld::Ptr target = getTarget();

    if (target.isEmpty() || !target.getRefData().getCount() || !target.getRefData().isEnabled()  // Really we should be checking whether the target is currently registered
                                                                                                 // with the MechanicsManager
            )
        return false; // Target is not here right now, wait for it to return

    actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);

    AiFollowStorage& storage = state.get<AiFollowStorage>();

    // AiFollow requires the target to be in range and within sight for the initial activation
    if (!mActive)
    {
        storage.mTimer -= duration;

        if (storage.mTimer < 0)
        {
            if ((actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length2()
                    < 500*500
                    && MWBase::Environment::get().getWorld()->getLOS(actor, target))
                mActive = true;
            storage.mTimer = 0.5f;
        }
    }
    if (!mActive)
        return false;

    ESM::Position pos = actor.getRefData().getPosition(); //position of the actor

    float followDistance = 180;
    // When there are multiple actors following the same target, they form a group with each group member at 180*(i+1) distance to the target
    int i=0;
    std::list<int> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowingIndices(target);
    followers.sort();
    for (std::list<int>::iterator it = followers.begin(); it != followers.end(); ++it)
    {
        if (*it == mFollowIndex)
            followDistance *= (i+1);
        ++i;
    }

    if(!mAlwaysFollow) //Update if you only follow for a bit
    {
         //Check if we've run out of time
        if (mDuration != 0)
        {
            mRemainingDuration -= ((duration*MWBase::Environment::get().getWorld()->getTimeScaleFactor()) / 3600);
            if (mRemainingDuration <= 0)
            {
                mRemainingDuration = mDuration;
                return true;
            }
        }

        if((pos.pos[0]-mX)*(pos.pos[0]-mX) +
            (pos.pos[1]-mY)*(pos.pos[1]-mY) +
            (pos.pos[2]-mZ)*(pos.pos[2]-mZ) < followDistance*followDistance) //Close-ish to final position
        {
            if(actor.getCell()->isExterior()) //Outside?
            {
                if(mCellId == "") //No cell to travel to
                    return true;
            }
            else
            {
                if(mCellId == actor.getCell()->getCell()->mName) //Cell to travel to
                    return true;
            }
        }
    }

    //Set the target destination from the actor
    ESM::Pathgrid::Point dest = target.getRefData().getPosition().pos;

    if (!storage.mMoving) 
    {
        const float threshold = 10; // to avoid constant switching between moving/stopping
        followDistance += threshold;
    }

    storage.mMoving = !pathTo(actor, dest, duration, followDistance); // Go to the destination

    if (storage.mMoving)
    {
        //Check if you're far away
        float dist = distance(dest, pos.pos[0], pos.pos[1], pos.pos[2]);

        if (dist > 450)
            actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, true); //Make NPC run
        else if (dist < 325) //Have a bit of a dead zone, otherwise npc will constantly flip between running and not when right on the edge of the running threshhold
            actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, false); //make NPC walk
    }

    return false;
}
示例#3
0
void Recharge::onItemClicked(MyGUI::Widget *sender)
{
    MWWorld::Ptr gem = *mGemIcon->getUserData<MWWorld::Ptr>();

    if (!gem.getRefData().getCount())
        return;

    MWWorld::Ptr item = *sender->getUserData<MWWorld::Ptr>();

    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
    MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
    MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player);

    float luckTerm = 0.1f * stats.getAttribute(ESM::Attribute::Luck).getModified();
    if (luckTerm < 1|| luckTerm > 10)
        luckTerm = 1;

    float intelligenceTerm = 0.2f * stats.getAttribute(ESM::Attribute::Intelligence).getModified();

    if (intelligenceTerm > 20)
        intelligenceTerm = 20;
    if (intelligenceTerm < 1)
        intelligenceTerm = 1;

    float x = (npcStats.getSkill(ESM::Skill::Enchant).getModified() + intelligenceTerm + luckTerm) * stats.getFatigueTerm();
    int roll = OEngine::Misc::Rng::roll0to99();
    if (roll < x)
    {
        std::string soul = gem.getCellRef().getSoul();
        const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().find(soul);

        float restored = creature->mData.mSoul * (roll / x);

        const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(
                    item.getClass().getEnchantment(item));
        item.getCellRef().setEnchantmentCharge(
            std::min(item.getCellRef().getEnchantmentCharge() + restored, static_cast<float>(enchantment->mData.mCharge)));

        player.getClass().getContainerStore(player).restack(item);

        player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0);
    }

    gem.getContainerStore()->remove(gem, 1, player);

    if (gem.getRefData().getCount() == 0)
    {
        std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage51")->getString();
        message = boost::str(boost::format(message) % gem.getClass().getName(gem));
        MWBase::Environment::get().getWindowManager()->messageBox(message);

        // special case: readd Azura's Star
        if (Misc::StringUtils::ciEqual(gem.get<ESM::Miscellaneous>()->mBase->mId, "Misc_SoulGem_Azura"))
            player.getClass().getContainerStore(player).add("Misc_SoulGem_Azura", 1, player);
    }

    updateView();
}
示例#4
0
    void AlchemyWindow::update()
    {
        mSortModel->clearDragItems();

        MWMechanics::Alchemy::TIngredientsIterator it = mAlchemy.beginIngredients ();
        for (int i=0; i<4; ++i)
        {
            MyGUI::ImageBox* ingredient = mIngredients[i];

            MWWorld::Ptr item;
            if (it != mAlchemy.endIngredients ())
            {
                item = *it;
                ++it;
            }

            if (!item.isEmpty())
                mSortModel->addDragItem(item, item.getRefData().getCount());

            if (ingredient->getChildCount())
                MyGUI::Gui::getInstance().destroyWidget(ingredient->getChildAt(0));

            ingredient->setImageTexture("");
            ingredient->clearUserStrings ();

            if (item.isEmpty ())
                continue;

            ingredient->setUserString("ToolTipType", "ItemPtr");
            ingredient->setUserData(item);
            ingredient->setImageTexture(getIconPath(item));

            MyGUI::TextBox* text = ingredient->createWidget<MyGUI::TextBox>("SandBrightText", MyGUI::IntCoord(0, 14, 32, 18), MyGUI::Align::Default, std::string("Label"));
            text->setTextAlign(MyGUI::Align::Right);
            text->setNeedMouseFocus(false);
            text->setTextShadow(true);
            text->setTextShadowColour(MyGUI::Colour(0,0,0));
            text->setCaption(getCountString(ingredient->getUserData<MWWorld::Ptr>()->getRefData().getCount()));
        }

        mItemView->update();

        std::vector<ESM::ENAMstruct> effects;
        ESM::EffectList list;
        list.mList = effects;
        for (MWMechanics::Alchemy::TEffectsIterator it = mAlchemy.beginEffects (); it != mAlchemy.endEffects (); ++it)
        {
            list.mList.push_back(*it);
        }

        while (mEffectsBox->getChildCount())
            MyGUI::Gui::getInstance().destroyWidget(mEffectsBox->getChildAt(0));

        MyGUI::IntCoord coord(0, 0, mEffectsBox->getWidth(), 24);
        Widgets::MWEffectListPtr effectsWidget = mEffectsBox->createWidget<Widgets::MWEffectList>
            ("MW_StatName", coord, MyGUI::Align::Left | MyGUI::Align::Top);

        Widgets::SpellEffectList _list = Widgets::MWEffectList::effectListFromESM(&list);
        effectsWidget->setEffectList(_list);

        std::vector<MyGUI::Widget*> effectItems;
        effectsWidget->createEffectWidgets(effectItems, mEffectsBox, coord, false, 0);
        effectsWidget->setCoord(coord);
    }
示例#5
0
 void Container::unlock (const MWWorld::Ptr& ptr) const
 {
     ptr.getCellRef().lockLevel = 0;
 }
示例#6
0
bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) const
{
    MWWorld::Ptr player = MWMechanics::getPlayer();

    switch (select.getFunction())
    {
        case SelectWrapper::Function_False:

            return false;

        case SelectWrapper::Function_NotId:

            return !Misc::StringUtils::ciEqual(mActor.getCellRef().getRefId(), select.getName());

        case SelectWrapper::Function_NotFaction:

            return !Misc::StringUtils::ciEqual(mActor.getClass().getPrimaryFaction(mActor), select.getName());

        case SelectWrapper::Function_NotClass:

            return !Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mClass, select.getName());

        case SelectWrapper::Function_NotRace:

            return !Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mRace, select.getName());

        case SelectWrapper::Function_NotCell:

            return !Misc::StringUtils::ciEqual(MWBase::Environment::get().getWorld()->getCellName(mActor.getCell())
                                               , select.getName());

        case SelectWrapper::Function_NotLocal:
        {
            std::string scriptName = mActor.getClass().getScript (mActor);

            if (scriptName.empty())
                // This actor has no attached script, so there is no local variable
                return true;

            const Compiler::Locals& localDefs =
                MWBase::Environment::get().getScriptManager()->getLocals (scriptName);

            return localDefs.getIndex (Misc::StringUtils::lowerCase (select.getName()))==-1;
        }

        case SelectWrapper::Function_SameGender:

            return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==
                (mActor.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female);

        case SelectWrapper::Function_SameRace:

            return Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mRace, player.get<ESM::NPC>()->mBase->mRace);

        case SelectWrapper::Function_SameFaction:

            return player.getClass().getNpcStats (player).isInFaction(mActor.getClass().getPrimaryFaction(mActor));

        case SelectWrapper::Function_PcCommonDisease:

            return player.getClass().getCreatureStats (player).hasCommonDisease();

        case SelectWrapper::Function_PcBlightDisease:

            return player.getClass().getCreatureStats (player).hasBlightDisease();

        case SelectWrapper::Function_PcCorprus:

            return player.getClass().getCreatureStats (player).
                getMagicEffects().get (ESM::MagicEffect::Corprus).getMagnitude()!=0;

        case SelectWrapper::Function_PcExpelled:
        {
            std::string faction = mActor.getClass().getPrimaryFaction(mActor);

            if (faction.empty())
                return false;

            return player.getClass().getNpcStats(player).getExpelled(faction);
        }

        case SelectWrapper::Function_PcVampire:

            return player.getClass().getCreatureStats(player).getMagicEffects().
                    get(ESM::MagicEffect::Vampirism).getMagnitude() > 0;

        case SelectWrapper::Function_TalkedToPc:

            return mTalkedToPlayer;

        case SelectWrapper::Function_Alarmed:

            return mActor.getClass().getCreatureStats (mActor).isAlarmed();

        case SelectWrapper::Function_Detected:

            return MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, mActor);

        case SelectWrapper::Function_Attacked:

            return mActor.getClass().getCreatureStats (mActor).getAttacked();

        case SelectWrapper::Function_ShouldAttack:

            return MWBase::Environment::get().getMechanicsManager()->isAggressive(mActor,
                    MWMechanics::getPlayer());

        case SelectWrapper::Function_Werewolf:

            return mActor.getClass().getNpcStats (mActor).isWerewolf();

        default:

            throw std::runtime_error ("unknown boolean select function");
    }
}
示例#7
0
void MWState::StateManager::saveGame (const std::string& description, const Slot *slot)
{
    try
    {
        ESM::SavedGame profile;

        MWBase::World& world = *MWBase::Environment::get().getWorld();

        MWWorld::Ptr player = world.getPlayerPtr();

        profile.mContentFiles = world.getContentFiles();

        profile.mPlayerName = player.get<ESM::NPC>()->mBase->mName;
        profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel();

        std::string classId = player.get<ESM::NPC>()->mBase->mClass;
        if (world.getStore().get<ESM::Class>().isDynamic(classId))
            profile.mPlayerClassName = world.getStore().get<ESM::Class>().find(classId)->mName;
        else
            profile.mPlayerClassId = classId;

        profile.mPlayerCell = world.getCellName();

        profile.mInGameTime.mGameHour = world.getTimeStamp().getHour();
        profile.mInGameTime.mDay = world.getDay();
        profile.mInGameTime.mMonth = world.getMonth();
        profile.mInGameTime.mYear = world.getYear();
        profile.mTimePlayed = mTimePlayed;
        profile.mDescription = description;

        writeScreenshot(profile.mScreenshot);

        if (!slot)
            slot = getCurrentCharacter()->createSlot (profile);
        else
            slot = getCurrentCharacter()->updateSlot (slot, profile);

        // Write to a memory stream first. If there is an exception during the save process, we don't want to trash the
        // existing save file we are overwriting.
        std::stringstream stream;

        ESM::ESMWriter writer;

        const std::vector<std::string>& current =
            MWBase::Environment::get().getWorld()->getContentFiles();

        for (std::vector<std::string>::const_iterator iter (current.begin()); iter!=current.end();
            ++iter)
            writer.addMaster (*iter, 0); // not using the size information anyway -> use value of 0

        writer.setFormat (ESM::SavedGame::sCurrentFormat);

        // all unused
        writer.setVersion(0);
        writer.setType(0);
        writer.setAuthor("");
        writer.setDescription("");

        int recordCount =         1 // saved game header
                +MWBase::Environment::get().getJournal()->countSavedGameRecords()
                +MWBase::Environment::get().getWorld()->countSavedGameRecords()
                +MWBase::Environment::get().getScriptManager()->getGlobalScripts().countSavedGameRecords()
                +MWBase::Environment::get().getDialogueManager()->countSavedGameRecords()
                +MWBase::Environment::get().getWindowManager()->countSavedGameRecords()
                +MWBase::Environment::get().getMechanicsManager()->countSavedGameRecords();
        writer.setRecordCount (recordCount);

        writer.save (stream);

        Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
        // Using only Cells for progress information, since they typically have the largest records by far
        listener.setProgressRange(MWBase::Environment::get().getWorld()->countSavedGameCells());
        listener.setLabel("#{sNotifyMessage4}", true);

        Loading::ScopedLoad load(&listener);

        writer.startRecord (ESM::REC_SAVE);
        slot->mProfile.save (writer);
        writer.endRecord (ESM::REC_SAVE);

        MWBase::Environment::get().getJournal()->write (writer, listener);
        MWBase::Environment::get().getDialogueManager()->write (writer, listener);
        MWBase::Environment::get().getWorld()->write (writer, listener);
        MWBase::Environment::get().getScriptManager()->getGlobalScripts().write (writer, listener);
        MWBase::Environment::get().getWindowManager()->write(writer, listener);
        MWBase::Environment::get().getMechanicsManager()->write(writer, listener);

        // Ensure we have written the number of records that was estimated
        if (writer.getRecordCount() != recordCount+1) // 1 extra for TES3 record
            std::cerr << "Warning: number of written savegame records does not match. Estimated: " << recordCount+1 << ", written: " << writer.getRecordCount() << std::endl;

        writer.close();

        if (stream.fail())
            throw std::runtime_error("Write operation failed (memory stream)");

        // All good, write to file
        boost::filesystem::ofstream filestream (slot->mPath, std::ios::binary);
        filestream << stream.rdbuf();

        if (filestream.fail())
            throw std::runtime_error("Write operation failed (file stream)");

        Settings::Manager::setString ("character", "Saves",
            slot->mPath.parent_path().filename().string());
    }
    catch (const std::exception& e)
    {
        std::stringstream error;
        error << "Failed to save game: " << e.what();

        std::cerr << error.str() << std::endl;

        std::vector<std::string> buttons;
        buttons.push_back("#{sOk}");
        MWBase::Environment::get().getWindowManager()->interactiveMessageBox(error.str(), buttons);

        // If no file was written, clean up the slot
        if (slot && !boost::filesystem::exists(slot->mPath))
            getCurrentCharacter()->deleteSlot(slot);
    }
}
示例#8
0
文件: combat.cpp 项目: dteviot/openmw
    bool blockMeleeAttack(const MWWorld::Ptr &attacker, const MWWorld::Ptr &blocker, const MWWorld::Ptr &weapon, float damage, float attackStrength)
    {
        if (!blocker.getClass().hasInventoryStore(blocker))
            return false;

        MWMechanics::CreatureStats& blockerStats = blocker.getClass().getCreatureStats(blocker);

        if (blockerStats.getKnockedDown() // Used for both knockout or knockdown
                || blockerStats.getHitRecovery()
                || blockerStats.isParalyzed())
            return false;

        if (!MWBase::Environment::get().getMechanicsManager()->isReadyToBlock(blocker))
            return false;

        MWWorld::InventoryStore& inv = blocker.getClass().getInventoryStore(blocker);
        MWWorld::ContainerStoreIterator shield = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
        if (shield == inv.end() || shield->getTypeName() != typeid(ESM::Armor).name())
            return false;

        if (!blocker.getRefData().getBaseNode())
            return false; // shouldn't happen

        float angleDegrees = osg::RadiansToDegrees(
                    signedAngleRadians (
                    (attacker.getRefData().getPosition().asVec3() - blocker.getRefData().getPosition().asVec3()),
                    blocker.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0),
                    osg::Vec3f(0,0,1)));

        const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
        if (angleDegrees < gmst.find("fCombatBlockLeftAngle")->getFloat())
            return false;
        if (angleDegrees > gmst.find("fCombatBlockRightAngle")->getFloat())
            return false;

        MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker);

        float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2f * blockerStats.getAttribute(ESM::Attribute::Agility).getModified()
            + 0.1f * blockerStats.getAttribute(ESM::Attribute::Luck).getModified();
        float enemySwing = attackStrength;
        float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->getFloat() + gmst.find("fSwingBlockBase")->getFloat();

        float blockerTerm = blockTerm * swingTerm;
        if (blocker.getClass().getMovementSettings(blocker).mPosition[1] <= 0)
            blockerTerm *= gmst.find("fBlockStillBonus")->getFloat();
        blockerTerm *= blockerStats.getFatigueTerm();

        int attackerSkill = 0;
        if (weapon.isEmpty())
            attackerSkill = attacker.getClass().getSkill(attacker, ESM::Skill::HandToHand);
        else
            attackerSkill = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon));
        float attackerTerm = attackerSkill + 0.2f * attackerStats.getAttribute(ESM::Attribute::Agility).getModified()
                + 0.1f * attackerStats.getAttribute(ESM::Attribute::Luck).getModified();
        attackerTerm *= attackerStats.getFatigueTerm();

        int x = int(blockerTerm - attackerTerm);
        int iBlockMaxChance = gmst.find("iBlockMaxChance")->getInt();
        int iBlockMinChance = gmst.find("iBlockMinChance")->getInt();
        x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x));

        if (Misc::Rng::roll0to99() < x)
        {
            // Reduce shield durability by incoming damage
            int shieldhealth = shield->getClass().getItemHealth(*shield);

            shieldhealth -= std::min(shieldhealth, int(damage));
            shield->getCellRef().setCharge(shieldhealth);
            if (shieldhealth == 0)
                inv.unequipItem(*shield, blocker);

            // Reduce blocker fatigue
            const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat();
            const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat();
            const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat();
            MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue();
            float normalizedEncumbrance = blocker.getClass().getNormalizedEncumbrance(blocker);
            normalizedEncumbrance = std::min(1.f, normalizedEncumbrance);
            float fatigueLoss = fFatigueBlockBase + normalizedEncumbrance * fFatigueBlockMult;
            if (!weapon.isEmpty())
                fatigueLoss += weapon.getClass().getWeight(weapon) * attackStrength * fWeaponFatigueBlockMult;
            fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
            blockerStats.setFatigue(fatigue);

            blockerStats.setBlock(true);

            if (blocker == getPlayer())
                blocker.getClass().skillUsageSucceeded(blocker, ESM::Skill::Block, 0);

            return true;
        }
        return false;
    }
示例#9
0
void Recharge::onItemClicked(MyGUI::Widget *sender)
{
    MWWorld::Ptr gem = *mGemIcon->getUserData<MWWorld::Ptr>();

    if (!gem.getRefData().getCount())
        return;

    MWWorld::Ptr item = *sender->getUserData<MWWorld::Ptr>();

    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
    MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
    MWMechanics::NpcStats& npcStats = player.getClass().getNpcStats(player);

    float luckTerm = 0.1 * stats.getAttribute(ESM::Attribute::Luck).getModified();
    if (luckTerm < 1|| luckTerm > 10)
        luckTerm = 1;

    float intelligenceTerm = 0.2 * stats.getAttribute(ESM::Attribute::Intelligence).getModified();

    if (intelligenceTerm > 20)
        intelligenceTerm = 20;
    if (intelligenceTerm < 1)
        intelligenceTerm = 1;

    float x = (npcStats.getSkill(ESM::Skill::Enchant).getModified() + intelligenceTerm + luckTerm) * stats.getFatigueTerm();
    int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
    if (roll < x)
    {
        std::string soul = gem.getCellRef().mSoul;
        const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().find(soul);

        float restored = creature->mData.mSoul * (roll / x);

        const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(
                item.getClass().getEnchantment(item));
        item.getCellRef().mEnchantmentCharge =
            std::min(item.getCellRef().mEnchantmentCharge + restored, static_cast<float>(enchantment->mData.mCharge));

        player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0);
    }

    gem.getContainerStore()->remove(gem, 1, player);

    if (gem.getRefData().getCount() == 0)
    {
        std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage51")->getString();
        message = boost::str(boost::format(message) % gem.getClass().getName(gem));
        MWBase::Environment::get().getWindowManager()->messageBox(message);
    }

    updateView();
}
示例#10
0
void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
{
    TSlots slots_;
    initSlots (slots_);

    // Disable model update during auto-equip
    mUpdatesEnabled = false;

    for (ContainerStoreIterator iter (begin()); iter!=end(); ++iter)
    {
        Ptr test = *iter;

        // Don't autoEquip lights. Handled in Actors::updateEquippedLight based on environment light.
        if (test.getTypeName() == typeid(ESM::Light).name())
        {
            continue;
        }

        // Only autoEquip if we are the original owner of the item.
        // This stops merchants from auto equipping anything you sell to them.
        // ...unless this is a companion, he should always equip items given to him.
        if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) &&
                (actor.getClass().getScript(actor).empty() ||
                !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion")))
            continue;

        int testSkill = test.getClass().getEquipmentSkill (test);

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

        for (std::vector<int>::const_iterator iter2 (itemsSlots.first.begin());
            iter2!=itemsSlots.first.end(); ++iter2)
        {
            if (*iter2 == Slot_CarriedRight) // Items in right hand are situational use, so don't equip them.
                // Equipping weapons is handled by AiCombat. Anything else (lockpicks, probes) can't be used by NPCs anyway (yet)
                continue;

            if (slots_.at (*iter2)!=end())
            {
                Ptr old = *slots_.at (*iter2);

                // check skill
                int oldSkill = old.getClass().getEquipmentSkill (old);

                bool use = false;
                if (testSkill!=-1 && oldSkill==-1)
                    use = true;
                else if (testSkill!=-1 && oldSkill!=-1 && testSkill!=oldSkill)
                {
                    if (actor.getClass().getSkill(actor, oldSkill) > actor.getClass().getSkill (actor, testSkill))
                        continue; // rejected, because old item better matched the NPC's skills.

                    if (actor.getClass().getSkill(actor, oldSkill) < actor.getClass().getSkill (actor, testSkill))
                        use = true;
                }

                if (!use)
                {
                    // check value
                    if (old.getClass().getValue (old)>=
                        test.getClass().getValue (test))
                    {
                        continue;
                    }
                }
            }

            switch(test.getClass().canBeEquipped (test, actor).first)
            {
                case 0:
                    continue;
                case 2:
                    slots_[MWWorld::InventoryStore::Slot_CarriedLeft] = end();
                    break;
                case 3:
                    // Prefer keeping twohanded weapon
                    break;
            }

            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);
                }
            }

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

    bool changed = false;

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

    mUpdatesEnabled = true;

    if (changed)
    {
        mSlots.swap (slots_);
        fireEquipmentChangedEvent();
        updateMagicEffects(actor);
        flagAsModified();
    }
}
示例#11
0
文件: combat.cpp 项目: dteviot/openmw
    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);
    }
示例#12
0
    bool AiTravel::execute (const MWWorld::Ptr& actor,float duration)
    {
        MWBase::World *world = MWBase::Environment::get().getWorld();
        ESM::Position pos = actor.getRefData().getPosition();
        Movement &movement = actor.getClass().getMovementSettings(actor);
        const ESM::Cell *cell = actor.getCell()->getCell();

        actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false);

        MWWorld::Ptr player = world->getPlayerPtr();
        if(cell->mData.mX != player.getCell()->getCell()->mData.mX)
        {
            int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX);
            //check if actor is near the border of an inactive cell. If so, stop walking.
            if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) >
               sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
            {
                movement.mPosition[1] = 0;
                return false;
            }
        }
        if(cell->mData.mY != player.getCell()->getCell()->mData.mY)
        {
            int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY);
            //check if actor is near the border of an inactive cell. If so, stop walking.
            if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) >
               sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
            {
                movement.mPosition[1] = 0;
                return false;
            }
        }

        bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY;
        if(!mPathFinder.isPathConstructed() || cellChange)
        {
            mCellX = cell->mData.mX;
            mCellY = cell->mData.mY;

            ESM::Pathgrid::Point dest;
            dest.mX = mX;
            dest.mY = mY;
            dest.mZ = mZ;

            ESM::Pathgrid::Point start;
            start.mX = pos.pos[0];
            start.mY = pos.pos[1];
            start.mZ = pos.pos[2];

            mPathFinder.buildPath(start, dest, actor.getCell(), true);
        }

        if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
        {
            movement.mPosition[1] = 0;
            return true;
        }

        zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
        movement.mPosition[1] = 1;

        return false;
    }
                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    runtime.push (ptr.getClass().getNpcStats (ptr).getReputation ());
                }
示例#14
0
    float rateWeapon (const MWWorld::Ptr &item, const MWWorld::Ptr& actor, const MWWorld::Ptr& target, int type,
                      float arrowRating, float boltRating)
    {
        if (item.getTypeName() != typeid(ESM::Weapon).name())
            return 0.f;

        const ESM::Weapon* weapon = item.get<ESM::Weapon>()->mBase;

        if (type != -1 && weapon->mData.mType != type)
            return 0.f;

        float rating=0.f;

        if (weapon->mData.mType >= ESM::Weapon::MarksmanBow)
        {
            rating = (weapon->mData.mChop[0] + weapon->mData.mChop[1]) / 2.f;
        }
        else
        {
            for (int i=0; i<2; ++i)
            {
                rating += weapon->mData.mSlash[i];
                rating += weapon->mData.mThrust[i];
                rating += weapon->mData.mChop[i];
            }
            rating /= 6.f;
        }

        if (item.getClass().hasItemHealth(item))
        {
            if (item.getClass().getItemHealth(item) == 0)
                return 0.f;
            rating *= item.getClass().getItemHealth(item) / float(item.getClass().getItemMaxHealth(item));
        }

        if (weapon->mData.mType == ESM::Weapon::MarksmanBow)
        {
            if (arrowRating <= 0.f)
                rating = 0.f;
            else
                rating += arrowRating;
        }
        else if (weapon->mData.mType == ESM::Weapon::MarksmanCrossbow)
        {
            if (boltRating <= 0.f)
                rating = 0.f;
            else
                rating += boltRating;
        }

        if (!weapon->mEnchant.empty())
        {
            const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(weapon->mEnchant);
            if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes
                    && (item.getCellRef().getEnchantmentCharge() == -1
                        || item.getCellRef().getEnchantmentCharge() >= enchantment->mData.mCost))
                rating += rateEffects(enchantment->mEffects, actor, target);
        }

        int skill = item.getClass().getEquipmentSkill(item);
        if (skill != -1)
            rating *= actor.getClass().getSkill(actor, skill) / 100.f;

        return rating;
    }
示例#15
0
bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) const
{
    switch (select.getFunction())
    {
        case SelectWrapper::Function_Global:

            // internally all globals are float :(
            return select.selectCompare (
                MWBase::Environment::get().getWorld()->getGlobalFloat (select.getName()));

        case SelectWrapper::Function_Local:
        {
            std::string scriptName = mActor.getClass().getScript (mActor);

            if (scriptName.empty())
                return false; // no script

            std::string name = Misc::StringUtils::lowerCase (select.getName());

            const Compiler::Locals& localDefs =
                MWBase::Environment::get().getScriptManager()->getLocals (scriptName);

            char type = localDefs.getType (name);

            if (type==' ')
                return false; // script does not have a variable of this name.

            int index = localDefs.getIndex (name);
            if (index < 0)
                return false; // shouldn't happen, we checked that variable has a type above, so must exist

            const MWScript::Locals& locals = mActor.getRefData().getLocals();

            switch (type)
            {
                case 's': return select.selectCompare (static_cast<int> (locals.mShorts[index]));
                case 'l': return select.selectCompare (locals.mLongs[index]);
                case 'f': return select.selectCompare (locals.mFloats[index]);
            }

            throw std::logic_error ("unknown local variable type in dialogue filter");
        }

        case SelectWrapper::Function_PcHealthPercent:
        {
            MWWorld::Ptr player = MWMechanics::getPlayer();

            float ratio = player.getClass().getCreatureStats (player).getHealth().getCurrent() /
                player.getClass().getCreatureStats (player).getHealth().getModified();

            return select.selectCompare (static_cast<int>(ratio*100));
        }

        case SelectWrapper::Function_PcDynamicStat:
        {
            MWWorld::Ptr player = MWMechanics::getPlayer();

            float value = player.getClass().getCreatureStats (player).
                getDynamic (select.getArgument()).getCurrent();

            return select.selectCompare (value);
        }

        case SelectWrapper::Function_HealthPercent:
        {
            float ratio = mActor.getClass().getCreatureStats (mActor).getHealth().getCurrent() /
                mActor.getClass().getCreatureStats (mActor).getHealth().getModified();

            return select.selectCompare (static_cast<int>(ratio*100));
        }

        default:

            throw std::runtime_error ("unknown numeric select function");
    }
}
示例#16
0
void Recharge::updateView()
{
    MWWorld::Ptr gem = *mGemIcon->getUserData<MWWorld::Ptr>();

    std::string soul = gem.getCellRef().mSoul;
    const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().find(soul);

    mChargeLabel->setCaptionWithReplacing("#{sCharges} " + boost::lexical_cast<std::string>(creature->mData.mSoul));

    bool toolBoxVisible = (gem.getRefData().getCount() != 0);
    mGemBox->setVisible(toolBoxVisible);

    bool toolBoxWasVisible = (mBox->getPosition().top != mGemBox->getPosition().top);

    if (toolBoxVisible && !toolBoxWasVisible)
    {
        // shrink
        mBox->setPosition(mBox->getPosition() + MyGUI::IntPoint(0, mGemBox->getSize().height));
        mBox->setSize(mBox->getSize() - MyGUI::IntSize(0,mGemBox->getSize().height));
    }
    else if (!toolBoxVisible && toolBoxWasVisible)
    {
        // expand
        mBox->setPosition(MyGUI::IntPoint (mBox->getPosition().left, mGemBox->getPosition().top));
        mBox->setSize(mBox->getSize() + MyGUI::IntSize(0,mGemBox->getSize().height));
    }

    while (mView->getChildCount())
        MyGUI::Gui::getInstance().destroyWidget(mView->getChildAt(0));

    int currentY = 0;

    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
    MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
    for (MWWorld::ContainerStoreIterator iter (store.begin());
            iter!=store.end(); ++iter)
    {
        std::string enchantmentName = iter->getClass().getEnchantment(*iter);
        if (enchantmentName.empty())
            continue;
        const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(enchantmentName);
        if (iter->getCellRef().mEnchantmentCharge >= enchantment->mData.mCharge
                || iter->getCellRef().mEnchantmentCharge == -1)
            continue;

        MyGUI::TextBox* text = mView->createWidget<MyGUI::TextBox> (
                                   "SandText", MyGUI::IntCoord(8, currentY, mView->getWidth()-8, 18), MyGUI::Align::Default);
        text->setCaption(MWWorld::Class::get(*iter).getName(*iter));
        text->setNeedMouseFocus(false);
        currentY += 19;

        MyGUI::ImageBox* icon = mView->createWidget<MyGUI::ImageBox> (
                                    "ImageBox", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default);
        std::string path = std::string("icons\\");
        path += MWWorld::Class::get(*iter).getInventoryIcon(*iter);
        int pos = path.rfind(".");
        path.erase(pos);
        path.append(".dds");
        icon->setImageTexture (path);
        icon->setUserString("ToolTipType", "ItemPtr");
        icon->setUserData(*iter);
        icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onItemClicked);
        icon->eventMouseWheel += MyGUI::newDelegate(this, &Recharge::onMouseWheel);

        Widgets::MWDynamicStatPtr chargeWidget = mView->createWidget<Widgets::MWDynamicStat>
                ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default);
        chargeWidget->setValue(iter->getCellRef().mEnchantmentCharge, enchantment->mData.mCharge);
        chargeWidget->setNeedMouseFocus(false);

        currentY += 32 + 4;
    }
    mView->setCanvasSize (MyGUI::IntSize(mView->getWidth(), std::max(mView->getHeight(), currentY)));
}
示例#17
0
int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) const
{
    MWWorld::Ptr player = MWMechanics::getPlayer();

    switch (select.getFunction())
    {
        case SelectWrapper::Function_Journal:

            return MWBase::Environment::get().getJournal()->getJournalIndex (select.getName());

        case SelectWrapper::Function_Item:
        {
            MWWorld::ContainerStore& store = player.getClass().getContainerStore (player);

            return store.count(select.getName());
        }

        case SelectWrapper::Function_Dead:

            return MWBase::Environment::get().getMechanicsManager()->countDeaths (select.getName());

        case SelectWrapper::Function_Choice:

            return mChoice;

        case SelectWrapper::Function_AiSetting:

            return mActor.getClass().getCreatureStats (mActor).getAiSetting (
                        (MWMechanics::CreatureStats::AiSetting)select.getArgument()).getModified();

        case SelectWrapper::Function_PcAttribute:

            return player.getClass().getCreatureStats (player).
                getAttribute (select.getArgument()).getModified();

        case SelectWrapper::Function_PcSkill:

            return static_cast<int> (player.getClass().
                getNpcStats (player).getSkill (select.getArgument()).getModified());

        case SelectWrapper::Function_FriendlyHit:
        {
            int hits = mActor.getClass().getCreatureStats (mActor).getFriendlyHits();

            return hits>4 ? 4 : hits;
        }

        case SelectWrapper::Function_PcLevel:

            return player.getClass().getCreatureStats (player).getLevel();

        case SelectWrapper::Function_PcGender:

            return player.get<ESM::NPC>()->mBase->isMale() ? 0 : 1;

        case SelectWrapper::Function_PcClothingModifier:
        {
            MWWorld::InventoryStore& store = player.getClass().getInventoryStore (player);

            int value = 0;

            for (int i=0; i<=15; ++i) // everything except things held in hands and ammunition
            {
                MWWorld::ContainerStoreIterator slot = store.getSlot (i);

                if (slot!=store.end())
                    value += slot->getClass().getValue (*slot);
            }

            return value;
        }

        case SelectWrapper::Function_PcCrimeLevel:

            return player.getClass().getNpcStats (player).getBounty();

        case SelectWrapper::Function_RankRequirement:
        {
            std::string faction = mActor.getClass().getPrimaryFaction(mActor);
            if (faction.empty())
                return 0;

            int rank = getFactionRank (player, faction);

            if (rank>=9)
                return 0; // max rank

            int result = 0;

            if (hasFactionRankSkillRequirements (player, faction, rank+1))
                result += 1;

            if (hasFactionRankReputationRequirements (player, faction, rank+1))
                result += 2;

            return result;
        }

        case SelectWrapper::Function_Level:

            return mActor.getClass().getCreatureStats (mActor).getLevel();

        case SelectWrapper::Function_PCReputation:

            return player.getClass().getNpcStats (player).getReputation();

        case SelectWrapper::Function_Weather:

            return MWBase::Environment::get().getWorld()->getCurrentWeather();

        case SelectWrapper::Function_Reputation:

            return mActor.getClass().getNpcStats (mActor).getReputation();

        case SelectWrapper::Function_FactionRankDiff:
        {
            std::string faction = mActor.getClass().getPrimaryFaction(mActor);

            if (faction.empty())
                return 0;

            int rank = getFactionRank (player, faction);
            int npcRank = mActor.getClass().getPrimaryFactionRank(mActor);
            return rank-npcRank;
        }

        case SelectWrapper::Function_WerewolfKills:

            return player.getClass().getNpcStats (player).getWerewolfKills();

        case SelectWrapper::Function_RankLow:
        case SelectWrapper::Function_RankHigh:
        {
            bool low = select.getFunction()==SelectWrapper::Function_RankLow;

            std::string factionId = mActor.getClass().getPrimaryFaction(mActor);

            if (factionId.empty())
                return 0;

            int value = 0;

            MWMechanics::NpcStats& playerStats = player.getClass().getNpcStats (player);

            std::map<std::string, int>::const_iterator playerFactionIt = playerStats.getFactionRanks().begin();
            for (; playerFactionIt != playerStats.getFactionRanks().end(); ++playerFactionIt)
            {
                int reaction = MWBase::Environment::get().getDialogueManager()->getFactionReaction(factionId, playerFactionIt->first);
                if (low ? reaction < value : reaction > value)
                    value = reaction;
            }

            return value;
        }

        case SelectWrapper::Function_CreatureTargetted:

            {
                MWWorld::Ptr target;
                mActor.getClass().getCreatureStats(mActor).getAiSequence().getCombatTarget(target);
                if (target)
                {
                    if (target.getClass().isNpc() && target.getClass().getNpcStats(target).isWerewolf())
                        return 2;
                    if (target.getTypeName() == typeid(ESM::Creature).name())
                        return 1;
                }
            }
            return 0;

        default:

            throw std::runtime_error ("unknown integer select function");
    }
}
示例#18
0
    bool AiWander::execute (const MWWorld::Ptr& actor)
    {
        MWBase::World *world = MWBase::Environment::get().getWorld();
        if(mDuration)
        {
            // End package if duration is complete or mid-night hits:
            MWWorld::TimeStamp currentTime = world->getTimeStamp();
            if(currentTime.getHour() >= mStartTime.getHour() + mDuration)
            {
                if(!mRepeat)
                {
                    stopWalking(actor);
                    return true;
                }
                else
                    mStartTime = currentTime;
            }
            else if(int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay())
            {
                if(!mRepeat)
                {
                    stopWalking(actor);
                    return true;
                }
                else
                    mStartTime = currentTime;
            }
        }

        ESM::Position pos = actor.getRefData().getPosition();

        if(!mStoredAvailableNodes)
        {
            mStoredAvailableNodes = true;
            mPathgrid = world->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);

            mCellX = actor.getCell()->mCell->mData.mX;
            mCellY = actor.getCell()->mCell->mData.mY;

            if(!mPathgrid)
                mDistance = 0;
            else if(mPathgrid->mPoints.empty())
                mDistance = 0;

            if(mDistance)
            {
                mXCell = 0;
                mYCell = 0;
                if(actor.getCell()->mCell->isExterior())
                {
                    mXCell = mCellX * ESM::Land::REAL_SIZE;
                    mYCell = mCellY * ESM::Land::REAL_SIZE;
                }

                Ogre::Vector3 npcPos(actor.getRefData().getPosition().pos);
                npcPos[0] = npcPos[0] - mXCell;
                npcPos[1] = npcPos[1] - mYCell;

                for(unsigned int counter = 0; counter < mPathgrid->mPoints.size(); counter++)
                {
                    Ogre::Vector3 nodePos(mPathgrid->mPoints[counter].mX, mPathgrid->mPoints[counter].mY,
                        mPathgrid->mPoints[counter].mZ);
                    if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance)
                        mAllowedNodes.push_back(mPathgrid->mPoints[counter]);
                }
                if(!mAllowedNodes.empty())
                {
                    Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ);
                    float closestNode = npcPos.squaredDistance(firstNodePos);
                    unsigned int index = 0;
                    for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
                    {
                        Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY,
                            mAllowedNodes[counterThree].mZ);
                        float tempDist = npcPos.squaredDistance(nodePos);
                        if(tempDist < closestNode)
                            index = counterThree;
                    }
                    mCurrentNode = mAllowedNodes[index];
                    mAllowedNodes.erase(mAllowedNodes.begin() + index);
                }

                if(mAllowedNodes.empty())
                    mDistance = 0;
            }
        }

        // Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
        if(mDistance && (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY))
            mDistance = 0;

        if(mChooseAction)
        {
            mPlayedIdle = 0;
            unsigned short idleRoll = 0;

            for(unsigned int counter = 0; counter < mIdle.size(); counter++)
            {
                unsigned short idleChance = mIdleChanceMultiplier * mIdle[counter];
                unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / mIdleChanceMultiplier));
                if(randSelect < idleChance && randSelect > idleRoll)
                {
                    mPlayedIdle = counter+2;
                    idleRoll = randSelect;
                }
            }

            if(!mPlayedIdle && mDistance)
            {
                mChooseAction = false;
                mMoveNow = true;
            }
            else
            {
                // Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
                MWWorld::TimeStamp currentTime = world->getTimeStamp();
                mStartTime = currentTime;
                playIdle(actor, mPlayedIdle);
                mChooseAction = false;
                mIdleNow = true;
            }
        }

        if(mIdleNow)
        {
            if(!checkIdle(actor, mPlayedIdle))
            {
                mPlayedIdle = 0;
                mIdleNow = false;
                mChooseAction = true;
            }
        }

        if(mMoveNow && mDistance)
        {
            if(!mPathFinder.isPathConstructed())
            {
                unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size());
                Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ);

                ESM::Pathgrid::Point dest;
                dest.mX = destNodePos[0] + mXCell;
                dest.mY = destNodePos[1] + mYCell;
                dest.mZ = destNodePos[2];

                ESM::Pathgrid::Point start;
                start.mX = pos.pos[0];
                start.mY = pos.pos[1];
                start.mZ = pos.pos[2];

                mPathFinder.buildPath(start, dest, mPathgrid, mXCell, mYCell, false);

                if(mPathFinder.isPathConstructed())
                {
                    // Remove this node as an option and add back the previously used node (stops NPC from picking the same node):
                    ESM::Pathgrid::Point temp = mAllowedNodes[randNode];
                    mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
                    mAllowedNodes.push_back(mCurrentNode);
                    mCurrentNode = temp;

                    mMoveNow = false;
                    mWalking = true;
                }
                // Choose a different node and delete this one from possible nodes because it is uncreachable:
                else
                    mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
            }
        }

        if(mWalking)
        {
            float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
            world->rotateObject(actor, 0, 0, zAngle, false);
            MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;

            if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
            {
                stopWalking(actor);
                mMoveNow = false;
                mWalking = false;
                mChooseAction = true;
            }
        }

        return false;
    }
示例#19
0
    void LevelupDialog::open()
    {
        MWBase::World *world = MWBase::Environment::get().getWorld();
        MWWorld::Ptr player = world->getPlayerPtr();
        MWMechanics::CreatureStats& creatureStats = player.getClass().getCreatureStats(player);
        MWMechanics::NpcStats& pcStats = player.getClass().getNpcStats(player);

        const ESM::NPC *playerData = player.get<ESM::NPC>()->mBase;

        // set class image
        const ESM::Class *cls =
            world->getStore().get<ESM::Class>().find(playerData->mClass);

        if(world->getStore().get<ESM::Class>().isDynamic(cls->mId))
        {
            // Vanilla uses thief.dds for custom classes.
            // Choosing Stealth specialization and Speed/Agility as attributes, if possible. Otherwise fall back to first class found.
            MWWorld::SharedIterator<ESM::Class> it = world->getStore().get<ESM::Class>().begin();
            for(; it != world->getStore().get<ESM::Class>().end(); it++)
            {
                if(it->mData.mIsPlayable && it->mData.mSpecialization == 2 && it->mData.mAttribute[0] == 4 && it->mData.mAttribute[1] == 3)
                    break;
            }
            if (it == world->getStore().get<ESM::Class>().end())
                it = world->getStore().get<ESM::Class>().begin();
            if (it != world->getStore().get<ESM::Class>().end())
                cls = &*it;
        }

        mClassImage->setImageTexture ("textures\\levelup\\" + cls->mId + ".dds");

        int level = creatureStats.getLevel ()+1;
        mLevelText->setCaptionWithReplacing("#{sLevelUpMenu1} " + boost::lexical_cast<std::string>(level));

        std::string levelupdescription;
        if(level > 20)
            levelupdescription=world->getFallback()->getFallbackString("Level_Up_Default");
        else
            levelupdescription=world->getFallback()->getFallbackString("Level_Up_Level"+boost::lexical_cast<std::string>(level));

        mLevelDescription->setCaption (levelupdescription);

        unsigned int availableAttributes = 0;
        for (int i = 0; i < 8; ++i)
        {
            MyGUI::TextBox* text = mAttributeMultipliers[i];
            if (pcStats.getAttribute(i).getBase() < 100)
            {
                mAttributes[i]->setEnabled(true);
                availableAttributes++;

                int mult = pcStats.getLevelupAttributeMultiplier (i);
                text->setCaption(mult <= 1 ? "" : "x" + boost::lexical_cast<std::string>(mult));
            }
            else
            {
                mAttributes[i]->setEnabled(false);

                text->setCaption("");
            }
        }

        mCoinCount = std::min(sMaxCoins, availableAttributes);

        for (unsigned int i = 0; i < sMaxCoins; i++)
        {
            if (i < mCoinCount)
                mCoins[i]->attachToWidget(mCoinBox);
            else
                mCoins[i]->detachFromWidget();
        }

        mSpentAttributes.clear();
        resetCoins();

        setAttributeValues();

        center();
    }
示例#20
0
void TradeItemModel::update()
{
    mSourceModel->update();

    int services = 0;
    if (!mMerchant.isEmpty())
        services = mMerchant.getClass().getServices(mMerchant);

    mItems.clear();
    // add regular items
    for (size_t i=0; i<mSourceModel->getItemCount(); ++i)
    {
        ItemStack item = mSourceModel->getItem(i);
        if(!mMerchant.isEmpty())
        {
            MWWorld::Ptr base = item.mBase;
            if(Misc::StringUtils::ciEqual(base.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId))
                continue;
            if(!base.getClass().canSell(base, services))
                continue;

            // Bound items may not be bought
            if (item.mBase.getCellRef().getRefId().size() > 6
                    && item.mBase.getCellRef().getRefId().substr(0,6) == "bound_")
            {
                continue;
            }

            // don't show equipped items
            if(mMerchant.getClass().hasInventoryStore(mMerchant))
            {
                bool isEquipped = false;
                MWWorld::InventoryStore& store = mMerchant.getClass().getInventoryStore(mMerchant);
                for (int slot=0; slot<MWWorld::InventoryStore::Slots; ++slot)
                {
                    MWWorld::ContainerStoreIterator equipped = store.getSlot(slot);
                    if (equipped == store.end())
                        continue;
                    if (*equipped == base)
                        isEquipped = true;
                }
                if (isEquipped)
                    continue;
            }
        }

        // don't show items that we borrowed to someone else
        std::vector<ItemStack>::iterator it = mBorrowedFromUs.begin();
        for (; it != mBorrowedFromUs.end(); ++it)
        {
            if (it->mBase == item.mBase)
            {
                if (item.mCount < it->mCount)
                    throw std::runtime_error("Lent more items than present");
                item.mCount -= it->mCount;
            }
        }

        if (item.mCount > 0)
            mItems.push_back(item);
    }

    // add items borrowed to us
    std::vector<ItemStack>::iterator it = mBorrowedToUs.begin();
    for (; it != mBorrowedToUs.end(); ++it)
    {
        ItemStack item = *it;
        item.mType = ItemStack::Type_Barter;
        mItems.push_back(item);
    }
}
示例#21
0
AiPursue::AiPursue(const MWWorld::Ptr& actor)
    : mTargetActorId(actor.getClass().getCreatureStats(actor).getActorId())
{
}
示例#22
0
 int InterpreterContext::getPCBounty() const
 {
     MWBase::World *world = MWBase::Environment::get().getWorld();
     MWWorld::Ptr player = world->getPlayerPtr();
     return player.getClass().getNpcStats (player).getBounty();
 }
示例#23
0
 virtual void execute (Interpreter::Runtime& runtime)
 {
     MWWorld::Ptr actor = R()(runtime);
     MWMechanics::CreatureStats& creatureStats = actor.getClass().getCreatureStats(actor);
     creatureStats.getAiSequence().stopCombat();
 }
示例#24
0
 void InterpreterContext::executeActivation(MWWorld::Ptr ptr, MWWorld::Ptr actor)
 {
     boost::shared_ptr<MWWorld::Action> action = (ptr.getClass().activate(ptr, actor));
     action->execute (actor);
 }
示例#25
0
 bool InterpreterContext::isDisabled (const std::string& id) const
 {
     const MWWorld::Ptr ref = getReference (id, false);
     return !ref.getRefData().isEnabled();
 }
示例#26
0
文件: repair.cpp 项目: Allxere/openmw
void Repair::updateRepairView()
{
    MWWorld::LiveCellRef<ESM::Repair> *ref =
        mRepair.getTool().get<ESM::Repair>();

    int uses = mRepair.getTool().getClass().getItemHealth(mRepair.getTool());

    float quality = ref->mBase->mData.mQuality;

    std::stringstream qualityStr;
    qualityStr << std::setprecision(3) << quality;

    mUsesLabel->setCaptionWithReplacing("#{sUses} " + boost::lexical_cast<std::string>(uses));
    mQualityLabel->setCaptionWithReplacing("#{sQuality} " + qualityStr.str());

    bool toolBoxVisible = (mRepair.getTool().getRefData().getCount() != 0);
    mToolBox->setVisible(toolBoxVisible);

    bool toolBoxWasVisible = (mRepairBox->getPosition().top != mToolBox->getPosition().top);

    if (toolBoxVisible && !toolBoxWasVisible)
    {
        // shrink
        mRepairBox->setPosition(mRepairBox->getPosition() + MyGUI::IntPoint(0,mToolBox->getSize().height));
        mRepairBox->setSize(mRepairBox->getSize() - MyGUI::IntSize(0,mToolBox->getSize().height));
    }
    else if (!toolBoxVisible && toolBoxWasVisible)
    {
        // expand
        mRepairBox->setPosition(MyGUI::IntPoint (mRepairBox->getPosition().left, mToolBox->getPosition().top));
        mRepairBox->setSize(mRepairBox->getSize() + MyGUI::IntSize(0,mToolBox->getSize().height));
    }

    while (mRepairView->getChildCount())
        MyGUI::Gui::getInstance().destroyWidget(mRepairView->getChildAt(0));

    int currentY = 0;

    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
    MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
    int categories = MWWorld::ContainerStore::Type_Weapon | MWWorld::ContainerStore::Type_Armor;
    for (MWWorld::ContainerStoreIterator iter (store.begin(categories));
         iter!=store.end(); ++iter)
    {
        if (iter->getClass().hasItemHealth(*iter))
        {
            int maxDurability = iter->getClass().getItemMaxHealth(*iter);
            int durability = iter->getClass().getItemHealth(*iter);
            if (maxDurability == durability)
                continue;

            MyGUI::TextBox* text = mRepairView->createWidget<MyGUI::TextBox> (
                        "SandText", MyGUI::IntCoord(8, currentY, mRepairView->getWidth()-8, 18), MyGUI::Align::Default);
            text->setCaption(iter->getClass().getName(*iter));
            text->setNeedMouseFocus(false);
            currentY += 19;

            ItemWidget* icon = mRepairView->createWidget<ItemWidget> (
                        "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default);
            icon->setItem(*iter);
            icon->setUserString("ToolTipType", "ItemPtr");
            icon->setUserData(*iter);
            icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Repair::onRepairItem);
            icon->eventMouseWheel += MyGUI::newDelegate(this, &Repair::onMouseWheel);

            Widgets::MWDynamicStatPtr chargeWidget = mRepairView->createWidget<Widgets::MWDynamicStat>
                    ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default);
            chargeWidget->setValue(durability, maxDurability);
            chargeWidget->setNeedMouseFocus(false);

            currentY += 32 + 4;
        }
    }
    // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
    mRepairView->setVisibleVScroll(false);
    mRepairView->setCanvasSize (MyGUI::IntSize(mRepairView->getWidth(), std::max(mRepairView->getHeight(), currentY)));
    mRepairView->setVisibleVScroll(true);
}
示例#27
0
 bool SpellBuyingWindow::playerHasSpell(const std::string &id)
 {
     MWWorld::Ptr player = MWMechanics::getPlayer();
     return player.getClass().getCreatureStats(player).getSpells().hasSpell(id);
 }
示例#28
0
        virtual bool operator()(const MWWorld::Ptr& ptr)
        {
            ptr.getClass().getModelsToPreload(ptr, mOut);

            return true;
        }
示例#29
0
void Recharge::updateView()
{
    MWWorld::Ptr gem = *mGemIcon->getUserData<MWWorld::Ptr>();

    std::string soul = gem.getCellRef().getSoul();
    const ESM::Creature *creature = MWBase::Environment::get().getWorld()->getStore().get<ESM::Creature>().find(soul);

    mChargeLabel->setCaptionWithReplacing("#{sCharges} " + MyGUI::utility::toString(creature->mData.mSoul));

    bool toolBoxVisible = (gem.getRefData().getCount() != 0);
    mGemBox->setVisible(toolBoxVisible);

    bool toolBoxWasVisible = (mBox->getPosition().top != mGemBox->getPosition().top);

    if (toolBoxVisible && !toolBoxWasVisible)
    {
        // shrink
        mBox->setPosition(mBox->getPosition() + MyGUI::IntPoint(0, mGemBox->getSize().height));
        mBox->setSize(mBox->getSize() - MyGUI::IntSize(0,mGemBox->getSize().height));
    }
    else if (!toolBoxVisible && toolBoxWasVisible)
    {
        // expand
        mBox->setPosition(MyGUI::IntPoint (mBox->getPosition().left, mGemBox->getPosition().top));
        mBox->setSize(mBox->getSize() + MyGUI::IntSize(0,mGemBox->getSize().height));
    }

    while (mView->getChildCount())
        MyGUI::Gui::getInstance().destroyWidget(mView->getChildAt(0));

    int currentY = 0;

    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
    MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
    for (MWWorld::ContainerStoreIterator iter (store.begin());
         iter!=store.end(); ++iter)
    {
        std::string enchantmentName = iter->getClass().getEnchantment(*iter);
        if (enchantmentName.empty())
            continue;
        const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(enchantmentName);
        if (iter->getCellRef().getEnchantmentCharge() >= enchantment->mData.mCharge
                || iter->getCellRef().getEnchantmentCharge() == -1)
            continue;

        MyGUI::TextBox* text = mView->createWidget<MyGUI::TextBox> (
                    "SandText", MyGUI::IntCoord(8, currentY, mView->getWidth()-8, 18), MyGUI::Align::Default);
        text->setCaption(iter->getClass().getName(*iter));
        text->setNeedMouseFocus(false);
        currentY += 19;

        ItemWidget* icon = mView->createWidget<ItemWidget> (
                    "MW_ItemIconSmall", MyGUI::IntCoord(16, currentY, 32, 32), MyGUI::Align::Default);
        icon->setItem(*iter);
        icon->setUserString("ToolTipType", "ItemPtr");
        icon->setUserData(*iter);
        icon->eventMouseButtonClick += MyGUI::newDelegate(this, &Recharge::onItemClicked);
        icon->eventMouseWheel += MyGUI::newDelegate(this, &Recharge::onMouseWheel);

        Widgets::MWDynamicStatPtr chargeWidget = mView->createWidget<Widgets::MWDynamicStat>
                ("MW_ChargeBar", MyGUI::IntCoord(72, currentY+2, 199, 20), MyGUI::Align::Default);
        chargeWidget->setValue(static_cast<int>(iter->getCellRef().getEnchantmentCharge()), enchantment->mData.mCharge);
        chargeWidget->setNeedMouseFocus(false);

        currentY += 32 + 4;
    }

    // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
    mView->setVisibleVScroll(false);
    mView->setCanvasSize (MyGUI::IntSize(mView->getWidth(), std::max(mView->getHeight(), currentY)));
    mView->setVisibleVScroll(true);
}
示例#30
0
 void ActionPotion::prepare(const MWWorld::Ptr &actor)
 {
     actor.getClass().apply(actor, mPotion.getCellRef().getRefId(), actor);
     actor.getClass().getContainerStore(actor).remove(mPotion, 1, actor);
 }