Пример #1
0
 void AiFollow::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");
     esm.getHNT (mAlwaysFollow, "ALWY");
     mCommanded = false;
     esm.getHNOT (mCommanded, "CMND");
     mActive = false;
     esm.getHNOT (mActive, "ACTV");
 }
Пример #2
0
void Clothing::load(ESMReader &esm)
{
    model = esm.getHNString("MODL");
    name = esm.getHNOString("FNAM");
    esm.getHNT(data, "CTDT", 12);

    script = esm.getHNOString("SCRI");
    icon = esm.getHNOString("ITEX");

    parts.load(esm);
    

    enchant = esm.getHNOString("ENAM");
}
Пример #3
0
void Tool::load(ESMReader &esm)
{
    model = esm.getHNString("MODL");
    name = esm.getHNString("FNAM");

    esm.getSubName();
    NAME n = esm.retSubName();
    // The data name varies, RIDT for repair items, LKDT for lock
    // picks, PBDT for probes

    esm.getHT(data, 16);

    if (n == "RIDT")
    {
        // Swap t.data.quality and t.data.uses for repair items (sigh)
        float tmp = *((float*) &data.uses);
        data.uses = *((int*) &data.quality);
        data.quality = tmp;
    }

    script = esm.getHNOString("SCRI");
    icon = esm.getHNOString("ITEX");
}
Пример #4
0
  void NPC::load(ESMReader &esm, const std::string& id)
  {
    mId = id;

    npdt52.gold = -10;

    model = esm.getHNOString("MODL");
    name = esm.getHNOString("FNAM");

    race = esm.getHNString("RNAM");
    cls = esm.getHNString("CNAM");
    faction = esm.getHNString("ANAM");
    head = esm.getHNString("BNAM");
    hair = esm.getHNString("KNAM");

    script = esm.getHNOString("SCRI");

    esm.getSubNameIs("NPDT");
    esm.getSubHeader();
    if(esm.getSubSize() == 52) esm.getExact(&npdt52, 52);
    else if(esm.getSubSize() == 12) esm.getExact(&npdt12, 12);
    else esm.fail("NPC_NPDT must be 12 or 52 bytes long");

    esm.getHNT(flags, "FLAG");

    inventory.load(esm);
    spells.load(esm);

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

    esm.skipRecord();
  }
Пример #5
0
void Faction::load(ESMReader &esm)
{
    mName = esm.getHNString("FNAM");

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

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

    if (mData.mIsHidden > 1)
        esm.fail("Unknown flag!");

    // Read faction response values
    while (esm.hasMoreSubs())
    {
        Reaction r;
        r.mFaction = esm.getHNString("ANAM");
        esm.getHNT(r.mReaction, "INTV");
        mReactions.push_back(r);
    }
}
Пример #6
0
void Container::load(ESMReader &esm)
{
    mModel = esm.getHNString("MODL");
    mName = esm.getHNOString("FNAM");
    esm.getHNT(mWeight, "CNDT", 4);
    esm.getHNT(mFlags, "FLAG", 4);

    if (mFlags & 0xf4)
        esm.fail("Unknown flags");
    if (!(mFlags & 0x8))
        esm.fail("Flag 8 not set");

    mScript = esm.getHNOString("SCRI");

    mInventory.load(esm);
}
Пример #7
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");
}
Пример #8
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();

}
Пример #9
0
void Region::load(ESMReader &esm)
{
    mName = esm.getHNString("FNAM");

    if (esm.getVer() == VER_12)
        esm.getHNExact(&mData, sizeof(mData) - 2, "WEAT");
    else if (esm.getVer() == VER_13)
        esm.getHNExact(&mData, sizeof(mData), "WEAT");
    else
        esm.fail("Don't know what to do in this version");

    mSleepList = esm.getHNOString("BNAM");

    esm.getHNT(mMapColor, "CNAM");

    while (esm.hasMoreSubs())
    {
        SoundRef sr;
        esm.getHNT(sr, "SNAM", 33);
        mSoundList.push_back(sr);
    }
}
Пример #10
0
void ESM::DebugProfile::load (ESMReader& esm)
{
    mDescription = esm.getHNString ("DESC");
    mScriptText = esm.getHNString ("SCRP");
    esm.getHNT (mFlags, "FLAG");
}
Пример #11
0
 void AiActivate::load(ESMReader &esm)
 {
     mTargetId = esm.getHNString("TARG");
 }
