Esempio n. 1
0
boost::shared_ptr<MWWorld::Action> Container::activate (const MWWorld::Ptr& ptr,
        const MWWorld::Ptr& actor) const
{
    if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
        return boost::shared_ptr<MWWorld::Action> (new MWWorld::NullAction ());

    if(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
    {
        const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
        const ESM::Sound *sound = store.get<ESM::Sound>().searchRandom("WolfContainer");

        boost::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction("#{sWerewolfRefusal}"));
        if(sound) action->setSound(sound->mId);

        return action;
    }

    const std::string lockedSound = "LockedChest";
    const std::string trapActivationSound = "Disarm Trap Fail";

    MWWorld::Ptr player = MWBase::Environment::get().getWorld ()->getPlayerPtr();
    MWWorld::InventoryStore& invStore = player.getClass().getInventoryStore(player);

    bool needKey = ptr.getCellRef().getLockLevel() > 0;
    bool hasKey = false;
    std::string keyName;

    // make key id lowercase
    std::string keyId = ptr.getCellRef().getKey();
    Misc::StringUtils::toLower(keyId);
    for (MWWorld::ContainerStoreIterator it = invStore.begin(); it != invStore.end(); ++it)
    {
        std::string refId = it->getCellRef().getRefId();
        Misc::StringUtils::toLower(refId);
        if (refId == keyId)
        {
            hasKey = true;
            keyName = it->getClass().getName(*it);
        }
    }

    if (needKey && hasKey)
    {
        MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}");
        unlock(ptr);
        // using a key disarms the trap
        ptr.getCellRef().setTrap("");
    }


    if (!needKey || hasKey)
    {
        if(ptr.getCellRef().getTrap().empty())
        {
            boost::shared_ptr<MWWorld::Action> action (new MWWorld::ActionOpen(ptr));
            return action;
        }
        else
        {
            // Activate trap
            boost::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTrap(actor, ptr.getCellRef().getTrap(), ptr));
            action->setSound(trapActivationSound);
            return action;
        }
    }
    else
    {
        boost::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction);
        action->setSound(lockedSound);
        return action;
    }
}
Esempio n. 2
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 = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(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;
    }
Esempio n. 3
0
                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    runtime.push (ptr.getClass().getNpcStats (ptr).getReputation ());
                }
Esempio n. 4
0
    bool ProjectileManager::readRecord(ESM::ESMReader &reader, uint32_t type)
    {
        if (type == ESM::REC_PROJ)
        {
            ESM::ProjectileState esm;
            esm.load(reader);

            ProjectileState state;
            state.mActorId = esm.mActorId;
            state.mBowId = esm.mBowId;
            state.mVelocity = esm.mVelocity;
            state.mId = esm.mId;
            state.mAttackStrength = esm.mAttackStrength;

            std::string model;
            try
            {
                MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), esm.mId);
                MWWorld::Ptr ptr = ref.getPtr();
                model = ptr.getClass().getModel(ptr);
            }
            catch(...)
            {
                return true;
            }

            createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), false);

            mProjectiles.push_back(state);
            return true;
        }
        else if (type == ESM::REC_MPRJ)
        {
            ESM::MagicBoltState esm;
            esm.load(reader);

            MagicBoltState state;
            state.mSourceName = esm.mSourceName;
            state.mId = esm.mId;
            state.mSpellId = esm.mSpellId;
            state.mActorId = esm.mActorId;
            state.mSpeed = esm.mSpeed;
            state.mStack = esm.mStack;
            state.mEffects = esm.mEffects;

            std::string model;
            try
            {
                MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), esm.mId);
                MWWorld::Ptr ptr = ref.getPtr();
                model = ptr.getClass().getModel(ptr);
            }
            catch(...)
            {
                return true;
            }

            createModel(state, model, osg::Vec3f(esm.mPosition), osg::Quat(esm.mOrientation), true);

            MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
            state.mSound = sndMgr->playSound3D(esm.mPosition, esm.mSound, 1.0f, 1.0f,
                                               MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
            state.mSoundId = esm.mSound;

            mMagicBolts.push_back(state);
            return true;
        }

        return false;
    }
Esempio n. 5
0
 void ActionEnchantedItem::prepare(const MWWorld::Ptr &actor)
 {
     actor.getClass().getCreatureStats(actor).getSpells().setSelectedSpell(std::string());
     actor.getClass().getInventoryStore(actor).setSelectedEnchantItem(mItem);
     actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Spell);
 }
