npc.cpp 19.4 KB
Newer Older
1 2 3 4 5

#include "npc.hpp"

#include <components/esm/loadnpc.hpp>

Marc Zinnschlag's avatar
Marc Zinnschlag committed
6
#include "../mwmechanics/creaturestats.hpp"
Marc Zinnschlag's avatar
Marc Zinnschlag committed
7
#include "../mwmechanics/npcstats.hpp"
Marc Zinnschlag's avatar
Marc Zinnschlag committed
8

9
#include "../mwworld/ptr.hpp"
10
#include "../mwworld/actiontalk.hpp"
11 12 13 14
#include "../mwworld/environment.hpp"
#include "../mwworld/world.hpp"

#include "../mwrender/cellimp.hpp"
15

16
#include "../mwmechanics/mechanicsmanager.hpp"
Jason Hooks's avatar
Jason Hooks committed
17
#include <OgreSceneNode.h>
18

Marc Zinnschlag's avatar
Marc Zinnschlag committed
19
namespace
20 21 22 23 24
{
    const Ogre::Radian kOgrePi (Ogre::Math::PI);
    const Ogre::Radian kOgrePiOverTwo (Ogre::Math::PI / Ogre::Real(2.0));
}

25
namespace MWClass
26
{
Marc Zinnschlag's avatar
Marc Zinnschlag committed
27 28 29 30 31 32 33 34
    std::string Npc::getId (const MWWorld::Ptr& ptr) const
    {
        ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
            ptr.get<ESM::NPC>();

        return ref->base->mId;
    }

35 36 37
    void Npc::insertObj (const MWWorld::Ptr& ptr, MWRender::CellRenderImp& cellRender,
        MWWorld::Environment& environment) const
    {
38
        //Ogre::SceneNode *chest;
39 40
        ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
            ptr.get<ESM::NPC>();
Marc Zinnschlag's avatar
Marc Zinnschlag committed
41

42 43
        //Store scenenodes by npc's name + bodypart [0]  ,  npc's name + bodypart    [1]
        //Ex.                 Fargothchest               ,  Fargothneck
44 45 46

        assert (ref->base != NULL);

47
        std::string hairID = ref->base->hair;
48
        std::string headID = ref->base->head;
Marc Zinnschlag's avatar
Marc Zinnschlag committed
49 50 51 52 53 54 55 56

        // very ugly workaround to stop OGRE from chocking on non-unique scene node handles
        static int uniqueId = 0;

        std::ostringstream stream;
        stream << "npc$" << uniqueId++;

        std::string npcName = stream.str(); // ref->base->name;
57
        //std::cout << "NPC: " << npcName << "\n";
58 59 60 61 62 63

        //get the part of the bodypart id which describes the race and the gender
        std::string bodyRaceID = headID.substr(0, headID.find_last_of("head_") - 4);
        std::string headModel = "meshes\\" +
            environment.mWorld->getStore().bodyParts.find(headID)->model;

64
        std::string hairModel = "meshes\\" +
Jason Hooks's avatar
Jason Hooks committed
65
            environment.mWorld->getStore().bodyParts.find(hairID)->model;
66

67
        MWRender::Rendering rendering (cellRender, ref->ref, ref->mData);
Marc Zinnschlag's avatar
Marc Zinnschlag committed
68

69 70 71 72 73 74

        //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the
        // right place
        const ESM::BodyPart *bodyPart =
            environment.mWorld->getStore().bodyParts.search (bodyRaceID + "chest");

75 76 77 78
        //bodyPart->model->
        Ogre::Vector3 pos = Ogre::Vector3( 20, 20, 20);
        Ogre::Vector3 axis = Ogre::Vector3( 0, 0, 1);
        Ogre::Radian angle = Ogre::Radian(0);
Marc Zinnschlag's avatar
Marc Zinnschlag committed
79

80 81 82 83 84 85 86 87
        std::string addresses[6] = {"", "", "", "","", ""};
        std::string addresses2[6] = {"", "", "", "", "", ""};
        std::string upperleft[5] = {"", "", "", "", ""};
        std::string upperright[5] = {"", "", "", "", ""};
        std::string neckandup[5] = {"", "", "","",""};
        int numbers = 0;
        int uppernumbers = 0;
        int neckNumbers = 0;
Marc Zinnschlag's avatar
Marc Zinnschlag committed
88

Jason Hooks's avatar
Jason Hooks committed
89
        if (bodyPart){
Marc Zinnschlag's avatar
Marc Zinnschlag committed
90

Jason Hooks's avatar
Jason Hooks committed
91
           cellRender.insertMesh("meshes\\" + bodyPart->model, pos, axis, angle, npcName + "chest", addresses, numbers, true);   //2 0
92 93 94 95 96 97
           addresses2[numbers] = npcName + "chest";
           addresses[numbers++] = npcName + "chest";
           upperleft[uppernumbers] = npcName + "chest";
           upperright[uppernumbers++] = npcName + "chest";
           neckandup[neckNumbers++] = npcName + "chest";
        }
Jason Hooks's avatar
Jason Hooks committed
98

Jason Hooks's avatar
Jason Hooks committed
99

100 101 102 103 104 105 106 107 108 109 110 111 112
        const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
        const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
        const ESM::BodyPart *arm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper arm");
        const ESM::BodyPart *neck = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "neck");
        const ESM::BodyPart *knee = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "knee");
        const ESM::BodyPart *ankle = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "ankle");
        const ESM::BodyPart *foot = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "foot");
        const ESM::BodyPart *feet = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "feet");
        const ESM::BodyPart *tail = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "tail");
        const ESM::BodyPart *wrist = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "wrist");
        const ESM::BodyPart *forearm = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "forearm");
        const ESM::BodyPart *hand = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hand.1st");
        const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st");