Пример #12
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;
}
Пример #13
0
    void LevelledListBase::load(ESMReader &esm, bool &isDeleted)
    {
        isDeleted = false;

        bool hasName = false;
        bool hasList = false;
        while (esm.hasMoreSubs())
        {
            esm.getSubName();
            switch (esm.retSubName().val)
            {
                case ESM::SREC_NAME:
                    mId = esm.getHString();
                    hasName = true;
                    break;
                case ESM::FourCC<'D','A','T','A'>::value:
                    esm.getHT(mFlags);
                    break;
                case ESM::FourCC<'N','N','A','M'>::value:
                    esm.getHT(mChanceNone);
                    break;
                case ESM::FourCC<'I','N','D','X'>::value:
                {
                    int length = 0;
                    esm.getHT(length);
                    mList.resize(length);

                    // If this levelled list was already loaded by a previous content file,
                    // we overwrite the list. Merging lists should probably be left to external tools,
                    // with the limited amount of information there is in the records, all merging methods
                    // will be flawed in some way. For a proper fix the ESM format would have to be changed
                    // to actually track list changes instead of including the whole list for every file
                    // that does something with that list.
                    for (size_t i = 0; i < mList.size(); i++)
                    {
                        LevelItem &li = mList[i];
                        li.mId = esm.getHNString(mRecName);
                        esm.getHNT(li.mLevel, "INTV");
                    }

                    hasList = true;
                    break;
                }
                case ESM::SREC_DELE:
                    esm.skipHSub();
                    isDeleted = true;
                    break;
                default:
                {
                    if (!hasList)
                    {
                        // Original engine ignores rest of the record, even if there are items following
                        mList.clear();
                        esm.skipRecord();
                    }
                    else
                    {
                        esm.fail("Unknown subrecord");
                    }
                    break;
                }
            }
        }

        if (!hasName)
            esm.fail("Missing NAME subrecord");
    }
