Example #1
0
void ESM::Player::load (ESMReader &esm)
{
    mObject.load (esm);

    mCellId.load (esm);

    esm.getHNT (mLastKnownExteriorPosition, "LKEP", 12);

    if (esm.isNextSub ("MARK"))
    {
        mHasMark = true;
        esm.getHT (mMarkedPosition, 24);
        mMarkedCell.load (esm);
    }
    else
        mHasMark = false;

    mAutoMove = 0;
    esm.getHNOT (mAutoMove, "AMOV");

    mBirthsign = esm.getHNString ("SIGN");

    mCurrentCrimeId = -1;
    esm.getHNOT (mCurrentCrimeId, "CURD");
    mPayedCrimeId = -1;
    esm.getHNOT (mPayedCrimeId, "PAYD");
}
Example #2
0
 void AiFollow::load(ESMReader &esm)
 {
     esm.getHNT (mData, "DATA");
     mTargetId = esm.getHNString("TARG");
     esm.getHNT (mRemainingDuration, "DURA");
     mCellId = esm.getHNOString ("CELL");
     esm.getHNT (mAlwaysFollow, "ALWY");
     mCommanded = false;
     esm.getHNOT (mCommanded, "CMND");
     mActive = false;
     esm.getHNOT (mActive, "ACTV");
 }
Example #3
0
void ESM::CellRef::loadData(ESMReader &esm)
{
    // Again, UNAM sometimes appears after NAME and sometimes later.
    // Or perhaps this UNAM means something different?
    mReferenceBlocked = -1;
    esm.getHNOT (mReferenceBlocked, "UNAM");

    mScale = 1.0;
    esm.getHNOT (mScale, "XSCL");

    mOwner = esm.getHNOString ("ANAM");
    mGlobalVariable = esm.getHNOString ("BNAM");
    mSoul = esm.getHNOString ("XSOL");

    mFaction = esm.getHNOString ("CNAM");
    mFactionRank = -2;
    esm.getHNOT (mFactionRank, "INDX");

    mGoldValue = 1;
    mChargeInt = -1;
    mEnchantmentCharge = -1;

    esm.getHNOT (mEnchantmentCharge, "XCHG");

    esm.getHNOT (mChargeInt, "INTV");

    esm.getHNOT (mGoldValue, "NAM9");

    // Present for doors that teleport you to another cell.
    if (esm.isNextSub ("DODT"))
    {
        mTeleport = true;
        esm.getHT (mDoorDest);
        mDestCell = esm.getHNOString ("DNAM");
    }
    else
        mTeleport = false;

    mLockLevel = 0; //Set to 0 to indicate no lock
    esm.getHNOT (mLockLevel, "FLTV");

    mKey = esm.getHNOString ("KNAM");
    mTrap = esm.getHNOString ("TNAM");

    esm.getHNOT (mReferenceBlocked, "UNAM");
    if (esm.isNextSub("FLTV")) // no longer used
        esm.skipHSub();

    esm.getHNOT(mPos, "DATA", 24);

    if (esm.isNextSub("NAM0"))
        esm.skipHSub();
}
Example #4
0
void Creature::load(ESMReader &esm)
{
    mPersistent = esm.getRecordFlags() & 0x0400;

    mModel = esm.getHNString("MODL");
    mOriginal = esm.getHNOString("CNAM");
    mName = esm.getHNOString("FNAM");
    mScript = esm.getHNOString("SCRI");

    esm.getHNT(mData, "NPDT", 96);

    esm.getHNT(mFlags, "FLAG");
    mScale = 1.0;
    esm.getHNOT(mScale, "XSCL");

    mInventory.load(esm);
    mSpells.load(esm);

    if (esm.isNextSub("AIDT"))
    {
        esm.getHExact(&mAiData, sizeof(mAiData));
        mHasAI = true;
    }
    else
        mHasAI = false;

    mAiPackage.load(esm);
    esm.skipRecord();
}
Example #5
0
    void DoorState::load(ESMReader &esm)
    {
        ObjectState::load(esm);

        mDoorState = 0;
        esm.getHNOT (mDoorState, "ANIM");
    }