Esempio n. 6
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");
    }
}
Esempio n. 7
0
bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
{
    try
    {
        float frametime = std::min(evt.timeSinceLastFrame, 0.2f);

        mEnvironment.setFrameDuration (frametime);

        // update input
        MWBase::Environment::get().getInputManager()->update(frametime, false);

        // sound
        if (mUseSound)
            MWBase::Environment::get().getSoundManager()->update(frametime);

        // GUI active? Most game processing will be paused, but scripts still run.
        bool guiActive = MWBase::Environment::get().getWindowManager()->isGuiMode();

        // Main menu opened? Then scripts are also paused.
        bool paused = MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu);

        // update game state
        MWBase::Environment::get().getStateManager()->update (frametime);

        if (MWBase::Environment::get().getStateManager()->getState()==
            MWBase::StateManager::State_Running)
        {
            if (!paused)
            {
                // global scripts
                MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();

                // local scripts
                executeLocalScripts();

                MWBase::Environment::get().getWorld()->markCellAsUnchanged();
            }

            if (!guiActive)
                MWBase::Environment::get().getWorld()->advanceTime(
                    frametime*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
        }


        // update actors
        if (MWBase::Environment::get().getStateManager()->getState()!=
            MWBase::StateManager::State_NoGame)
        {
            MWBase::Environment::get().getMechanicsManager()->update(frametime,
                guiActive);
        }

        if (MWBase::Environment::get().getStateManager()->getState()==
            MWBase::StateManager::State_Running)
        {
            MWWorld::Ptr player = mEnvironment.getWorld()->getPlayerPtr();
            if(!guiActive && player.getClass().getCreatureStats(player).isDead())
                MWBase::Environment::get().getStateManager()->endGame();
        }

        // update world
        if (MWBase::Environment::get().getStateManager()->getState()!=
            MWBase::StateManager::State_NoGame)
        {
            MWBase::Environment::get().getWorld()->update(frametime, guiActive);
        }

        // update GUI
        MWBase::Environment::get().getWindowManager()->onFrame(frametime);
        if (MWBase::Environment::get().getStateManager()->getState()!=
            MWBase::StateManager::State_NoGame)
        {
            Ogre::RenderWindow* window = mOgre->getWindow();
            unsigned int tri, batch;
            MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch);
            MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch);

            MWBase::Environment::get().getWindowManager()->update();
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "Error in framelistener: " << e.what() << std::endl;
    }

    return true;
}
Esempio n. 8
0
    void TradeWindow::onOfferButtonClicked(MyGUI::Widget* _sender)
    {
        TradeItemModel* playerItemModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();

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

        // were there any items traded at all?
        std::vector<ItemStack> playerBought = playerItemModel->getItemsBorrowedToUs();
        std::vector<ItemStack> merchantBought = mTradeModel->getItemsBorrowedToUs();
        if (playerBought.empty() && merchantBought.empty())
        {
            // user notification
            MWBase::Environment::get().getWindowManager()->
                messageBox("#{sBarterDialog11}");
            return;
        }

        MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
        int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);

        // check if the player can afford this
        if (mCurrentBalance < 0 && playerGold < std::abs(mCurrentBalance))
        {
            // user notification
            MWBase::Environment::get().getWindowManager()->
                messageBox("#{sBarterDialog1}");
            return;
        }

        // check if the merchant can afford this
        if (mCurrentBalance > 0 && getMerchantGold() < mCurrentBalance)
        {
            // user notification
            MWBase::Environment::get().getWindowManager()->
                messageBox("#{sBarterDialog2}");
            return;
        }

        // check if the player is attempting to sell back an item stolen from this actor
        for (std::vector<ItemStack>::iterator it = merchantBought.begin(); it != merchantBought.end(); ++it)
        {
            if (Misc::StringUtils::ciEqual(it->mBase.getCellRef().getOwner(), mPtr.getCellRef().getRefId()))
            {
                std::string msg = gmst.find("sNotifyMessage49")->getString();
                if (msg.find("%s") != std::string::npos)
                    msg.replace(msg.find("%s"), 2, it->mBase.getClass().getName(it->mBase));
                MWBase::Environment::get().getWindowManager()->messageBox(msg);
                MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
                MWBase::Environment::get().getMechanicsManager()->reportCrime(player, mPtr, MWBase::MechanicsManager::OT_Theft,
                                                                              it->mBase.getClass().getValue(it->mBase)
                                                                              * it->mCount);
                onCancelButtonClicked(mCancelButton);
                MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
                return;
            }
        }

        if(mCurrentBalance > mCurrentMerchantOffer)
        {
            //if npc is a creature: reject (no haggle)
            if (mPtr.getTypeName() != typeid(ESM::NPC).name())
            {
                MWBase::Environment::get().getWindowManager()->
                    messageBox("#{sNotifyMessage9}");
                return;
            }

            int a = abs(mCurrentMerchantOffer);
            int b = abs(mCurrentBalance);
            int d = 0;
            if (mCurrentBalance<0)
                d = int(100 * (a - b) / a);
            else
                d = int(100 * (b - a) / a);

            float clampedDisposition = std::max<int>(0,std::min<int>(int(MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mPtr)
                + MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange()),100));

            const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
            const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player);

            float a1 = std::min(player.getClass().getSkill(player, ESM::Skill::Mercantile), 100);
            float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
            float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
            float d1 = std::min(mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile), 100);
            float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
            float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);

            float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm();
            float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm();
            float x = gmst.find("fBargainOfferMulti")->getFloat() * d + gmst.find("fBargainOfferBase")->getFloat();
            if (mCurrentBalance<0)
                x += abs(int(pcTerm - npcTerm));
            else
                x += abs(int(npcTerm - pcTerm));

            int roll = std::rand()%100 + 1;
            if(roll > x) //trade refused
            {
                MWBase::Environment::get().getWindowManager()->
                    messageBox("#{sNotifyMessage9}");

                int iBarterFailDisposition = gmst.find("iBarterFailDisposition")->getInt();
                if (mPtr.getClass().isNpc())
                    MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterFailDisposition);
                return;
            }

            //skill use!
            player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0);
        }

        int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();
        if (mPtr.getClass().isNpc())
            MWBase::Environment::get().getDialogueManager()->applyDispositionChange(iBarterSuccessDisposition);

        // make the item transfer
        mTradeModel->transferItems();
        playerItemModel->transferItems();

        // transfer the gold
        if (mCurrentBalance != 0)
        {
            addOrRemoveGold(mCurrentBalance, player);
            mPtr.getClass().getCreatureStats(mPtr).setGoldPool(
                        mPtr.getClass().getCreatureStats(mPtr).getGoldPool() - mCurrentBalance );
        }

        MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse(
            MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString());

        std::string sound = "Item Gold Up";
        MWBase::Environment::get().getSoundManager()->playSound (sound, 1.0, 1.0);

        MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Barter);
    }
Esempio n. 9
0
    void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem)
    {
        int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, item.getClass().getValue(item) * count, !soldItem);

        mCurrentBalance -= diff;
        mCurrentMerchantOffer -= diff;

        updateLabels();
    }
