Beispiel #1
0
void PathGrid::load(ESMReader &esm)
{
    esm.getHNT(data, "DATA", 12);
    cell = esm.getHNString("NAME");

    // Remember this file position
    context = esm.getContext();

    // Check that the sizes match up. Size = 16 * s2 (path points?)
    if (esm.isNextSub("PGRP"))
    {
        esm.skipHSub();
        int size = esm.getSubSize();
        if (size != 16 * data.s2)
            esm.fail("Path grid table size mismatch");
    }

    // Size varies. Path grid chances? Connections? Multiples of 4
    // suggest either int or two shorts, or perhaps a float. Study
    // it later.
    if (esm.isNextSub("PGRC"))
    {
        esm.skipHSub();
        int size = esm.getSubSize();
        if (size % 4 != 0)
            esm.fail("PGRC size not a multiple of 4");
    }
}
Beispiel #2
0
void ESM::Header::load (ESMReader &esm)
{
    if (esm.isNextSub("HEDR"))
    {
        esm.getSubHeader();
        esm.getT(mData.version);
        esm.getT(mData.type);
        mData.author.assign(esm.getString(sizeof(mData.author.name)));
        mData.desc.assign(esm.getString(sizeof(mData.desc.name)));
        esm.getT(mData.records);
    }

    if (esm.isNextSub ("FORM"))
    {
        esm.getHT (mFormat);
        if (mFormat<0)
            esm.fail ("invalid format code");
    }
    else
        mFormat = 0;

    while (esm.isNextSub ("MAST"))
    {
        MasterData m;
        m.name = esm.getHString();
        m.size = esm.getHNLong ("DATA");
        mMaster.push_back (m);
    }
}
Beispiel #3
0
bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted)
{
    // 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.
    }

    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;
}
Beispiel #4
0
    void SpellState::load(ESMReader &esm)
    {
        while (esm.isNextSub("SPEL"))
        {
            std::string id = esm.getHString();

            std::map<const int, float> random;
            while (esm.isNextSub("INDX"))
            {
                int index;
                esm.getHT(index);

                float magnitude;
                esm.getHNT(magnitude, "RAND");

                random[index] = magnitude;
            }

            mSpells[id] = random;
        }

        while (esm.isNextSub("USED"))
        {
            std::string id = esm.getHString();
            TimeStamp time;
            esm.getHNT(time, "TIME");

            mUsedPowers[id] = time;
        }

        mSelectedSpell = esm.getHNOString("SLCT");
    }
Beispiel #5
0
  void load(ESMReader &esm)
  {
    // Get the grid location
    esm.getSubNameIs("INTV");
    esm.getT(X);
    esm.getT(Y);

    esm.getHNT(flags, "DATA");

    // Store the file position
    context = esm.getContext();

    hasData = false;
    int cnt = 0;

    // Skip these here. Load the actual data when the cell is loaded.
    if(esm.isNextSub("VNML")) {esm.skipHSubSize(12675);cnt++;}
    if(esm.isNextSub("VHGT")) {esm.skipHSubSize(4232);cnt++;}
    if(esm.isNextSub("WNAM")) esm.skipHSubSize(81);
    if(esm.isNextSub("VCLR")) esm.skipHSubSize(12675);
    if(esm.isNextSub("VTEX")) {esm.skipHSubSize(512);cnt++;}

    // We need all three of VNML, VHGT and VTEX in order to use the
    // landscape.
    hasData = (cnt == 3);
  }