Jason Hooks's avatar
Jason Hooks committed
113 114


115
        Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75);
Marc Zinnschlag's avatar
Marc Zinnschlag committed
116

Jason Hooks's avatar
Jason Hooks committed
117
        if (groin){
118
            cellRender.insertMesh("meshes\\" + groin->model, pos2, axis, kOgrePi, npcName + "groin", addresses, numbers);
119 120 121 122
            addresses2[numbers] = npcName + "groin";
            addresses[numbers++] = npcName + "groin";
        }
        if (tail) {
123
            cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, kOgrePi, npcName + "tail", addresses, numbers, "tail");
124
        }
Marc Zinnschlag's avatar
Marc Zinnschlag committed
125

Jason Hooks's avatar
Jason Hooks committed
126
  
127
        if(upperleg){
128
        cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -16), axis, kOgrePi, npcName + "upper leg", addresses, numbers); //-18
129 130 131 132 133 134 135 136 137 138
        cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers);
        addresses2[numbers] = npcName + "upper leg2";
        addresses[numbers++] = npcName + "upper leg";
        cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers);
        }
        if(knee)
        {
            cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee", addresses, numbers);
        //cellRender.rotateMesh(Ogre::Vector3(0, 1, 0), Ogre::Radian (1), npcName + "upper arm");
        cellRender.insertMesh ("meshes\\" + knee->model, Ogre::Vector3( 0, -1, -23), axis, Ogre::Radian(0), npcName + "knee2", addresses2, numbers);
Marc Zinnschlag's avatar
Marc Zinnschlag committed
139

140 141 142 143
            addresses2[numbers] = npcName + "knee2";
            addresses[numbers++] = npcName + "knee";
        }
        if(ankle){
Marc Zinnschlag's avatar
Marc Zinnschlag committed
144

145 146
            cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0, 0, -20), axis, Ogre::Radian(0), npcName + "ankle", addresses, numbers);   //-1
            cellRender.insertMesh ("meshes\\" + ankle->model, Ogre::Vector3( 0,0, -20), axis, Ogre::Radian(0), npcName + "ankle2", addresses2, numbers); //-1
Marc Zinnschlag's avatar
Marc Zinnschlag committed
147

148 149 150 151 152 153 154 155 156 157 158
            addresses2[numbers] = npcName + "ankle2";
            addresses[numbers++] = npcName + "ankle";
        }
        if(foot){
            if(bodyRaceID.compare("b_n_khajiit_m_") == 0)
            {
                feet = foot;
            }
            else
            {
                cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot", addresses, numbers);
Jason Hooks's avatar
Jason Hooks committed
159

160 161 162 163 164 165 166
                cellRender.insertMesh ("meshes\\" + foot->model, Ogre::Vector3( 0, -4, -15), axis, Ogre::Radian(0), npcName + "foot2", addresses2, numbers);
                addresses2[numbers] = npcName + "foot2";
                addresses[numbers++] = npcName + "foot";
            }
            //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers);
        }
        if(feet){
Marc Zinnschlag's avatar
Marc Zinnschlag committed
167

168
            cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, kOgrePi, npcName + "foot", addresses, numbers);        //9, 0, -14