Esempio n. 10
0
bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) const
{
    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();

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

            return false;

        case SelectWrapper::Function_NotId:

            return !Misc::StringUtils::ciEqual(MWWorld::Class::get (mActor).getId (mActor), select.getName());

        case SelectWrapper::Function_NotFaction:

            return !Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mFaction, 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(mActor.getCell()->getCell()->mName, select.getName());

        case SelectWrapper::Function_NotLocal:
        {
            std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor);

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

            const ESM::Script *script =
                MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptName);

            std::string name = select.getName();

            int i = 0;
            for (; i < static_cast<int> (script->mVarNames.size()); ++i)
                if (Misc::StringUtils::ciEqual(script->mVarNames[i], name))
                    break;

            if (i >= static_cast<int> (script->mVarNames.size()))
                return true; // script does not have a variable of this name

            return false;
        }

        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 MWWorld::Class::get (mActor).getNpcStats (mActor).isSameFaction (
                MWWorld::Class::get (player).getNpcStats (player));

        case SelectWrapper::Function_PcCommonDisease:

            return MWWorld::Class::get (player).getCreatureStats (player).hasCommonDisease();

        case SelectWrapper::Function_PcBlightDisease:

            return MWWorld::Class::get (player).getCreatureStats (player).hasBlightDisease();

        case SelectWrapper::Function_PcCorprus:

            return MWWorld::Class::get (player).getCreatureStats (player).
                getMagicEffects().get (ESM::MagicEffect::Corprus).mMagnitude!=0;

        case SelectWrapper::Function_PcExpelled:
        {
            if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty())
                return false;

            std::string faction =
                MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first;

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

        case SelectWrapper::Function_PcVampire:

            return MWWorld::Class::get (player).getCreatureStats(player).getMagicEffects().
                    get(ESM::MagicEffect::Vampirism).mMagnitude > 0;

        case SelectWrapper::Function_TalkedToPc:

            return mTalkedToPlayer;

        case SelectWrapper::Function_Alarmed:

            return MWWorld::Class::get (mActor).getCreatureStats (mActor).isAlarmed();

        case SelectWrapper::Function_Detected:

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

        case SelectWrapper::Function_Attacked:

            return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAttacked();

        case SelectWrapper::Function_ShouldAttack:

            return MWWorld::Class::get (mActor).getCreatureStats (mActor).isHostile();

        case SelectWrapper::Function_CreatureTargetted:

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

        case SelectWrapper::Function_Werewolf:

            return MWWorld::Class::get (mActor).getNpcStats (mActor).isWerewolf();

        default:

            throw std::runtime_error ("unknown boolean select function");
    }
}
Esempio n. 11
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.getClass().getName (player);
        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;

        int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
        Ogre::Image screenshot;
        world.screenshot(screenshot, screenshotW, screenshotH);
        Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
        profile.mScreenshot.resize(encoded->size());
        encoded->read(&profile.mScreenshot[0], encoded->size());

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

        boost::filesystem::ofstream stream (slot->mPath, std::ios::binary);

        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::Header::CurrentFormat);
        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();
        writer.setRecordCount (recordCount);

        writer.save (stream);

        Loading::Listener& listener = *MWBase::Environment::get().getWindowManager()->getLoadingScreen();
        listener.setProgressRange(recordCount);
        listener.setLabel("#{sNotifyMessage4}");

        Loading::ScopedLoad load(&listener);

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

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

        // 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");

        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()->messageBox(error.str(), buttons);

        // If no file was written, clean up the slot
        if (slot && !boost::filesystem::exists(slot->mPath))
            getCurrentCharacter()->deleteSlot(slot);
    }
}
Esempio n. 12
0
    void EnchantingDialog::onBuyButtonClicked(MyGUI::Widget* sender)
    {
        if (mEffects.size() <= 0)
        {
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu11}");
            return;
        }

        if (mName->getCaption ().empty())
        {
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage10}");
            return;
        }

        if (mEnchanting.soulEmpty())
        {
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage52}");
            return;
        }

        if (mEnchanting.itemEmpty())
        {
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage11}");
            return;
        }

        if (mEnchanting.getEnchantPoints() > mEnchanting.getMaxEnchantValue())
        {
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage29}");
            return;
        }

        mEnchanting.setNewItemName(mName->getCaption());
        mEnchanting.setEffect(mEffectList);

        MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
        int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
        if (mEnchanting.getEnchantPrice() > playerGold)
        {
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage18}");
            return;
        }

        // check if the player is attempting to use a soulstone or item that was stolen from this actor
        if (mPtr != player)
        {
            for (int i=0; i<2; ++i)
            {
                MWWorld::Ptr item = (i == 0) ? mEnchanting.getOldItem() : mEnchanting.getGem();
                if (Misc::StringUtils::ciEqual(item.getCellRef().getOwner(), mPtr.getCellRef().getRefId()))
                {
                    std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->getString();
                    if (msg.find("%s") != std::string::npos)
                        msg.replace(msg.find("%s"), 2, item.getClass().getName(item));
                    MWBase::Environment::get().getWindowManager()->messageBox(msg);
                    MWBase::Environment::get().getDialogueManager()->say(mPtr, "Thief");
                    MWBase::Environment::get().getMechanicsManager()->reportCrime(player, mPtr, MWBase::MechanicsManager::OT_Theft,
                                                                                  item.getClass().getValue(item));
                    MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
                    MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Dialogue);
                    return;
                }
            }
        }

        int result = mEnchanting.create();

        if(result==1)
        {
            MWBase::Environment::get().getSoundManager()->playSound("enchant success", 1.f, 1.f);
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu12}");
        }
        else
        {
            MWBase::Environment::get().getSoundManager()->playSound("enchant fail", 1.f, 1.f);
            MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage34}");
        }

        MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
    }