Beispiel #6
0
void NPC::load(ESMReader &esm)
{
    mNpdt52.mGold = -10;

    mPersistent = esm.getRecordFlags() & 0x0400;

    mModel = esm.getHNOString("MODL");
    mName = esm.getHNOString("FNAM");

    mRace = esm.getHNString("RNAM");
    mClass = esm.getHNString("CNAM");
    mFaction = esm.getHNString("ANAM");
    mHead = esm.getHNString("BNAM");
    mHair = esm.getHNString("KNAM");

    mScript = esm.getHNOString("SCRI");

    esm.getSubNameIs("NPDT");
    esm.getSubHeader();
    if (esm.getSubSize() == 52)
    {
        mNpdtType = 52;
        esm.getExact(&mNpdt52, 52);
    }
    else if (esm.getSubSize() == 12)
    {
        mNpdtType = 12;
        esm.getExact(&mNpdt12, 12);
    }
    else
        esm.fail("NPC_NPDT must be 12 or 52 bytes long");

    esm.getHNT(mFlags, "FLAG");

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

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

    while (esm.isNextSub("DODT") || esm.isNextSub("DNAM")) {
        if (esm.retSubName() == 0x54444f44) { // DODT struct
            Dest dodt;
            esm.getHExact(&dodt.mPos, 24);
            mTransport.push_back(dodt);
        } else if (esm.retSubName() == 0x4d414e44) { // DNAM struct
            mTransport.back().mCellName = esm.getHString();
        }
    }
    mAiPackage.load(esm);
    esm.skipRecord();
}
Beispiel #7
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();
}
Beispiel #8
0
void Land::load(ESMReader &esm)
{
    mEsm = &esm;
    mPlugin = mEsm->getIndex();

    // Get the grid location
    esm.getSubNameIs("INTV");
    esm.getSubHeaderIs(8);
    esm.getT<int>(mX);
    esm.getT<int>(mY);

    esm.getHNT(mFlags, "DATA");

    // Store the file position
    mContext = esm.getContext();

    mHasData = false;

    // Skip these here. Load the actual data when the cell is loaded.
    if (esm.isNextSub("VNML"))
    {
        esm.skipHSubSize(12675);
        mDataTypes |= DATA_VNML;
    }
    if (esm.isNextSub("VHGT"))
    {
        esm.skipHSubSize(4232);
        mDataTypes |= DATA_VHGT;
    }
    if (esm.isNextSub("WNAM"))
    {
        esm.skipHSubSize(81);
        mDataTypes |= DATA_WNAM;
    }
    if (esm.isNextSub("VCLR"))
    {
        esm.skipHSubSize(12675);
        mDataTypes |= DATA_VCLR;
    }
    if (esm.isNextSub("VTEX"))
    {
        esm.skipHSubSize(512);
        mDataTypes |= DATA_VTEX;
    }

    // We need all three of VNML, VHGT and VTEX in order to use the
    // landscape. (Though Morrowind seems to accept terrain without VTEX/VCLR entries)
    mHasData = mDataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM);

    mDataLoaded = 0;
    mLandData = NULL;
}
Beispiel #9
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");
}
Beispiel #10
0
void LeveledListBase::load(ESMReader &esm)
{
    esm.getHNT(mFlags, "DATA");
    esm.getHNT(mChanceNone, "NNAM");

    if (esm.isNextSub("INDX"))
    {
        int len;
        esm.getHT(len);
        mList.resize(len);
    }
    else
        return;

    // TODO: Merge with an existing lists here. This can be done
    // simply by adding the lists together, making sure that they are
    // sorted by level. A better way might be to exclude repeated
    // items. Also, some times we don't want to merge lists, just
    // overwrite. Figure out a way to give the user this option.

    for (size_t i = 0; i < mList.size(); i++)
    {
        LevelItem &li = mList[i];
        li.mId = esm.getHNString(mRecName);
        esm.getHNT(li.mLevel, "INTV");
    }
}
Beispiel #11
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();
}
Beispiel #12
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

    // 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");
}
Beispiel #13
0
void EffectList::load(ESMReader &esm)
{
    ENAMstruct s;
    while (esm.isNextSub("ENAM")) {
        esm.getHT(s, 24);
        mList.push_back(s);
    }
}
Beispiel #14
0
void Land::load(ESMReader &esm)
{
    mEsm = &esm;
    mPlugin = mEsm->getIndex();

    // Get the grid location
    esm.getSubNameIs("INTV");
    esm.getSubHeaderIs(8);
    esm.getT<int>(mX);
    esm.getT<int>(mY);

    esm.getHNT(mFlags, "DATA");

    // Store the file position
    mContext = esm.getContext();

    // Skip these here. Load the actual data when the cell is loaded.
    if (esm.isNextSub("VNML"))
    {
        esm.skipHSubSize(12675);
        mDataTypes |= DATA_VNML;
    }
    if (esm.isNextSub("VHGT"))
    {
        esm.skipHSubSize(4232);
        mDataTypes |= DATA_VHGT;
    }
    if (esm.isNextSub("WNAM"))
    {
        esm.skipHSubSize(81);
        mDataTypes |= DATA_WNAM;
    }
    if (esm.isNextSub("VCLR"))
    {
        esm.skipHSubSize(12675);
        mDataTypes |= DATA_VCLR;
    }
    if (esm.isNextSub("VTEX"))
    {
        esm.skipHSubSize(512);
        mDataTypes |= DATA_VTEX;
    }

    mDataLoaded = 0;
    mLandData = NULL;
}
Beispiel #15
0
void InventoryList::load(ESMReader &esm)
{
    ContItem ci;
    while (esm.isNextSub("NPCO"))
    {
        esm.getHT(ci, 36);
        mList.push_back(ci);
    }
}
Beispiel #16
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();
    }
}
Beispiel #17
0
 void load(ESMReader &esm)
 {
   while(esm.isNextSub("INDX"))
     {
       PartReference pr;
       esm.getHT(pr.part); // The INDX byte
       pr.male = esm.getHNOString("BNAM");
       pr.female = esm.getHNOString("CNAM");
     }
 }