Example #6
0
void ESM::ObjectState::load (ESMReader &esm)
{
    mVersion = esm.getFormat();

    mRef.loadData(esm);

    mHasLocals = 0;
    esm.getHNOT (mHasLocals, "HLOC");

    if (mHasLocals)
        mLocals.load (esm);

    mEnabled = 1;
    esm.getHNOT (mEnabled, "ENAB");

    mCount = 1;
    esm.getHNOT (mCount, "COUN");

    esm.getHNOT (mPosition, "POS_", 24);

    esm.getHNOT (mLocalRotation, "LROT", 12);

    // obsolete
    int unused;
    esm.getHNOT(unused, "LTIM");

    // FIXME: assuming "false" as default would make more sense, but also break compatibility with older save files
    mHasCustomState = true;
    esm.getHNOT (mHasCustomState, "HCUS");
}
Example #7
0
void ESM::ObjectState::load (ESMReader &esm)
{
    mVersion = esm.getFormat();

    bool isDeleted;
    mRef.loadData(esm, isDeleted);

    mHasLocals = 0;
    esm.getHNOT (mHasLocals, "HLOC");

    if (mHasLocals)
        mLocals.load (esm);

    mEnabled = 1;
    esm.getHNOT (mEnabled, "ENAB");

    mCount = 1;
    esm.getHNOT (mCount, "COUN");

    esm.getHNOT (mPosition, "POS_", 24);

    if (esm.isNextSub("LROT"))
        esm.skipHSub(); // local rotation, no longer used

    mFlags = 0;
    esm.getHNOT (mFlags, "FLAG");

    // obsolete
    int unused;
    esm.getHNOT(unused, "LTIM");

    // FIXME: assuming "false" as default would make more sense, but also break compatibility with older save files
    mHasCustomState = true;
    esm.getHNOT (mHasCustomState, "HCUS");
}
Example #8
0
    bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
    {
        esm.getHT(mref.mRefNum.mIndex);
        esm.getHNOT(mref.mTarget, "CNDT");

        adjustRefNum (mref.mRefNum, esm);

        return true;
    }
Example #9
0
 void AiEscort::load(ESMReader &esm)
 {
     esm.getHNT (mData, "DATA");
     mTargetId = esm.getHNString("TARG");
     mTargetActorId = -1;
     esm.getHNOT (mTargetActorId, "TAID");
     esm.getHNT (mRemainingDuration, "DURA");
     mCellId = esm.getHNOString ("CELL");
 }
Example #10
0
    void ProjectileState::load(ESMReader &esm)
    {
        BaseProjectileState::load(esm);

        mBowId = esm.getHNString ("BOW_");
        esm.getHNT (mVelocity, "VEL_");

        mAttackStrength = 1.f;
        esm.getHNOT(mAttackStrength, "STR_");
    }
