Example #1
0
    void AIPackageList::add(ESMReader &esm)
    {
        AIPackage pack;
        if (esm.retSubName() == AI_CNDT) {
            mList.back().mCellName = esm.getHString();
        } else if (esm.retSubName() == AI_Wander) {
            pack.mType = AI_Wander;
            esm.getHExact(&pack.mWander, 14);
            mList.push_back(pack);
        } else if (esm.retSubName() == AI_Travel) {
            pack.mType = AI_Travel;
            esm.getHExact(&pack.mTravel, 16);
            mList.push_back(pack);
        } else if (esm.retSubName() == AI_Escort ||
                   esm.retSubName() == AI_Follow)
        {
            pack.mType =
                (esm.retSubName() == AI_Escort) ? AI_Escort : AI_Follow;
                esm.getHExact(&pack.mTarget, 48);
            mList.push_back(pack);
        } else if (esm.retSubName() == AI_Activate) {
            pack.mType = AI_Activate;
            esm.getHExact(&pack.mActivate, 33);
            mList.push_back(pack);
        } else { // not AI package related data, so leave
             return;
        }

    }
Example #2
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();
}
Example #3
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 #4
0
    void Script::load(ESMReader &esm)
    {
        SCHD data;
        esm.getHNT(data, "SCHD", 52);
        mData = data.mData;
        mId = data.mName.toString();

        mVarNames.clear();

        while (esm.hasMoreSubs())
        {
            esm.getSubName();
            uint32_t name = esm.retSubName().val;
            switch (name)
            {
                case ESM::FourCC<'S','C','V','R'>::value:
                    // list of local variables
                    loadSCVR(esm);
                    break;
                case ESM::FourCC<'S','C','D','T'>::value:
                    // compiled script
                    mScriptData.resize(mData.mScriptDataSize);
                    esm.getHExact(&mScriptData[0], mScriptData.size());
                    break;
                case ESM::FourCC<'S','C','T','X'>::value:
                    mScriptText = esm.getHString();
                    break;
                default:
                    esm.fail("Unknown subrecord");
            }
        }
    }
Example #5
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 #6
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");
}
Example #7
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();
  }
Example #8
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;

        std::vector<char> tmp (s);
        esm.getHExact (&tmp[0], 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[0];
        for (size_t i = 0; i < mVarNames.size(); i++)
        {
            // Support '\r' terminated strings like vanilla.  See Bug #1324.
            char *termsym = strchr(str, '\r');
            if(termsym) *termsym = '\0';
            mVarNames[i] = std::string(str);
            str += mVarNames[i].size() + 1;

            if (str - &tmp[0] > s)
            {
                // Apparently SCVR subrecord is not used and variable names are
                // determined on the fly from the script text.  Therefore don't throw
                // an exeption, just log an error and continue.
                std::stringstream ss;

                ss << "ESM Error: " << "String table overflow";
                ss << "\n  File: " << esm.getName();
                ss << "\n  Record: " << esm.getContext().recName.toString();
                ss << "\n  Subrecord: " << "SCVR";
                ss << "\n  Offset: 0x" << std::hex << esm.getFileOffset();
                std::cerr << ss.str() << std::endl;
                break;
            }

        }
    }

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

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

    // NOTE: A minor hack/workaround...
    //
    // MAO_Containers.esp from Morrowind Acoustic Overhaul has SCVR records
    // at the end (see Bug #1849). Since OpenMW does not use SCVR subrecords
    // for variable names just skip these as a quick fix.  An alternative
    // solution would be to decode and validate SCVR subrecords even if they
    // appear here.
    if (esm.isNextSub("SCVR")) {
        esm.skipHSub();
    }
}
Example #9
0
    void NPC::load(ESMReader &esm)
    {
        mPersistent = (esm.getRecordFlags() & 0x0400) != 0;

        mSpells.mList.clear();
        mInventory.mList.clear();
        mTransport.mList.clear();
        mAiPackage.mList.clear();

        bool hasNpdt = false;
        bool hasFlags = false;
        mHasAI = false;
        while (esm.hasMoreSubs())
        {
            esm.getSubName();
            uint32_t name = esm.retSubName().val;
            switch (name)
            {
                case ESM::FourCC<'M','O','D','L'>::value:
                    mModel = esm.getHString();
                    break;
                case ESM::FourCC<'F','N','A','M'>::value:
                    mName = esm.getHString();
                    break;
                case ESM::FourCC<'R','N','A','M'>::value:
                    mRace = esm.getHString();
                    break;
                case ESM::FourCC<'C','N','A','M'>::value:
                    mClass = esm.getHString();
                    break;
                case ESM::FourCC<'A','N','A','M'>::value:
                    mFaction = esm.getHString();
                    break;
                case ESM::FourCC<'B','N','A','M'>::value:
                    mHead = esm.getHString();
                    break;
                case ESM::FourCC<'K','N','A','M'>::value:
                    mHair = esm.getHString();
                    break;
                case ESM::FourCC<'S','C','R','I'>::value:
                    mScript = esm.getHString();
                    break;
                case ESM::FourCC<'N','P','D','T'>::value:
                    hasNpdt = true;
                    esm.getSubHeader();
                    if (esm.getSubSize() == 52)
                    {
                        mNpdtType = NPC_DEFAULT;
                        esm.getExact(&mNpdt52, 52);
                    }
                    else if (esm.getSubSize() == 12)
                    {
                        mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
                        esm.getExact(&mNpdt12, 12);
                    }
                    else
                        esm.fail("NPC_NPDT must be 12 or 52 bytes long");
                    break;
                case ESM::FourCC<'F','L','A','G'>::value:
                    hasFlags = true;
                    esm.getHT(mFlags);
                    break;
                case ESM::FourCC<'N','P','C','S'>::value:
                    mSpells.add(esm);
                    break;
                case ESM::FourCC<'N','P','C','O'>::value:
                    mInventory.add(esm);
                    break;
                case ESM::FourCC<'A','I','D','T'>::value:
                    esm.getHExact(&mAiData, sizeof(mAiData));
                    mHasAI= true;
                    break;
                case ESM::FourCC<'D','O','D','T'>::value:
                case ESM::FourCC<'D','N','A','M'>::value:
                    mTransport.add(esm);
                    break;
                case AI_Wander:
                case AI_Activate:
                case AI_Escort:
                case AI_Follow:
                case AI_Travel:
                case AI_CNDT:
                    mAiPackage.add(esm);
                    break;
                default:
                    esm.fail("Unknown subrecord");
            }
        }
        if (!hasNpdt)
            esm.fail("Missing NPDT subrecord");
        if (!hasFlags)
            esm.fail("Missing FLAG subrecord");
    }