Beispiel #18
0
void ESM::DialogueState::load (ESMReader &esm)
{
    while (esm.isNextSub ("TOPI"))
        mKnownTopics.push_back (esm.getHString());

    while (esm.isNextSub ("FACT"))
    {
        std::string faction = esm.getHString();

        while (esm.isNextSub ("REAC"))
        {
            std::string faction2 = esm.getHString();
            int reaction;
            esm.getHNT(reaction, "INTV");

            mModFactionReaction[faction][faction2] = reaction;
        }
    }
}
Beispiel #19
0
void Cell::loadData(ESMReader &esm)
{
    // Ignore this for now, it might mean we should delete the entire
    // cell?
    // TODO: treat the special case "another plugin moved this ref, but we want to delete it"!
    if (esm.isNextSub("DELE")) {
        esm.skipHSub();
    }

    esm.getHNT(mData, "DATA", 12);
}
Beispiel #20
0
 void AiWander::load(ESMReader &esm)
 {
     esm.getHNT (mData, "DATA");
     esm.getHNT(mDurationData, "STAR"); // was mStartTime
     mStoredInitialActorPosition = false;
     if (esm.isNextSub("POS_"))
     {
         mStoredInitialActorPosition = true;
         esm.getHT(mInitialActorPosition);
     }
 }