Esempio n. 13
0
bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration)
{
    //Update various Timers
    mTimer += duration; //Update timer
    mStuckTimer += duration;   //Update stuck timer

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

    /// Stops the actor when it gets too close to a unloaded cell
    {
        MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
        const ESM::Cell *cell = actor.getCell()->getCell();
        Movement &movement = actor.getClass().getMovementSettings(actor);

        //Ensure pursuer doesn't leave loaded cells
        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;
            }
        }
    }

    //Start position
    ESM::Pathgrid::Point start = pos.pos;

    //***********************
    /// Checks if you can't get to the end position at all, adds end position to end of path
    /// Rebuilds path every quarter of a second, in case the target has moved
    //***********************
    if(mTimer > 0.25)
    {
        if(distance(mPrevDest, dest) > 10) { //Only rebuild path if it's moved
            mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved
            mPrevDest = dest;
        }

        if(!mPathFinder.getPath().empty()) //Path has points in it
        {
            ESM::Pathgrid::Point lastPos = mPathFinder.getPath().back(); //Get the end of the proposed path

            if(distance(dest, lastPos) > 100) //End of the path is far from the destination
                mPathFinder.addPointToPath(dest); //Adds the final destination to the path, to try to get to where you want to go
        }

        mTimer = 0;
    }

    //************************
    /// Checks if you aren't moving; attempts to unstick you
    //************************
    if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) //Path finished?
        return true;
    else if(mStuckTimer>0.5) //Every half second see if we need to take action to avoid something
    {
/// TODO (tluppi#1#): Use ObstacleCheck here. Not working for some reason
        //if(mObstacleCheck.check(actor, duration)) {
        if(distance(start, mStuckPos.pos[0], mStuckPos.pos[1], mStuckPos.pos[2]) < 10 && distance(dest, start) > 20) { //Actually stuck, and far enough away from destination to care
            // first check if we're walking into a door
            MWWorld::Ptr door = getNearbyDoor(actor);
            if(door != MWWorld::Ptr()) // NOTE: checks interior cells only
            {
                if(door.getCellRef().getTrap().empty() && mLastDoorChecked != door) { //Open the door if untrapped
                    door.getClass().activate(door, actor).get()->execute(actor);
                    mLastDoorChecked = door;
                }
            }
            else // probably walking into another NPC
            {
                // TODO: diagonal should have same animation as walk forward
                //       but doesn't seem to do that?
                actor.getClass().getMovementSettings(actor).mPosition[0] = 1;
                actor.getClass().getMovementSettings(actor).mPosition[1] = 0.1f;
                // change the angle a bit, too
                zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0] + 1, pos.pos[1])));
            }
        }
        else { //Not stuck, so reset things
            mStuckTimer = 0;
            mStuckPos = pos;
            mLastDoorChecked = MWWorld::Ptr(); //Resets it, in case he gets stuck behind the door again
            actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward
        }
    }
    else {
        actor.getClass().getMovementSettings(actor).mPosition[1] = 1; //Just run forward the rest of the time
    }

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

    return false;
}
Esempio n. 14
0
void MerchantRepair::startRepair(const MWWorld::Ptr &actor)
{
    mActor = actor;

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

    int currentY = 0;

    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
    int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);

    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;

            int basePrice = iter->getClass().getValue(*iter);
            float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
                    .find("fRepairMult")->getFloat();

            float p = std::max(1, basePrice);
            float r = std::max(1, static_cast<int>(maxDurability / p));

            int x = ((maxDurability - durability) / r);
            x = (fRepairMult * x);

            int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mActor, x, true);


            std::string name = iter->getClass().getName(*iter)
                    + " - " + boost::lexical_cast<std::string>(price)
                    + MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
                    .find("sgp")->getString();


            MyGUI::Button* button =
                mList->createWidget<MyGUI::Button>("SandTextButton",
                    0,
                    currentY,
                    0,
                    18,
                    MyGUI::Align::Default
                );

            currentY += 18;

            button->setEnabled(price<=playerGold);
            button->setUserString("Price", boost::lexical_cast<std::string>(price));
            button->setUserData(*iter);
            button->setCaptionWithReplacing(name);
            button->setSize(button->getTextSize().width,18);
            button->eventMouseWheel += MyGUI::newDelegate(this, &MerchantRepair::onMouseWheel);
            button->setUserString("ToolTipType", "ItemPtr");
            button->eventMouseButtonClick += MyGUI::newDelegate(this, &MerchantRepair::onRepairButtonClick);
        }
    }
    // Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
    mList->setVisibleVScroll(false);
    mList->setCanvasSize (MyGUI::IntSize(mList->getWidth(), std::max(mList->getHeight(), currentY)));
    mList->setVisibleVScroll(true);

    mGoldLabel->setCaptionWithReplacing("#{sGold}: "
        + boost::lexical_cast<std::string>(playerGold));
}
Esempio n. 15
0
    void ActionEquip::executeImp (const Ptr& actor)
    {
        MWWorld::Ptr object = getTarget();
        MWWorld::InventoryStore& invStore = actor.getClass().getInventoryStore(actor);

        if (object.getClass().hasItemHealth(object) && object.getCellRef().getCharge() == 0)
        {
            if (actor == MWMechanics::getPlayer())
                MWBase::Environment::get().getWindowManager()->messageBox("#{sInventoryMessage1}");

            return;
        }

        if (!mForce)
        {
            std::pair <int, std::string> result = object.getClass().canBeEquipped (object, actor);

            // display error message if the player tried to equip something
            if (!result.second.empty() && actor == MWMechanics::getPlayer())
                MWBase::Environment::get().getWindowManager()->messageBox(result.second);

            switch(result.first)
            {
                case 0:
                    return;
                default:
                    break;
            }
        }

        // slots that this item can be equipped in
        std::pair<std::vector<int>, bool> slots_ = getTarget().getClass().getEquipmentSlots(getTarget());
        if (slots_.first.empty())
            return;

        // retrieve ContainerStoreIterator to the item
        MWWorld::ContainerStoreIterator it = invStore.begin();
        for (; it != invStore.end(); ++it)
        {
            if (*it == object)
            {
                break;
            }
        }

        if (it == invStore.end())
        {
            std::stringstream error;
            error << "ActionEquip can't find item " << object.getCellRef().getRefId();
            throw std::runtime_error(error.str());
        }

        // equip the item in the first free slot
        std::vector<int>::const_iterator slot=slots_.first.begin();
        for (;slot!=slots_.first.end(); ++slot)
        {
            // if the item is equipped already, nothing to do
            if (invStore.getSlot(*slot) == it)
                return;

            if (invStore.getSlot(*slot) == invStore.end())
            {
                // slot is not occupied
                invStore.equip(*slot, it, actor);
                break;
            }
        }

        // all slots are occupied -> cycle
        // move all slots one towards begin(), then equip the item in the slot that is now free
        if (slot == slots_.first.end())
        {
            for (slot=slots_.first.begin();slot!=slots_.first.end(); ++slot)
            {
                invStore.unequipSlot(*slot, actor);
                if (slot+1 != slots_.first.end())
                    invStore.equip(*slot, invStore.getSlot(*(slot+1)), actor);
                else
                    invStore.equip(*slot, it, actor);
            }
        }
    }