Example #10
0
    void NPC::load(ESMReader &esm, bool &isDeleted)
    {
        isDeleted = false;

        mPersistent = (esm.getRecordFlags() & 0x0400) != 0;

        mSpells.mList.clear();
        mInventory.mList.clear();
        mTransport.mList.clear();
        mAiPackage.mList.clear();
        mAiData.blank();
        mAiData.mHello = mAiData.mFight = mAiData.mFlee = 30;

        bool hasName = false;
        bool hasNpdt = false;
        bool hasFlags = false;
        while (esm.hasMoreSubs())
        {
            esm.getSubName();
            switch (esm.retSubName().intval)
            {
                case ESM::SREC_NAME:
                    mId = esm.getHString();
                    hasName = true;
                    break;
                case ESM::FourCC<'M','O','D','L'>::value:
                    mModel = esm.getHString();
                    break;
                case ESM::FourCC<'F','N','A','M'>::value:
                    mName = esm.getHString();
                    break;
                case ESM::FourCC<'R','N','A','M'>::value:
                    mRace = esm.getHString();
                    break;
                case ESM::FourCC<'C','N','A','M'>::value:
                    mClass = esm.getHString();
                    break;
                case ESM::FourCC<'A','N','A','M'>::value:
                    mFaction = esm.getHString();
                    break;
                case ESM::FourCC<'B','N','A','M'>::value:
                    mHead = esm.getHString();
                    break;
                case ESM::FourCC<'K','N','A','M'>::value:
                    mHair = esm.getHString();
                    break;
                case ESM::FourCC<'S','C','R','I'>::value:
                    mScript = esm.getHString();
                    break;
                case ESM::FourCC<'N','P','D','T'>::value:
                    hasNpdt = true;
                    esm.getSubHeader();
                    if (esm.getSubSize() == 52)
                    {
                        mNpdtType = NPC_DEFAULT;
                        esm.getExact(&mNpdt, 52);
                    }
                    else if (esm.getSubSize() == 12)
                    {
                        //Reading into temporary NPDTstruct12 object
                        NPDTstruct12 npdt12;
                        mNpdtType = NPC_WITH_AUTOCALCULATED_STATS;
                        esm.getExact(&npdt12, 12);

                        //Clearing the mNdpt struct to initialize all values
                        blankNpdt();
                        //Swiching to an internal representation
                        mNpdt.mLevel = npdt12.mLevel;
                        mNpdt.mDisposition = npdt12.mDisposition;
                        mNpdt.mReputation = npdt12.mReputation;
                        mNpdt.mRank = npdt12.mRank;
                        mNpdt.mGold = npdt12.mGold;
                    }
                    else
                        esm.fail("NPC_NPDT must be 12 or 52 bytes long");
                    break;
                case ESM::FourCC<'F','L','A','G'>::value:
                    hasFlags = true;
                    esm.getHT(mFlags);
                    break;
                case ESM::FourCC<'N','P','C','S'>::value:
                    mSpells.add(esm);
                    break;
                case ESM::FourCC<'N','P','C','O'>::value:
                    mInventory.add(esm);
                    break;
                case ESM::FourCC<'A','I','D','T'>::value:
                    esm.getHExact(&mAiData, sizeof(mAiData));
                    break;
                case ESM::FourCC<'D','O','D','T'>::value:
                case ESM::FourCC<'D','N','A','M'>::value:
                    mTransport.add(esm);
                    break;
                case AI_Wander:
                case AI_Activate:
                case AI_Escort:
                case AI_Follow:
                case AI_Travel:
                case AI_CNDT:
                    mAiPackage.add(esm);
                    break;
                case ESM::SREC_DELE:
                    esm.skipHSub();
                    isDeleted = true;
                    break;
                default:
                    esm.fail("Unknown subrecord");
                    break;
            }
        }

        if (!hasName)
            esm.fail("Missing NAME subrecord");
        if (!hasNpdt && !isDeleted)
            esm.fail("Missing NPDT subrecord");
        if (!hasFlags && !isDeleted)
            esm.fail("Missing FLAG subrecord");
    }