Beispiel #21
0
void ESM::CellId::load (ESMReader &esm)
{
    mWorldspace = esm.getHNString ("SPAC");

    if (esm.isNextSub ("CIDX"))
    {
        esm.getHT (mIndex, 8);
        mPaged = true;
    }
    else
        mPaged = false;
}
Beispiel #22
0
void ESM::Header::load (ESMReader &esm)
{
    esm.getHNT (mData, "HEDR", 300);

    if (esm.isNextSub ("FORM"))
    {
        esm.getHT (mFormat);
        if (mFormat<0)
            esm.fail ("invalid format code");
    }
    else
        mFormat = 0;

    while (esm.isNextSub ("MAST"))
    {
        MasterData m;
        m.name = esm.getHString();
        m.size = esm.getHNLong ("DATA");
        mMaster.push_back (m);
    }
}
Beispiel #23
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;
}
Beispiel #24
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();
}
Beispiel #25
0
void ESM::CellRef::loadId(ESMReader &esm, bool wideRefNum)
{
    // According to Hrnchamd, this does not belong to the actual ref. Instead, it is a marker indicating that
    // the following refs are part of a "temp refs" section. A temp ref is not being tracked by the moved references system.
    // Its only purpose is a performance optimization for "immovable" things. We don't need this, and it's problematic anyway,
    // because any item can theoretically be moved by a script.
    if (esm.isNextSub ("NAM0"))
        esm.skipHSub();

    if (wideRefNum)
        esm.getHNT (mRefNum, "FRMR", 8);
    else
        esm.getHNT (mRefNum.mIndex, "FRMR");

    mRefID = esm.getHNString ("NAME");
}
Beispiel #26
0
void ESM::GlobalMap::load (ESMReader &esm)
{
    esm.getHNT(mBounds, "BNDS");

    esm.getSubNameIs("DATA");
    esm.getSubHeader();
    mImageData.resize(esm.getSubSize());
    esm.getExact(&mImageData[0], mImageData.size());

    while (esm.isNextSub("MRK_"))
    {
        esm.getSubHeader();
        CellId cell;
        esm.getT(cell.first);
        esm.getT(cell.second);
        mMarkers.push_back(cell);
    }
}
Beispiel #27
0
void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum)
{
    // According to Hrnchamd, this does not belong to the actual ref. Instead, it is a marker indicating that
    // the following refs are part of a "temp refs" section. A temp ref is not being tracked by the moved references system.
    // Its only purpose is a performance optimization for "immovable" things. We don't need this, and it's problematic anyway,
    // because any item can theoretically be moved by a script.
    if (esm.isNextSub ("NAM0"))
        esm.skipHSub();

    blank();

    mRefNum.load (esm, wideRefNum);

    mRefID = esm.getHNOString ("NAME");
    if (mRefID.empty())
    {
        std::ios::fmtflags f(std::cerr.flags());
        std::cerr << "Warning: got CellRef with empty RefId in " << esm.getName() << " 0x" << std::hex << esm.getFileOffset() << std::endl;
        std::cerr.flags(f);
    }
}
Beispiel #28
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();

}
Beispiel #29
0
  void load(ESMReader &esm)
  {
    name = esm.getHNString("FNAM");

    // Read rank names. These are optional.
    int i = 0;
    while(esm.isNextSub("RNAM") && i<10) ranks[i++] = esm.getHString();

    // Main data struct
    esm.getHNT(data, "FADT", 240);

    if(data.isHidden > 1) esm.fail("Unknown flag!");

    // Read faction response values
    while(esm.hasMoreSubs())
      {
        Reaction r;
        r.faction = esm.getHNString("ANAM");
        esm.getHNT(r.reaction, "INTV");
        reactions.push_back(r);
      }
  }
Beispiel #30
0
void Script::load(ESMReader &esm)
{
    SCHD data;
    esm.getHNT(data, "SCHD", 52);
    mData = data.mData;
    mId = data.mName.toString();

    // List of local variables
    if (esm.isNextSub("SCVR"))
    {
        int s = mData.mStringTableSize;
        char* tmp = new char[s];
        esm.getHExact(tmp, s);

        // Set up the list of variable names
        mVarNames.resize(mData.mNumShorts + mData.mNumLongs + mData.mNumFloats);

        // The tmp buffer is a null-byte separated string list, we
        // just have to pick out one string at a time.
        char* str = tmp;
        for (size_t i = 0; i < mVarNames.size(); i++)
        {
            mVarNames[i] = std::string(str);
            str += mVarNames[i].size() + 1;

            if (str - tmp > s)
                esm.fail("String table overflow");
        }
        delete[] tmp;
    }

    // Script mData
    mScriptData.resize(mData.mScriptDataSize);
    esm.getHNExact(&mScriptData[0], mScriptData.size(), "SCDT");

    // Script text
    mScriptText = esm.getHNOString("SCTX");
}