Example #11
0
void ESM::GlobalScript::load (ESMReader &esm)
{
    mId = esm.getHNString ("NAME");

    mLocals.load (esm);

    mRunning = 0;
    esm.getHNOT (mRunning, "RUN_");

    mTargetId = esm.getHNOString ("TARG");
}
Example #12
0
bool Cell::getNextMVRF(ESMReader &esm, MovedCellRef &mref)
{
    esm.getHT(mref.mRefnum);
    esm.getHNOT(mref.mTarget, "CNDT");

    // Identify references belonging to a parent file and adapt the ID accordingly.
    int local = (mref.mRefnum & 0xff000000) >> 24;
    size_t global = esm.getIndex() + 1;
    mref.mRefnum &= 0x00ffffff; // delete old plugin ID
    const std::vector<Header::MasterData> &masters = esm.getGameFiles();
    global = masters[local-1].index + 1;
    mref.mRefnum |= global << 24; // insert global plugin ID

    return true;
}
Example #13
0
void ESM::JournalEntry::load (ESMReader &esm)
{
    esm.getHNOT (mType, "JETY");
    mTopic = esm.getHNString ("YETO");
    mInfo = esm.getHNString ("YEIN");
    mText = esm.getHNString ("TEXT");

    if (mType==Type_Journal)
    {
        esm.getHNT (mDay, "JEDA");
        esm.getHNT (mMonth, "JEMO");
        esm.getHNT (mDayOfMonth, "JEDM");
    }
    else if (mType==Type_Topic)
        mActorName = esm.getHNOString("ACT_");
}
Example #14
0
void Cell::loadCell(ESMReader &esm, bool saveContext)
{
    mRefNumCounter = 0;

    if (mData.mFlags & Interior)
    {
        // Interior cells
        if (esm.isNextSub("INTV"))
        {
            int waterl;
            esm.getHT(waterl);
            mWater = (float) waterl;
            mWaterInt = true;
        }
        else if (esm.isNextSub("WHGT"))
        {
            esm.getHT(mWater);
        }

        // Quasi-exterior cells have a region (which determines the
        // weather), pure interior cells have ambient lighting
        // instead.
        if (mData.mFlags & QuasiEx)
            mRegion = esm.getHNOString("RGNN");
        else if (esm.isNextSub("AMBI"))
            esm.getHT(mAmbi);
    }
    else
    {
        // Exterior cells
        mRegion = esm.getHNOString("RGNN");

        mMapColor = 0;
        esm.getHNOT(mMapColor, "NAM5");
    }
    if (esm.isNextSub("NAM0")) {
        esm.getHT(mRefNumCounter);
    }

    if (saveContext) {
        mContextList.push_back(esm.getContext());
        esm.skipRecord();
    }
}
Example #15
0
void Creature::load(ESMReader &esm, const std::string& id)
{
    mId = id;

    model = esm.getHNString("MODL");
    original = esm.getHNOString("CNAM");
    name = esm.getHNOString("FNAM");
    script = esm.getHNOString("SCRI");

    esm.getHNT(data, "NPDT", 96);

    esm.getHNT(flags, "FLAG");
    scale = 1.0;
    esm.getHNOT(scale, "XSCL");

    inventory.load(esm);

    if (esm.isNextSub("AIDT"))
    {
        esm.getHExact(&AI, sizeof(AI));
        hasAI = true;
    }
    else
        hasAI = false;

    // More subrecords:
    // AI_W - wander (14 bytes, i don't understand it)
    //    short distance
    //    byte duration
    //    byte timeOfDay
    //    byte idle[10]
    //
    // Rest is optional:
    // AI_T - travel?
    // AI_F - follow?
    // AI_E - escort?
    // AI_A - activate?
    esm.skipRecord();

}
Example #16
0
bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMoves, MovedCellRef *mref)
{
    // TODO: Try and document reference numbering, I don't think this has been done anywhere else.
    if (!esm.hasMoreSubs())
        return false;

    // NOTE: We should not need this check. It is a safety check until we have checked
    // more plugins, and how they treat these moved references.
    if (esm.isNextSub("MVRF"))
    {
        if (ignoreMoves)
        {
            esm.getHT (mref->mRefNum.mIndex);
            esm.getHNOT (mref->mTarget, "CNDT");
            adjustRefNum (mref->mRefNum, esm);
        }
        else
        {
            // skip rest of cell record (moved references), they are handled elsewhere
            esm.skipRecord(); // skip MVRF, CNDT
            return false;
        }
    }

    ref.load (esm);

    // Identify references belonging to a parent file and adapt the ID accordingly.
    adjustRefNum (ref.mRefNum, esm);

    if (esm.isNextSub("DELE"))
    {
        esm.skipHSub();
        deleted = true;
    }
    else
        deleted = false;

    return true;
}
Example #17
0
void Cell::load(ESMReader &esm)
{
    // Ignore this for now, it might mean we should delete the entire
    // cell?
    if (esm.isNextSub("DELE"))
        esm.skipHSub();

    esm.getHNT(data, "DATA", 12);

    // Water level
    water = 0;

    if (data.flags & Interior)
    {
        // Interior cells

        if (esm.isNextSub("INTV") || esm.isNextSub("WHGT"))
            esm.getHT(water);

        // Quasi-exterior cells have a region (which determines the
        // weather), pure interior cells have ambient lighting
        // instead.
        if (data.flags & QuasiEx)
            region = esm.getHNOString("RGNN");
        else
            esm.getHNT(ambi, "AMBI", 16);
    }
    else
    {
        // Exterior cells
        region = esm.getHNOString("RGNN");
        esm.getHNOT(mapColor, "NAM5");
    }

    // Save position of the cell references and move on
    context = esm.getContext();
    esm.skipRecord();
}
Example #18
0
void ESM::CreatureStats::load (ESMReader &esm)
{
    for (int i=0; i<8; ++i)
        mAttributes[i].load (esm);

    for (int i=0; i<3; ++i)
        mDynamic[i].load (esm);

    mGoldPool = 0;
    esm.getHNOT (mGoldPool, "GOLD");

    mTradeTime.mDay = 0;
    mTradeTime.mHour = 0;
    esm.getHNOT (mTradeTime, "TIME");

    mDead = false;
    esm.getHNOT (mDead, "DEAD");

    mDied = false;
    esm.getHNOT (mDied, "DIED");

    mMurdered = false;
    esm.getHNOT (mMurdered, "MURD");

    mFriendlyHits = 0;
    esm.getHNOT (mFriendlyHits, "FRHT");

    mTalkedTo = false;
    esm.getHNOT (mTalkedTo, "TALK");

    mAlarmed = false;
    esm.getHNOT (mAlarmed, "ALRM");

    mAttacked = false;
    esm.getHNOT (mAttacked, "ATKD");

    if (esm.isNextSub("HOST"))
        esm.skipHSub(); // Hostile, no longer used

    mAttackingOrSpell = false;
    esm.getHNOT (mAttackingOrSpell, "ATCK");

    mKnockdown = false;
    esm.getHNOT (mKnockdown, "KNCK");

    mKnockdownOneFrame = false;
    esm.getHNOT (mKnockdownOneFrame, "KNC1");

    mKnockdownOverOneFrame = false;
    esm.getHNOT (mKnockdownOverOneFrame, "KNCO");

    mHitRecovery = false;
    esm.getHNOT (mHitRecovery, "HITR");

    mBlock = false;
    esm.getHNOT (mBlock, "BLCK");

    mMovementFlags = 0;
    esm.getHNOT (mMovementFlags, "MOVE");

    mAttackStrength = 0;
    esm.getHNOT (mAttackStrength, "ASTR");

    mFallHeight = 0;
    esm.getHNOT (mFallHeight, "FALL");

    mLastHitObject = esm.getHNOString ("LHIT");

    mLastHitAttemptObject = esm.getHNOString ("LHAT");

    mRecalcDynamicStats = false;
    esm.getHNOT (mRecalcDynamicStats, "CALC");

    mDrawState = 0;
    esm.getHNOT (mDrawState, "DRAW");

    mLevel = 1;
    esm.getHNOT (mLevel, "LEVL");

    mActorId = -1;
    esm.getHNOT (mActorId, "ACID");

    mDeathAnimation = 0;
    esm.getHNOT (mDeathAnimation, "DANM");

    mSpells.load(esm);
    mActiveSpells.load(esm);
    mAiSequence.load(esm);
    mMagicEffects.load(esm);

    while (esm.isNextSub("SUMM"))
    {
        int magicEffect;
        esm.getHT(magicEffect);
        std::string source = esm.getHNOString("SOUR");
        int actorId;
        esm.getHNT (actorId, "ACID");
        mSummonedCreatureMap[std::make_pair(magicEffect, source)] = actorId;
    }

    while (esm.isNextSub("GRAV"))
    {
        int actorId;
        esm.getHT(actorId);
        mSummonGraveyard.push_back(actorId);
    }

    mHasAiSettings = false;
    esm.getHNOT(mHasAiSettings, "AISE");

    if (mHasAiSettings)
    {
        for (int i=0; i<4; ++i)
            mAiSettings[i].load(esm);
    }
}
Example #19
0
bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
{
    if (!esm.hasMoreSubs())
        return false;

    // Number of references in the cell? Maximum once in each cell,
    // but not always at the beginning, and not always right. In other
    // words, completely useless.
    {
        int i;
        esm.getHNOT(i, "NAM0");
    }

    esm.getHNT(ref.refnum, "FRMR");
    ref.refID = esm.getHNString("NAME");

    // getHNOT will not change the existing value if the subrecord is
    // missing
    ref.scale = 1.0;
    esm.getHNOT(ref.scale, "XSCL");

    ref.owner = esm.getHNOString("ANAM");
    ref.glob = esm.getHNOString("BNAM");
    ref.soul = esm.getHNOString("XSOL");

    ref.faction = esm.getHNOString("CNAM");
    ref.factIndex = -1;
    esm.getHNOT(ref.factIndex, "INDX");

    ref.charge = -1.0;
    esm.getHNOT(ref.charge, "XCHG");

    ref.intv = 0;
    ref.nam9 = 0;
    esm.getHNOT(ref.intv, "INTV");
    esm.getHNOT(ref.nam9, "NAM9");

    // Present for doors that teleport you to another cell.
    if (esm.isNextSub("DODT"))
    {
        ref.teleport = true;
        esm.getHT(ref.doorDest);
        ref.destCell = esm.getHNOString("DNAM");
    }
    else
        ref.teleport = false;

    // Integer, despite the name suggesting otherwise
    ref.lockLevel = 0;
    esm.getHNOT(ref.lockLevel, "FLTV");
    ref.key = esm.getHNOString("KNAM");
    ref.trap = esm.getHNOString("TNAM");

    ref.unam = 0;
    ref.fltv = 0;
    esm.getHNOT(ref.unam, "UNAM");
    esm.getHNOT(ref.fltv, "FLTV");

    esm.getHNT(ref.pos, "DATA", 24);

    return true;
}
Example #20
0
bool Cell::getNextRef(ESMReader &esm, CellRef &ref)
{
    // TODO: Try and document reference numbering, I don't think this has been done anywhere else.
    if (!esm.hasMoreSubs())
        return false;

    // NOTE: We should not need this check. It is a safety check until we have checked
    // more plugins, and how they treat these moved references.
    if (esm.isNextSub("MVRF")) {
        esm.skipRecord(); // skip MVRF
        esm.skipRecord(); // skip CNDT
        // That should be it, I haven't seen any other fields yet.
    }

    // NAM0 sometimes appears here, sometimes further on
    ref.mNam0 = 0;
    if (esm.isNextSub("NAM0"))
    {
        esm.getHT(ref.mNam0);
        //esm.getHNOT(NAM0, "NAM0");
    }

    esm.getHNT(ref.mRefnum, "FRMR");
    ref.mRefID = esm.getHNString("NAME");

    // Identify references belonging to a parent file and adapt the ID accordingly.
    int local = (ref.mRefnum & 0xff000000) >> 24;
    size_t global = esm.getIndex() + 1;
    if (local)
    {
        // If the most significant 8 bits are used, then this reference already exists.
        // In this case, do not spawn a new reference, but overwrite the old one.
        ref.mRefnum &= 0x00ffffff; // delete old plugin ID
        const std::vector<Header::MasterData> &masters = esm.getGameFiles();
        global = masters[local-1].index + 1;
        ref.mRefnum |= global << 24; // insert global plugin ID
    }
    else
    {
        // This is an addition by the present plugin. Set the corresponding plugin index.
        ref.mRefnum |= global << 24; // insert global plugin ID
    }

    // getHNOT will not change the existing value if the subrecord is
    // missing
    ref.mScale = 1.0;
    esm.getHNOT(ref.mScale, "XSCL");

    // TODO: support loading references from saves, there are tons of keys not recognized yet.
    // The following is just an incomplete list.
    if (esm.isNextSub("ACTN"))
        esm.skipHSub();
    if (esm.isNextSub("STPR"))
        esm.skipHSub();
    if (esm.isNextSub("ACDT"))
        esm.skipHSub();
    if (esm.isNextSub("ACSC"))
        esm.skipHSub();
    if (esm.isNextSub("ACSL"))
        esm.skipHSub();
    if (esm.isNextSub("CHRD"))
        esm.skipHSub();
    else if (esm.isNextSub("CRED")) // ???
        esm.skipHSub();

    ref.mOwner = esm.getHNOString("ANAM");
    ref.mGlob = esm.getHNOString("BNAM");
    ref.mSoul = esm.getHNOString("XSOL");

    ref.mFaction = esm.getHNOString("CNAM");
    ref.mFactIndex = -2;
    esm.getHNOT(ref.mFactIndex, "INDX");

    ref.mGoldValue = 1;
    ref.mCharge = -1;
    ref.mEnchantmentCharge = -1;

    esm.getHNOT(ref.mEnchantmentCharge, "XCHG");

    esm.getHNOT(ref.mCharge, "INTV");

    esm.getHNOT(ref.mGoldValue, "NAM9");

    // Present for doors that teleport you to another cell.
    if (esm.isNextSub("DODT"))
    {
        ref.mTeleport = true;
        esm.getHT(ref.mDoorDest);
        ref.mDestCell = esm.getHNOString("DNAM");
    } else {
        ref.mTeleport = false;
    }

    // Integer, despite the name suggesting otherwise
    ref.mLockLevel = -1;
    esm.getHNOT(ref.mLockLevel, "FLTV");
    ref.mKey = esm.getHNOString("KNAM");
    ref.mTrap = esm.getHNOString("TNAM");

    ref.mReferenceBlocked = -1;
    ref.mFltv = 0;
    esm.getHNOT(ref.mReferenceBlocked, "UNAM");
    esm.getHNOT(ref.mFltv, "FLTV");

    esm.getHNOT(ref.mPos, "DATA", 24);

    // Number of references in the cell? Maximum once in each cell,
    // but not always at the beginning, and not always right. In other
    // words, completely useless.
    // Update: Well, maybe not completely useless. This might actually be
    //  number_of_references + number_of_references_moved_here_Across_boundaries,
    //  and could be helpful for collecting these weird moved references.
    if (esm.isNextSub("NAM0"))
    {
        esm.getHT(ref.mNam0);
        //esm.getHNOT(NAM0, "NAM0");
    }

    if (esm.isNextSub("DELE")) {
        esm.skipHSub();
        ref.mDeleted = 2; // Deleted, will not respawn.
        // TODO: find out when references do respawn.
    } else
        ref.mDeleted = 0;

    return true;
}
Example #21
0
    void AiSequence::load(ESMReader &esm)
    {
        while (esm.isNextSub("AIPK"))
        {
            int type;
            esm.getHT(type);

            mPackages.push_back(AiPackageContainer());
            mPackages.back().mType = type;

            switch (type)
            {
            case Ai_Wander:
            {
                std::unique_ptr<AiWander> ptr (new AiWander());
                ptr->load(esm);
                mPackages.back().mPackage = ptr.release();
                break;
            }
            case Ai_Travel:
            {
                std::unique_ptr<AiTravel> ptr (new AiTravel());
                ptr->load(esm);
                mPackages.back().mPackage = ptr.release();
                break;
            }
            case Ai_Escort:
            {
                std::unique_ptr<AiEscort> ptr (new AiEscort());
                ptr->load(esm);
                mPackages.back().mPackage = ptr.release();
                break;
            }
            case Ai_Follow:
            {
                std::unique_ptr<AiFollow> ptr (new AiFollow());
                ptr->load(esm);
                mPackages.back().mPackage = ptr.release();
                break;
            }
            case Ai_Activate:
            {
                std::unique_ptr<AiActivate> ptr (new AiActivate());
                ptr->load(esm);
                mPackages.back().mPackage = ptr.release();
                break;
            }
            case Ai_Combat:
            {
                std::unique_ptr<AiCombat> ptr (new AiCombat());
                ptr->load(esm);
                mPackages.back().mPackage = ptr.release();
                break;
            }
            case Ai_Pursue:
            {
                std::unique_ptr<AiPursue> ptr (new AiPursue());
                ptr->load(esm);
                mPackages.back().mPackage = ptr.release();
                break;
            }
            default:
                return;
            }
        }

        esm.getHNOT (mLastAiPackage, "LAST");
    }