Jason Hooks's avatar
Jason Hooks committed
169

170
            cellRender.insertMesh ("foot\\" + feet->model, Ogre::Vector3( 7, 4, -16), axis, kOgrePi, npcName + "foot2", addresses2, numbers);
171 172 173 174
            addresses2[numbers] = npcName + "foot2";
            addresses[numbers++] = npcName + "foot";
            //cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), addresses, numbers);
        }
Marc Zinnschlag's avatar
Marc Zinnschlag committed
175 176


177 178
        if (arm){
            //010
179
            cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(-12.5, 0, 104), Ogre::Vector3(0, 1, 0), -kOgrePiOverTwo, npcName + "upper arm", upperleft, uppernumbers);   //1, 0,.75
180
             //cellRender.rotateMesh(Ogre::Vector3(1, 0, 0), Ogre::Radian (.45), upperarmpath, 2);                                                                                          //-.5, 0, -.75
181
            cellRender.insertMesh("meshes\\" + arm->model, Ogre::Vector3(12.5, 0, 105), Ogre::Vector3(-.5, 0, -.75), kOgrePi, npcName + "upper arm2", upperright, uppernumbers);
182 183 184
            upperleft[uppernumbers] = npcName + "upper arm";
            upperright[uppernumbers++] = npcName + "upper arm2";
            cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers);        //1 -1 1
185
            cellRender.rotateMesh(Ogre::Vector3(0, .1, 0),  kOgrePiOverTwo, upperleft, uppernumbers);
186
        }
Jason Hooks's avatar
Jason Hooks committed
187

188 189 190
        if (forearm)
        {
        //addresses[1] = npcName + "upper arm";
191 192
            cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm", upperleft, uppernumbers);
            cellRender.insertMesh("meshes\\" + forearm->model, Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm2", upperright, uppernumbers);
193 194 195 196 197 198 199 200 201
            upperleft[uppernumbers] = npcName + "forearm";
            upperright[uppernumbers++] = npcName + "forearm2";
        }
        //else
        //  std::cout << npcName << "has no forearm";
        if (wrist)
        {
            if(upperleft[uppernumbers - 1].compare(npcName + "upper arm") == 0)
            {
202 203
                cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm", upperleft, uppernumbers);
                cellRender.insertMesh("meshes\\b\\B_N_Argonian_M_Forearm.nif", Ogre::Vector3(-12.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "forearm2", upperright, uppernumbers);
204 205
                upperleft[uppernumbers] = npcName + "forearm";
                upperright[uppernumbers++] = npcName + "forearm2";
Jason Hooks's avatar
Jason Hooks committed
206

207
            }
208 209
            cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "wrist", upperleft, uppernumbers);
            cellRender.insertMesh("meshes\\" + wrist->model, Ogre::Vector3(-9.5, 0, 0), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "wrist2", upperright, uppernumbers);
210 211 212
            upperleft[uppernumbers] = npcName + "wrist";
            upperright[uppernumbers++] = npcName + "wrist2";
        }
Marc Zinnschlag's avatar
Marc Zinnschlag committed
213

Jason Hooks's avatar
Jason Hooks committed
214

215 216 217 218
        if(hand)
        {
            std::string pass;
            if(hand->model.compare("b\\B_N_Dark Elf_F_Hands.1st.NIF")==0 && bodyRaceID.compare("b_n_dark elf_m_") == 0)
Marc Zinnschlag's avatar
Marc Zinnschlag committed
219
                pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF";
220 221
            else
                pass = hand->model;
222 223
            cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers,false);   //0, 100, -100    0,0,120
            cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false);   //0, 100, -100    0,0,120
224 225 226 227 228 229 230 231 232 233 234 235 236 237
            upperleft[uppernumbers] = npcName + "hand";
            upperright[uppernumbers++] = npcName + "hand2";
            cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers);
            cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers);
        }
        if(hands)
        {
            std::string pass;
            if(hands->model.compare("b\\B_N_Redguard_F_Hands.1st.nif")==0 && bodyRaceID.compare("b_n_redguard_m_") == 0)
                pass = "b\\B_N_Redguard_M_Hands.1st.nif";
            else if(hands->model.compare("b\\B_N_Imperial_M_Hands.1st.nif") == 0 && bodyRaceID.compare("b_n_nord_m_") == 0)
                pass = "b\\B_N_Nord_M_Hands.1st.nif";
            else
                pass =hands->model;                             //-50, 0, -120
238 239
            cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false);   //0, 100, -100    42, 0, -110
            cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false);   //0, 100, -100    0,0,120