Пример #14
0
void Pathgrid::load(ESMReader &esm)
{
    esm.getHNT(mData, "DATA", 12);
    mCell = esm.getHNString("NAME");

    // keep track of total connections so we can reserve edge vector size
    int edgeCount = 0;

    if (esm.isNextSub("PGRP"))
    {
        esm.getSubHeader();
        int size = esm.getSubSize();
        // Check that the sizes match up. Size = 16 * s2 (path points)
        if (size != static_cast<int> (sizeof(Point) * mData.mS2))
            esm.fail("Path point subrecord size mismatch");
        else
        {
            int pointCount = mData.mS2;
            mPoints.reserve(pointCount);
            for (int i = 0; i < pointCount; ++i)
            {
                Point p;
                esm.getExact(&p, sizeof(Point));
                mPoints.push_back(p);
                edgeCount += p.mConnectionNum;
            }
        }
    }

    if (esm.isNextSub("PGRC"))
    {
        esm.getSubHeader();
        int size = esm.getSubSize();
        if (size % sizeof(int) != 0)
            esm.fail("PGRC size not a multiple of 4");
        else
        {
            int rawConnNum = size / sizeof(int);
            std::vector<int> rawConnections;
            rawConnections.reserve(rawConnNum);
            for (int i = 0; i < rawConnNum; ++i)
            {
                int currentValue;
                esm.getT(currentValue);
                rawConnections.push_back(currentValue);
            }

            std::vector<int>::const_iterator rawIt = rawConnections.begin();
            int pointIndex = 0;
            mEdges.reserve(edgeCount);
            for(PointList::const_iterator it = mPoints.begin(); it != mPoints.end(); ++it, ++pointIndex)
            {
                unsigned char connectionNum = (*it).mConnectionNum;
                for (int i = 0; i < connectionNum; ++i) {
                    Edge edge;
                    edge.mV0 = pointIndex;
                    edge.mV1 = *rawIt;
                    ++rawIt;
                    mEdges.push_back(edge);
                }
            }
        }
    }
}
Пример #15
0
void DialInfo::load(ESMReader &esm)
{
    mId = esm.getHNString("INAM");
    mPrev = esm.getHNString("PNAM");
    mNext = esm.getHNString("NNAM");

    // Not present if deleted
    if (esm.isNextSub("DATA")) {
        esm.getHT(mData, 12);
    }

    // What follows is somewhat spaghetti-ish, but it's worth if for
    // an extra speedup. INFO is by far the most common record type.

    // subName is a reference to the original, so it changes whenever
    // a new sub name is read. esm.isEmptyOrGetName() will get the
    // next name for us, or return true if there are no more records.
    esm.getSubName();
    const NAME &subName = esm.retSubName();

    if (subName.val == REC_ONAM)
    {
        mActor = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }
    if (subName.val == REC_RNAM)
    {
        mRace = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }
    if (subName.val == REC_CNAM)
    {
        mClass = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }

    mFactionLess = false;
    if (subName.val == REC_FNAM)
    {
        mNpcFaction = esm.getHString();
        if (mNpcFaction == "FFFF")
            mFactionLess = true;
        if (esm.isEmptyOrGetName())
            return;
    }
    if (subName.val == REC_ANAM)
    {
        mCell = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }
    if (subName.val == REC_DNAM)
    {
        mPcFaction = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }
    if (subName.val == REC_SNAM)
    {
        mSound = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }
    if (subName.val == REC_NAME)
    {
        mResponse = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }

    while (subName.val == REC_SCVR)
    {
        SelectStruct ss;

        ss.mSelectRule = esm.getHString();
        esm.isEmptyOrGetName();

        if (subName.val == REC_INTV)
        {
            ss.mType = VT_Int;
            esm.getHT(ss.mI);
        }
        else if (subName.val == REC_FLTV)
        {
            ss.mType = VT_Float;
            esm.getHT(ss.mF);
        }
        else
            esm.fail(
                    "INFO.SCVR must precede INTV or FLTV, not "
                            + subName.toString());

        mSelects.push_back(ss);

        if (esm.isEmptyOrGetName())
            return;
    }

    if (subName.val == REC_BNAM)
    {
        mResultScript = esm.getHString();
        if (esm.isEmptyOrGetName())
            return;
    }

    mQuestStatus = QS_None;

    if (subName.val == REC_QSTN)
        mQuestStatus = QS_Name;
    else if (subName.val == REC_QSTF)
        mQuestStatus = QS_Finished;
    else if (subName.val == REC_QSTR)
        mQuestStatus = QS_Restart;
    else if (subName.val == REC_DELE)
        mQuestStatus = QS_Deleted;
    else
        esm.fail(
                "Don't know what to do with " + subName.toString()
                        + " in INFO " + mId);

    if (mQuestStatus != QS_None)
        // Skip rest of record
        esm.skipRecord();
}
Пример #16
0
 // Load a record and add it to the list
 void load(ESMReader &esm)
 {
   esm.getSubNameIs("DATA");
   esm.skipHSub();
   script = esm.getHNString("NAME");
 }
Пример #17
0
void BodyPart::load(ESMReader &esm)
{
    model = esm.getHNString("MODL");
    name = esm.getHNString("FNAM");
    esm.getHNT(data, "BYDT", 4);
}
Пример #18
0
void Activator::load(ESMReader &esm)
{
    mModel = esm.getHNString("MODL");
    mName = esm.getHNString("FNAM");
    mScript = esm.getHNOString("SCRI");
}
Пример #19
0
 void load(ESMReader &esm)
 {
   model = esm.getHNString("MODL");
   name = esm.getHNString("FNAM");
   script = esm.getHNOString("SCRI");
 }
Пример #20
0
void BodyPart::load(ESMReader &esm)
{
    mModel = esm.getHNString("MODL");
    mRace = esm.getHNOString("FNAM");
    esm.getHNT(mData, "BYDT", 4);
}
Пример #21
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;
}