Esempio n. 16
0
    void CharacterCreation::spawnDialog(const char id)
    {
        switch (id)
        {
            case GM_Name:
                MWBase::Environment::get().getWindowManager()->removeDialog(mNameDialog);
                mNameDialog = 0;
                mNameDialog = new TextInputDialog();
                mNameDialog->setTextLabel(MWBase::Environment::get().getWindowManager()->getGameSettingString("sName", "Name"));
                mNameDialog->setTextInput(mPlayerName);
                mNameDialog->setNextButtonShow(mCreationStage >= CSE_NameChosen);
                mNameDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onNameDialogDone);
                mNameDialog->setVisible(true);
                break;

            case GM_Race:
                MWBase::Environment::get().getWindowManager()->removeDialog(mRaceDialog);
                mRaceDialog = 0;
                mRaceDialog = new RaceDialog();
                mRaceDialog->setNextButtonShow(mCreationStage >= CSE_RaceChosen);
                mRaceDialog->setRaceId(mPlayerRaceId);
                mRaceDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogDone);
                mRaceDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onRaceDialogBack);
                mRaceDialog->setVisible(true);
                if (mCreationStage < CSE_NameChosen)
                    mCreationStage = CSE_NameChosen;
                break;

            case GM_Class:
                MWBase::Environment::get().getWindowManager()->removeDialog(mClassChoiceDialog);
                mClassChoiceDialog = 0;
                mClassChoiceDialog = new ClassChoiceDialog();
                mClassChoiceDialog->eventButtonSelected += MyGUI::newDelegate(this, &CharacterCreation::onClassChoice);
                mClassChoiceDialog->setVisible(true);
                if (mCreationStage < CSE_RaceChosen)
                    mCreationStage = CSE_RaceChosen;
                break;

            case GM_ClassPick:
                MWBase::Environment::get().getWindowManager()->removeDialog(mPickClassDialog);
                mPickClassDialog = 0;
                mPickClassDialog = new PickClassDialog();
                mPickClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
                mPickClassDialog->setClassId(mPlayerClass.mName);
                mPickClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogDone);
                mPickClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onPickClassDialogBack);
                mPickClassDialog->setVisible(true);
                if (mCreationStage < CSE_RaceChosen)
                    mCreationStage = CSE_RaceChosen;
                break;

            case GM_Birth:
                MWBase::Environment::get().getWindowManager()->removeDialog(mBirthSignDialog);
                mBirthSignDialog = 0;
                mBirthSignDialog = new BirthDialog();
                mBirthSignDialog->setNextButtonShow(mCreationStage >= CSE_BirthSignChosen);
                mBirthSignDialog->setBirthId(mPlayerBirthSignId);
                mBirthSignDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogDone);
                mBirthSignDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onBirthSignDialogBack);
                mBirthSignDialog->setVisible(true);
                if (mCreationStage < CSE_ClassChosen)
                    mCreationStage = CSE_ClassChosen;
                break;

            case GM_ClassCreate:
                if (!mCreateClassDialog)
                {
                    mCreateClassDialog = new CreateClassDialog();
                    mCreateClassDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogDone);
                    mCreateClassDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onCreateClassDialogBack);
                }
                mCreateClassDialog->setNextButtonShow(mCreationStage >= CSE_ClassChosen);
                mCreateClassDialog->setVisible(true);
                if (mCreationStage < CSE_RaceChosen)
                    mCreationStage = CSE_RaceChosen;
                break;
            case GM_ClassGenerate:
                mGenerateClassStep = 0;
                mGenerateClass = "";
                mGenerateClassSpecializations[0] = 0;
                mGenerateClassSpecializations[1] = 0;
                mGenerateClassSpecializations[2] = 0;
                showClassQuestionDialog();
                if (mCreationStage < CSE_RaceChosen)
                    mCreationStage = CSE_RaceChosen;
                break;
            case GM_Review:
                MWBase::Environment::get().getWindowManager()->removeDialog(mReviewDialog);
                mReviewDialog = 0;
                mReviewDialog = new ReviewDialog();
                mReviewDialog->setPlayerName(mPlayerName);
                mReviewDialog->setRace(mPlayerRaceId);
                mReviewDialog->setClass(mPlayerClass);
                mReviewDialog->setBirthSign(mPlayerBirthSignId);

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

                    mReviewDialog->setHealth ( stats.getHealth()  );
                    mReviewDialog->setMagicka( stats.getMagicka() );
                    mReviewDialog->setFatigue( stats.getFatigue() );
                }

                {
                    std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
                    for (std::map<int, MWMechanics::AttributeValue >::iterator it = attributes.begin();
                        it != attributes.end(); ++it)
                    {
                        mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (it->first), it->second);
                    }
                }

                {
                    std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
                    for (std::map<int, MWMechanics::SkillValue >::iterator it = skills.begin();
                        it != skills.end(); ++it)
                    {
                        mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);
                    }
                    mReviewDialog->configureSkills(MWBase::Environment::get().getWindowManager()->getPlayerMajorSkills(), MWBase::Environment::get().getWindowManager()->getPlayerMinorSkills());
                }

                mReviewDialog->eventDone += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogDone);
                mReviewDialog->eventBack += MyGUI::newDelegate(this, &CharacterCreation::onReviewDialogBack);
                mReviewDialog->eventActivateDialog += MyGUI::newDelegate(this, &CharacterCreation::onReviewActivateDialog);
                mReviewDialog->setVisible(true);
                if (mCreationStage < CSE_BirthSignChosen)
                    mCreationStage = CSE_BirthSignChosen;
                break;
        }
    }