240 241 242 243 244
            upperleft[uppernumbers] = npcName + "hand";
            upperright[uppernumbers++] = npcName + "hand2";
            cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers);
            cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers);
        }
Jason Hooks's avatar
Jason Hooks committed
245

246 247 248
        //neck will reset chest counter
        if(neck)
        {
249
            cellRender.insertMesh ("meshes\\" + neck->model, Ogre::Vector3( 0, 0, 120), axis, kOgrePi, npcName + "neck", neckandup, neckNumbers);
250 251 252 253 254
            neckandup[neckNumbers++] = npcName + "neck";
        }
        cellRender.insertMesh (headModel, Ogre::Vector3( 0, 0, 5), axis, Ogre::Radian(0), npcName + "head", neckandup, neckNumbers);
        neckandup[neckNumbers++] = npcName + "head";
        cellRender.insertMesh (hairModel, Ogre::Vector3( 0, -1, 0), axis, Ogre::Radian(0), npcName + "hair", neckandup, neckNumbers);
255 256 257

        cellRender.insertActorPhysics();
        ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
258
    }
259

260 261 262 263 264 265 266 267 268 269
    void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
    {
        environment.mMechanicsManager->addActor (ptr);
    }

    void Npc::disable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const
    {
        environment.mMechanicsManager->removeActor (ptr);
    }

Marc Zinnschlag's avatar
Marc Zinnschlag committed
270 271 272 273 274 275 276 277
    std::string Npc::getName (const MWWorld::Ptr& ptr) const
    {
        ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
            ptr.get<ESM::NPC>();

        return ref->base->name;
    }

278
    MWMechanics::CreatureStats& Npc::getCreatureStats (const MWWorld::Ptr& ptr) const
279 280 281 282 283 284
    {
        if (!ptr.getRefData().getCreatureStats().get())
        {
            boost::shared_ptr<MWMechanics::CreatureStats> stats (
                new MWMechanics::CreatureStats);

285
            ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();
286 287 288 289 290 291 292 293 294 295 296 297 298

            stats->mAttributes[0].set (ref->base->npdt52.strength);
            stats->mAttributes[1].set (ref->base->npdt52.intelligence);
            stats->mAttributes[2].set (ref->base->npdt52.willpower);
            stats->mAttributes[3].set (ref->base->npdt52.agility);
            stats->mAttributes[4].set (ref->base->npdt52.speed);
            stats->mAttributes[5].set (ref->base->npdt52.endurance);
            stats->mAttributes[6].set (ref->base->npdt52.personality);
            stats->mAttributes[7].set (ref->base->npdt52.luck);
            stats->mDynamic[0].set (ref->base->npdt52.health);
            stats->mDynamic[1].set (ref->base->npdt52.mana);
            stats->mDynamic[2].set (ref->base->npdt52.fatigue);

299 300
            stats->mLevel = ref->base->npdt52.level;

301 302 303 304 305 306
            ptr.getRefData().getCreatureStats() = stats;
        }

        return *ptr.getRefData().getCreatureStats();
    }

Marc Zinnschlag's avatar
Marc Zinnschlag committed
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
    MWMechanics::NpcStats& Npc::getNpcStats (const MWWorld::Ptr& ptr) const
    {
        if (!ptr.getRefData().getNpcStats().get())
        {
            boost::shared_ptr<MWMechanics::NpcStats> stats (
                new MWMechanics::NpcStats);

            ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref = ptr.get<ESM::NPC>();

            if (!ref->base->faction.empty())
            {
                // TODO research how initial rank is stored. The information in loadnpc.hpp are at
                // best very unclear.
                stats->mFactionRank[ref->base->faction] = 0;
            }

323 324 325
            for (int i=0; i<27; ++i)
                stats->mSkill[i].setBase (ref->base->npdt52.skills[i]);

Marc Zinnschlag's avatar
Marc Zinnschlag committed
326 327 328 329 330 331
            ptr.getRefData().getNpcStats() = stats;
        }

        return *ptr.getRefData().getNpcStats();
    }