Example #22
0
 void AiTravel::load(ESMReader &esm)
 {
     esm.getHNT (mData, "DATA");
     esm.getHNOT (mHidden, "HIDD");
 }
Example #23
0
void ESM::NpcStats::load (ESMReader &esm)
{
    while (esm.isNextSub ("FACT"))
    {
        std::string id = esm.getHString();

        Faction faction;

        int expelled = 0;
        esm.getHNOT (expelled, "FAEX");

        if (expelled)
            faction.mExpelled = true;

        esm.getHNOT (faction.mRank, "FARA");

        esm.getHNOT (faction.mReputation, "FARE");

        mFactions.insert (std::make_pair (id, faction));
    }

    mDisposition = 0;
    esm.getHNOT (mDisposition, "DISP");

    for (int i=0; i<27; ++i)
    {
        mSkills[i].mRegular.load (esm);
        mSkills[i].mWerewolf.load (esm);
    }

    bool hasWerewolfAttributes = false;
    esm.getHNOT (hasWerewolfAttributes, "HWAT");

    if (hasWerewolfAttributes)
    {
        for (int i=0; i<8; ++i)
            mWerewolfAttributes[i].load (esm);
    }

    mIsWerewolf = false;
    esm.getHNOT (mIsWerewolf, "WOLF");

    mBounty = 0;
    esm.getHNOT (mBounty, "BOUN");

    mReputation = 0;
    esm.getHNOT (mReputation, "REPU");

    mWerewolfKills = 0;
    esm.getHNOT (mWerewolfKills, "WKIL");

    mProfit = 0;
    esm.getHNOT (mProfit, "PROF");

    // No longer used. Now part of CreatureStats.
    float attackStrength = 0;
    esm.getHNOT (attackStrength, "ASTR");

    mLevelProgress = 0;
    esm.getHNOT (mLevelProgress, "LPRO");

    esm.getHNT (mSkillIncrease, "INCR");

    while (esm.isNextSub ("USED"))
        mUsedIds.push_back (esm.getHString());

    mTimeToStartDrowning = 0;
    esm.getHNOT (mTimeToStartDrowning, "DRTI");

    mLastDrowningHit = 0;
    esm.getHNOT (mLastDrowningHit, "DRLH");

    mLevelHealthBonus = 0;
    esm.getHNOT (mLevelHealthBonus, "LVLH");

    mCrimeId = -1;
    esm.getHNOT (mCrimeId, "CRID");
}