Esempio n. 17
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");
    }
}
Esempio n. 18
0
void RenderingManager::addObject (const MWWorld::Ptr& ptr){
    const MWWorld::Class& class_ =
            ptr.getClass();
    class_.insertObjectRendering(ptr, *this);
}
Esempio n. 19
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");
    }
}
Esempio n. 20
0
void RenderingManager::update (float duration, bool paused)
{
    if (MWBase::Environment::get().getStateManager()->getState()==
        MWBase::StateManager::State_NoGame)
        return;

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

    MWWorld::Ptr player = world->getPlayerPtr();

    int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude();
    MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f)));
    setAmbientMode();

    // player position
    MWWorld::RefData &data = player.getRefData();
    Ogre::Vector3 playerPos(data.getPosition().pos);

    mCamera->setCameraDistance();
    if(!mCamera->isFirstPerson())
    {
        Ogre::Vector3 orig, dest;
        mCamera->getPosition(orig, dest);

        btVector3 btOrig(orig.x, orig.y, orig.z);
        btVector3 btDest(dest.x, dest.y, dest.z);
        std::pair<bool,float> test = mPhysicsEngine->sphereCast(mRendering.getCamera()->getNearClipDistance()*2.5, btOrig, btDest);
        if(test.first)
            mCamera->setCameraDistance(test.second * orig.distance(dest), false, false);
    }

    // Sink the camera while sneaking
    bool isSneaking = player.getClass().getCreatureStats(player).getStance(MWMechanics::CreatureStats::Stance_Sneak);
    bool isInAir = !world->isOnGround(player);
    bool isSwimming = world->isSwimming(player);

    static const int i1stPersonSneakDelta = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
            .find("i1stPersonSneakDelta")->getInt();
    if(!paused && isSneaking && !(isSwimming || isInAir))
        mCamera->setSneakOffset(i1stPersonSneakDelta);

    mOcclusionQuery->update(duration);

    mRendering.update(duration);

    Ogre::ControllerManager::getSingleton().setTimeFactor(paused ? 0.f : 1.f);

    Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition();

    applyFog(world->isUnderwater(player.getCell(), cam));

    mCamera->update(duration, paused);

    Ogre::SceneNode *node = data.getBaseNode();
    Ogre::Quaternion orient = node->_getDerivedOrientation();
    mLocalMap->updatePlayer(playerPos, orient);

    if(paused)
        return;

    mEffectManager->update(duration, mRendering.getCamera());

    mActors->update (mRendering.getCamera());
    mPlayerAnimation->preRender(mRendering.getCamera());
    mObjects->update (duration, mRendering.getCamera());

    mSkyManager->update(duration);

    mSkyManager->setGlare(mOcclusionQuery->getSunVisibility());


    mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam));

    mWater->update(duration, playerPos);
}
Esempio n. 21
0
bool MWMechanics::AiPackage::isTargetMagicallyHidden(const MWWorld::Ptr& target)
{
    const MagicEffects& magicEffects(target.getClass().getCreatureStats(target).getMagicEffects());
    return (magicEffects.get(ESM::MagicEffect::Invisibility).getMagnitude() > 0)
        || (magicEffects.get(ESM::MagicEffect::Chameleon).getMagnitude() > 75);
}
Esempio n. 22
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

    // The distances below are approximations based on observations of the original engine.
    // If only one actor is following the target, it uses 186.
    // If there are multiple actors following the same target, they form a group with each group member at 313 + (130 * i) distance to the target.

    short followDistance = 186;
    std::list<int> followers = MWBase::Environment::get().getMechanicsManager()->getActorsFollowingIndices(target);
    if (followers.size() >= 2)
    {
        followDistance = 313;
        short i = 0;
        followers.sort();
        for (std::list<int>::iterator it = followers.begin(); it != followers.end(); ++it)
        {
            if (*it == mFollowIndex)
                followDistance += 130 * i;
            ++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 short 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 threshold
            actor.getClass().getCreatureStats(actor).setMovementFlag(MWMechanics::CreatureStats::Flag_Run, false); //make NPC walk
    }

    return false;
}
Esempio n. 23
0
    float rateEffect(const ESM::ENAMstruct &effect, const MWWorld::Ptr &actor, const MWWorld::Ptr &target)
    {
        // NOTE: target may be empty

        float rating = 1;
        switch (effect.mEffectID)
        {
        case ESM::MagicEffect::Soultrap:
        case ESM::MagicEffect::AlmsiviIntervention:
        case ESM::MagicEffect::DivineIntervention:
        case ESM::MagicEffect::CalmHumanoid:
        case ESM::MagicEffect::CalmCreature:
        case ESM::MagicEffect::FrenzyHumanoid:
        case ESM::MagicEffect::FrenzyCreature:
        case ESM::MagicEffect::DemoralizeHumanoid:
        case ESM::MagicEffect::DemoralizeCreature:
        case ESM::MagicEffect::RallyHumanoid:
        case ESM::MagicEffect::RallyCreature:
        case ESM::MagicEffect::Charm:
        case ESM::MagicEffect::DetectAnimal:
        case ESM::MagicEffect::DetectEnchantment:
        case ESM::MagicEffect::DetectKey:
        case ESM::MagicEffect::Telekinesis:
        case ESM::MagicEffect::Mark:
        case ESM::MagicEffect::Recall:
        case ESM::MagicEffect::Jump:
        case ESM::MagicEffect::WaterBreathing:
        case ESM::MagicEffect::SwiftSwim:
        case ESM::MagicEffect::WaterWalking:
        case ESM::MagicEffect::SlowFall:
        case ESM::MagicEffect::Light:
        case ESM::MagicEffect::Lock:
        case ESM::MagicEffect::Open:
        case ESM::MagicEffect::TurnUndead:
        case ESM::MagicEffect::WeaknessToCommonDisease:
        case ESM::MagicEffect::WeaknessToBlightDisease:
        case ESM::MagicEffect::WeaknessToCorprusDisease:
        case ESM::MagicEffect::CureCommonDisease:
        case ESM::MagicEffect::CureBlightDisease:
        case ESM::MagicEffect::CureCorprusDisease:
        case ESM::MagicEffect::Invisibility:
            return 0.f;
        case ESM::MagicEffect::Feather:
            if (actor.getClass().getEncumbrance(actor) - actor.getClass().getCapacity(actor) >= 0)
                return 100.f;
            else
                return 0.f;
        case ESM::MagicEffect::Levitate:
            return 0.f; // AI isn't designed to take advantage of this, and could be perceived as unfair anyway
        case ESM::MagicEffect::BoundBoots:
        case ESM::MagicEffect::BoundHelm:
            if (actor.getClass().isNpc())
            {
                // Beast races can't wear helmets or boots
                std::string raceid = actor.get<ESM::NPC>()->mBase->mRace;
                const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(raceid);
                if (race->mData.mFlags & ESM::Race::Beast)
                    return 0.f;
            }
            // Intended fall-through
        // Creatures can not wear armor
        case ESM::MagicEffect::BoundCuirass:
        case ESM::MagicEffect::BoundGloves:
            if (!actor.getClass().isNpc())
                return 0.f;
            break;

        case ESM::MagicEffect::RestoreHealth:
        case ESM::MagicEffect::RestoreMagicka:
        case ESM::MagicEffect::RestoreFatigue:
            if (effect.mRange == ESM::RT_Self)
            {
                int priority = 1;
                if (effect.mEffectID == ESM::MagicEffect::RestoreHealth)
                    priority = 10;
                const DynamicStat<float>& current = actor.getClass().getCreatureStats(actor).
                        getDynamic(effect.mEffectID - ESM::MagicEffect::RestoreHealth);
                float toHeal = (effect.mMagnMin + effect.mMagnMax)/2.f * effect.mDuration;
                // Effect doesn't heal more than we need, *or* we are below 1/2 health
                if (current.getModified() - current.getCurrent() > toHeal
                        || current.getCurrent() < current.getModified()*0.5)
                    return 10000.f * priority;
                else
                    return -10000.f * priority; // Save for later
            }
            break;

        // Prefer Cure effects over Dispel, because Dispel also removes positive effects
        case ESM::MagicEffect::Dispel:
            return 1000.f * numEffectsToCure(actor);
        case ESM::MagicEffect::CureParalyzation:
            return 1001.f * numEffectsToCure(actor, ESM::MagicEffect::Paralyze);
        case ESM::MagicEffect::CurePoison:
            return 1001.f * numEffectsToCure(actor, ESM::MagicEffect::Poison);

        case ESM::MagicEffect::DisintegrateArmor: // TODO: check if actor is wearing armor
        case ESM::MagicEffect::DisintegrateWeapon: // TODO: check if actor is wearing weapon
            break;

        case ESM::MagicEffect::DamageAttribute:
        case ESM::MagicEffect::DrainAttribute:
            if (!target.isEmpty() && target.getClass().getCreatureStats(target).getAttribute(effect.mAttribute).getModified() <= 0)
                return 0.f;
            {
                if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length)
                {
                    const float attributePriorities[ESM::Attribute::Length] = {
                        1.f, // Strength
                        0.5, // Intelligence
                        0.6, // Willpower
                        0.7, // Agility
                        0.5, // Speed
                        0.8, // Endurance
                        0.7, // Personality
                        0.3 // Luck
                    };
                    rating *= attributePriorities[effect.mAttribute];
                }
            }
            break;

        case ESM::MagicEffect::DamageSkill:
        case ESM::MagicEffect::DrainSkill:
            if (target.isEmpty() || !target.getClass().isNpc())
                return 0.f;
            if (target.getClass().getNpcStats(target).getSkill(effect.mSkill).getModified() <= 0)
                return 0.f;
            break;

        default:
            break;
        }

        // TODO: for non-cumulative effects (e.g. paralyze), check if the target is already suffering from them

        // TODO: could take into account target's resistance/weakness against the effect

        const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);

        rating *= magicEffect->mData.mBaseCost;

        if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
            rating *= (effect.mMagnMin + effect.mMagnMax)/2.f;
        if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
            rating *= effect.mDuration;

        if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful)
            rating *= -1.f;

        // Currently treating all "on target" or "on touch" effects to target the enemy actor.
        // Combat AI is egoistic, so doesn't consider applying positive effects to friendly actors.
        if (effect.mRange != ESM::RT_Self)
            rating *= -1.f;
        return rating;
    }