332 333 334 335
    boost::shared_ptr<MWWorld::Action> Npc::activate (const MWWorld::Ptr& ptr,
        const MWWorld::Ptr& actor, const MWWorld::Environment& environment) const
    {
        return boost::shared_ptr<MWWorld::Action> (new MWWorld::ActionTalk (ptr));
336
    }
Marc Zinnschlag's avatar
Marc Zinnschlag committed
337

338 339
    MWWorld::ContainerStore<MWWorld::RefData>& Npc::getContainerStore (const MWWorld::Ptr& ptr)
        const
Marc Zinnschlag's avatar
Marc Zinnschlag committed
340 341 342 343 344 345 346 347 348 349 350 351 352 353
    {
        if (!ptr.getRefData().getContainerStore().get())
        {
            boost::shared_ptr<MWWorld::ContainerStore<MWWorld::RefData> > store (
                new MWWorld::ContainerStore<MWWorld::RefData>);

            // TODO add initial content

            ptr.getRefData().getContainerStore() = store;
        }

        return *ptr.getRefData().getContainerStore();
    }

354 355 356 357 358 359 360 361
    std::string Npc::getScript (const MWWorld::Ptr& ptr) const
    {
        ESMS::LiveCellRef<ESM::NPC, MWWorld::RefData> *ref =
            ptr.get<ESM::NPC>();

        return ref->base->script;
    }

Marc Zinnschlag's avatar
Marc Zinnschlag committed
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
    void Npc::setForceStance (const MWWorld::Ptr& ptr, Stance stance, bool force) const
    {
        MWMechanics::NpcStats& stats = getNpcStats (ptr);

        switch (stance)
        {
            case Run:

                stats.mForceRun = force;
                break;

            case Sneak:

                stats.mForceSneak = force;
                break;

            case Combat:

                throw std::runtime_error ("combat stance not enforcable for NPCs");
        }
    }

    void Npc::setStance (const MWWorld::Ptr& ptr, Stance stance, bool set) const
    {
        MWMechanics::NpcStats& stats = getNpcStats (ptr);

        switch (stance)
        {
            case Run:

392 393
                stats.mRun = set;
                break;
Marc Zinnschlag's avatar
Marc Zinnschlag committed
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414

            case Sneak:

                stats.mSneak = set;
                break;

            case Combat:

                stats.mCombat = set;
                break;
        }
    }

    bool Npc::getStance (const MWWorld::Ptr& ptr, Stance stance, bool ignoreForce) const
    {
        MWMechanics::NpcStats& stats = getNpcStats (ptr);

        switch (stance)
        {
            case Run:

415 416 417 418
                if (!ignoreForce && stats.mForceRun)
                    return true;

                return stats.mRun;
Marc Zinnschlag's avatar
Marc Zinnschlag committed
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439

            case Sneak:

                if (!ignoreForce && stats.mForceSneak)
                    return true;

                return stats.mSneak;

            case Combat:

                return stats.mCombat;
        }

        return false;
    }

    float Npc::getSpeed (const MWWorld::Ptr& ptr) const
    {
        return getStance (ptr, Run) ? 600 : 300; // TODO calculate these values from stats
    }

440 441 442 443 444 445
    MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
    {
        if (!ptr.getRefData().getMovement().get())
        {
            boost::shared_ptr<MWMechanics::Movement> movement (
                new MWMechanics::Movement);
Marc Zinnschlag's avatar
Marc Zinnschlag committed
446 447

            ptr.getRefData().getMovement() = movement;
448 449 450 451 452 453 454 455 456 457 458 459
        }

        return *ptr.getRefData().getMovement();
    }

    Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const
    {
        Ogre::Vector3 vector (0, 0, 0);

        if (ptr.getRefData().getMovement().get())
        {
            vector.x = - ptr.getRefData().getMovement()->mLeftRight * 200;
gugus's avatar
gugus committed
460
            vector.y = ptr.getRefData().getMovement()->mForwardBackward * 200;
461 462 463 464 465 466 467 468

            if (getStance (ptr, Run, false))
                vector *= 2;
        }

        return vector;
    }

469 470 471 472 473 474 475
    void Npc::registerSelf()
    {
        boost::shared_ptr<Class> instance (new Npc);

        registerClass (typeid (ESM::NPC).name(), instance);
    }
}