Esempio n. 24
0
                virtual void execute (Interpreter::Runtime& runtime)
                {
                    MWWorld::Ptr ptr = R()(runtime);

                    ptr.getClass().getCreatureStats(ptr).setMovementFlag (mFlag, false);
                }
Esempio n. 25
0
 void ActionPotion::prepare(const MWWorld::Ptr &actor)
 {
     actor.getClass().apply(actor, mPotion.getCellRef().getRefId(), actor);
     actor.getClass().getContainerStore(actor).remove(mPotion, 1, actor);
 }
Esempio n. 26
0
    std::shared_ptr<MWWorld::Action> Door::activate (const MWWorld::Ptr& ptr,
        const MWWorld::Ptr& actor) const
    {
        MWWorld::LiveCellRef<ESM::Door> *ref = ptr.get<ESM::Door>();

        const std::string &openSound = ref->mBase->mOpenSound;
        const std::string &closeSound = ref->mBase->mCloseSound;
        const std::string lockedSound = "LockedDoor";
        const std::string trapActivationSound = "Disarm Trap Fail";

        MWWorld::ContainerStore &invStore = actor.getClass().getContainerStore(actor);

        bool isLocked = ptr.getCellRef().getLockLevel() > 0;
        bool isTrapped = !ptr.getCellRef().getTrap().empty();
        bool hasKey = false;
        std::string keyName;

        // FIXME: If NPC activate teleporting door, it can lead to crash due to iterator invalidation in the Actors update.
        // Make such activation a no-op for now, like how it is in the vanilla game.
        if (actor != MWMechanics::getPlayer() && ptr.getCellRef().getTeleport())
        {
            std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction(std::string(), ptr));
            action->setSound(lockedSound);
            return action;
        }

        // make door glow if player activates it with telekinesis
        if (actor == MWMechanics::getPlayer() &&
            MWBase::Environment::get().getWorld()->getDistanceToFacedObject() >
            MWBase::Environment::get().getWorld()->getMaxActivationDistance())
        {
            MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);

            const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
            int index = ESM::MagicEffect::effectStringToId("sEffectTelekinesis");
            const ESM::MagicEffect *effect = store.get<ESM::MagicEffect>().find(index);

            animation->addSpellCastGlow(effect, 1); // 1 second glow to match the time taken for a door opening or closing
        }

        const std::string keyId = ptr.getCellRef().getKey();
        if (!keyId.empty())
        {
            MWWorld::Ptr keyPtr = invStore.search(keyId);
            if (!keyPtr.isEmpty())
            {
                hasKey = true;
                keyName = keyPtr.getClass().getName(keyPtr);
            }
        }

        if ((isLocked || isTrapped) && hasKey)
        {
            if(actor == MWMechanics::getPlayer())
                MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}");
            if(isLocked)
                unlock(ptr); //Call the function here. because that makes sense.
            // using a key disarms the trap
            if(isTrapped)
            {
                ptr.getCellRef().setTrap("");
                MWBase::Environment::get().getSoundManager()->playSound3D(ptr, "Disarm Trap", 1.0f, 1.0f);
                isTrapped = false;
            }
        }

        if (!isLocked || hasKey)
        {
            if(isTrapped)
            {
                // Trap activation
                std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTrap(ptr.getCellRef().getTrap(), ptr));
                action->setSound(trapActivationSound);
                return action;
            }

            if (ptr.getCellRef().getTeleport())
            {
                if (actor == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getDistanceToFacedObject() > MWBase::Environment::get().getWorld()->getMaxActivationDistance())
                {
                    // player activated teleport door with telekinesis
                    std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction);
                    return action;
                }
                else
                {
                    std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionTeleport (ptr.getCellRef().getDestCell(), ptr.getCellRef().getDoorDest(), true));
                    action->setSound(openSound);
                    return action;
                }
            }
            else
            {
                // animated door
                std::shared_ptr<MWWorld::Action> action(new MWWorld::ActionDoor(ptr));
                int doorstate = getDoorState(ptr);
                bool opening = true;
                float doorRot = ptr.getRefData().getPosition().rot[2] - ptr.getCellRef().getPosition().rot[2];
                if (doorstate == 1)
                    opening = false;
                if (doorstate == 0 && doorRot != 0)
                    opening = false;

                if (opening)
                {
                    MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr,
                            closeSound, 0.5f);
                    // Doors rotate at 90 degrees per second, so start the sound at
                    // where it would be at the current rotation.
                    float offset = doorRot/(osg::PI * 0.5f);
                    action->setSoundOffset(offset);
                    action->setSound(openSound);
                }
                else
                {
                    MWBase::Environment::get().getSoundManager()->fadeOutSound3D(ptr,
                                                openSound, 0.5f);
                    float offset = 1.0f - doorRot/(osg::PI * 0.5f);
                    action->setSoundOffset(std::max(offset, 0.0f));
                    action->setSound(closeSound);
                }

                return action;
            }
        }
        else
        {
            // locked, and we can't open.
            std::shared_ptr<MWWorld::Action> action(new MWWorld::FailedAction(std::string(), ptr));
            action->setSound(lockedSound);
            return action;
        }
    }
Esempio n. 27
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;
    }
Esempio n. 28
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"))
                && !actor.getClass().getCreatureStats(actor).isDead() // Corpses can be dressed up by the player as desired
                )
        {
            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 (iter.getType() == MWWorld::ContainerStore::Type_Weapon)
                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;
                default:
                    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;
            break;
        }
    }
    mUpdatesEnabled = true;

    if (changed)
    {
        mSlots.swap (slots_);
        fireEquipmentChangedEvent(actor);
        updateMagicEffects(actor);
        flagAsModified();
    }
}
Esempio n. 29
0
bool OMW::Engine::frame(float frametime)
{
    try
    {
        mStartTick = mViewer->getStartTick();

        mEnvironment.setFrameDuration(frametime);

        // update input
        mEnvironment.getInputManager()->update(frametime, false);

        // When the window is minimized, pause the game. Currently this *has* to be here to work around a MyGUI bug.
        // If we are not currently rendering, then RenderItems will not be reused resulting in a memory leak upon changing widget textures (fixed in MyGUI 3.3.2),
        // and destroyed widgets will not be deleted (not fixed yet, https://github.com/MyGUI/mygui/issues/21)
        if (!mEnvironment.getInputManager()->isWindowVisible())
            return false;

        // sound
        if (mUseSound)
            mEnvironment.getSoundManager()->update(frametime);

        // Main menu opened? Then scripts are also paused.
        bool paused = mEnvironment.getWindowManager()->containsMode(MWGui::GM_MainMenu);

        // update game state
        mEnvironment.getStateManager()->update (frametime);

        bool guiActive = mEnvironment.getWindowManager()->isGuiMode();

        osg::Timer_t beforeScriptTick = osg::Timer::instance()->tick();
        if (mEnvironment.getStateManager()->getState()==
            MWBase::StateManager::State_Running)
        {
            if (!paused)
            {
                if (mEnvironment.getWorld()->getScriptsEnabled())
                {
                    // local scripts
                    executeLocalScripts();

                    // global scripts
                    mEnvironment.getScriptManager()->getGlobalScripts().run();
                }

                mEnvironment.getWorld()->markCellAsUnchanged();
            }

            if (!guiActive)
            {
                double hours = (frametime * mEnvironment.getWorld()->getTimeScaleFactor()) / 3600.0;
                mEnvironment.getWorld()->advanceTime(hours, true);
            }
        }
        osg::Timer_t afterScriptTick = osg::Timer::instance()->tick();

        // update actors
        osg::Timer_t beforeMechanicsTick = osg::Timer::instance()->tick();
        if (mEnvironment.getStateManager()->getState()!=
            MWBase::StateManager::State_NoGame)
        {
            mEnvironment.getMechanicsManager()->update(frametime,
                guiActive);
        }
        osg::Timer_t afterMechanicsTick = osg::Timer::instance()->tick();

        if (mEnvironment.getStateManager()->getState()==
            MWBase::StateManager::State_Running)
        {
            MWWorld::Ptr player = mEnvironment.getWorld()->getPlayerPtr();
            if(!guiActive && player.getClass().getCreatureStats(player).isDead())
                mEnvironment.getStateManager()->endGame();
        }

        // update world
        osg::Timer_t beforePhysicsTick = osg::Timer::instance()->tick();;
        if (mEnvironment.getStateManager()->getState()!=
            MWBase::StateManager::State_NoGame)
        {
            mEnvironment.getWorld()->update(frametime, guiActive);
        }
        osg::Timer_t afterPhysicsTick = osg::Timer::instance()->tick();

        // update GUI
        mEnvironment.getWindowManager()->onFrame(frametime);

        unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
        osg::Stats* stats = mViewer->getViewerStats();
        stats->setAttribute(frameNumber, "script_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeScriptTick));
        stats->setAttribute(frameNumber, "script_time_taken", osg::Timer::instance()->delta_s(beforeScriptTick, afterScriptTick));
        stats->setAttribute(frameNumber, "script_time_end", osg::Timer::instance()->delta_s(mStartTick, afterScriptTick));

        stats->setAttribute(frameNumber, "mechanics_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforeMechanicsTick));
        stats->setAttribute(frameNumber, "mechanics_time_taken", osg::Timer::instance()->delta_s(beforeMechanicsTick, afterMechanicsTick));
        stats->setAttribute(frameNumber, "mechanics_time_end", osg::Timer::instance()->delta_s(mStartTick, afterMechanicsTick));

        stats->setAttribute(frameNumber, "physics_time_begin", osg::Timer::instance()->delta_s(mStartTick, beforePhysicsTick));
        stats->setAttribute(frameNumber, "physics_time_taken", osg::Timer::instance()->delta_s(beforePhysicsTick, afterPhysicsTick));
        stats->setAttribute(frameNumber, "physics_time_end", osg::Timer::instance()->delta_s(mStartTick, afterPhysicsTick));

        if (stats->collectStats("resource"))
        {
            mResourceSystem->reportStats(frameNumber, stats);

            stats->setAttribute(frameNumber, "WorkQueue", mWorkQueue->getNumItems());
            stats->setAttribute(frameNumber, "WorkThread", mWorkQueue->getNumActiveThreads());
        }

    }
    catch (const std::exception& e)
    {
        Log(Debug::Error) << "Error in frame: " << e.what();
    }
    return true;
}
Esempio n. 30
0
bool AiWander::execute (const MWWorld::Ptr& actor,float duration)
{
    if (actor.getClass().isNpc())
        actor.getClass().getNpcStats(actor).setDrawState(DrawState_Nothing);
    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())
        {
            assert(mAllowedNodes.size());
            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]);
        // TODO: use movement settings instead of rotating directly
        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;
}