Example #1
0
void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
{
    bool quiet = (info.quiet_given || info.mode == "clone");
    bool save = (info.mode == "clone");

    // Skip back to the beginning of the reference list
    // FIXME: Changes to the references backend required to support multiple plugins have
    //  almost certainly broken this following line. I'll leave it as is for now, so that
    //  the compiler does not complain.
    cell.restore(esm, 0);

    // Loop through all the references
    ESM::CellRef ref;
    if(!quiet) std::cout << "  References:\n";
    while(cell.getNextRef(esm, ref))
    {
        if (save) {
            info.data.mCellRefs[&cell].push_back(ref);
        }

        if(quiet) continue;

        std::cout << "    Refnum: " << ref.mRefnum << std::endl;
        std::cout << "    ID: '" << ref.mRefID << "'\n";
        std::cout << "    Owner: '" << ref.mOwner << "'\n";
        std::cout << "    Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
        std::cout << "    Uses/health: '" << ref.mCharge << "'\n";
        std::cout << "    Gold value: '" << ref.mGoldValue << "'\n";
        std::cout << "    Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
    }
}
Example #2
0
    /// Run through references and store IDs
    void listRefs(const ESMStore &store, ESMReader &esm)
    {
        assert (cell);

        if (cell->context.filename.empty())
            return; // this is a dynamically generated cell -> skipping.

        // Reopen the ESM reader and seek to the right position.
        cell->restore (esm);

        CellRef ref;

        // Get each reference in turn
        while (cell->getNextRef (esm, ref))
        {
            std::string lowerCase;

            std::transform (ref.refID.begin(), ref.refID.end(), std::back_inserter (lowerCase),
                (int(*)(int)) std::tolower);

            mIds.push_back (lowerCase);
        }

        std::sort (mIds.begin(), mIds.end());
    }
Example #3
0
QString CellNameLoader::getCellName(ESM::ESMReader &esmReader)
{
    ESM::Cell cell;
    bool isDeleted = false;
    cell.loadNameAndData(esmReader, isDeleted);

    return QString::fromStdString(cell.mName);
}
Example #4
0
    void loadRefs(const ESMStore &store, ESMReader &esm)
    {
      assert (cell);

        if (cell->context.filename.empty())
            return; // this is a dynamically generated cell -> skipping.

      // Reopen the ESM reader and seek to the right position.
      cell->restore(esm);

      CellRef ref;

      // Get each reference in turn
      while(cell->getNextRef(esm, ref))
        {
            std::string lowerCase;

            std::transform (ref.refID.begin(), ref.refID.end(), std::back_inserter (lowerCase),
                (int(*)(int)) std::tolower);

            int rec = store.find(ref.refID);

            ref.refID = lowerCase;

          /* We can optimize this further by storing the pointer to the
             record itself in store.all, so that we don't need to look it
             up again here. However, never optimize. There are infinite
             opportunities to do that later.
           */
          switch(rec)
            {
            case REC_ACTI: activators.find(ref, store.activators); break;
            case REC_ALCH: potions.find(ref, store.potions); break;
            case REC_APPA: appas.find(ref, store.appas); break;
            case REC_ARMO: armors.find(ref, store.armors); break;
            case REC_BOOK: books.find(ref, store.books); break;
            case REC_CLOT: clothes.find(ref, store.clothes); break;
            case REC_CONT: containers.find(ref, store.containers); break;
            case REC_CREA: creatures.find(ref, store.creatures); break;
            case REC_DOOR: doors.find(ref, store.doors); break;
            case REC_INGR: ingreds.find(ref, store.ingreds); break;
            case REC_LEVC: creatureLists.find(ref, store.creatureLists); break;
            case REC_LEVI: itemLists.find(ref, store.itemLists); break;
            case REC_LIGH: lights.find(ref, store.lights); break;
            case REC_LOCK: lockpicks.find(ref, store.lockpicks); break;
            case REC_MISC: miscItems.find(ref, store.miscItems); break;
            case REC_NPC_: npcs.find(ref, store.npcs); break;
            case REC_PROB: probes.find(ref, store.probes); break;
            case REC_REPA: repairs.find(ref, store.repairs); break;
            case REC_STAT: statics.find(ref, store.statics); break;
            case REC_WEAP: weapons.find(ref, store.weapons); break;

            case 0: std::cout << "Cell reference " + ref.refID + " not found!\n"; break;
            default:
              std::cout << "WARNING: Ignoring reference '" << ref.refID << "' of unhandled type\n";
            }
        }
    }
Example #5
0
    void load(ESMReader &esm, const std::string &id)
    {
      count++;

      // All cells have a name record, even nameless exterior cells.
      ESM::Cell *cell = new ESM::Cell;
      cell->name = id;

      // The cell itself takes care of all the hairy details
      cell->load(esm);

      if(cell->data.flags & ESM::Cell::Interior)
        {
          // Store interior cell by name
          intCells[id] = cell;
        }
      else
        {
          // Store exterior cells by grid position
          extCells[std::make_pair (cell->data.gridX, cell->data.gridY)] = cell;
        }
    }
Example #6
0
    void load (const ESMStore &store, ESMReader &esm)
    {
        if (mState!=State_Loaded)
        {
            if (mState==State_Preloaded)
                mIds.clear();

            std::cout << "loading cell " << cell->getDescription() << std::endl;

            loadRefs (store, esm);

            mState = State_Loaded;
        }
    }
Example #7
0
 bool isExterior() const {
     return mCell->isExterior();
 }
Example #8
0
void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
{
    // Don't automatically assume that a new cell must be spawned. Multiple plugins write to the same cell,
    //  and we merge all this data into one Cell object. However, we can't simply search for the cell id,
    //  as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
    //  are not available until both cells have been loaded at least partially!

    // All cells have a name record, even nameless exterior cells.
    std::string idLower = Misc::StringUtils::lowerCase(id);
    ESM::Cell cell;
    cell.mName = id;

    // Load the (x,y) coordinates of the cell, if it is an exterior cell,
    // so we can find the cell we need to merge with
    cell.loadData(esm);

    if(cell.mData.mFlags & ESM::Cell::Interior)
    {
        // Store interior cell by name, try to merge with existing parent data.
        ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(idLower));
        if (oldcell) {
            // merge new cell into old cell
            // push the new references on the list of references to manage (saveContext = true)
            oldcell->mData = cell.mData;
            oldcell->loadCell(esm, true);
        } else
        {
            // spawn a new cell
            cell.loadCell(esm, true);

            mInt[idLower] = cell;
        }
    }
    else
    {
        // Store exterior cells by grid position, try to merge with existing parent data.
        ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(cell.getGridX(), cell.getGridY()));
        if (oldcell) {
            // merge new cell into old cell
            oldcell->mData = cell.mData;
            oldcell->loadCell(esm, false);

            // handle moved ref (MVRF) subrecords
            handleMovedCellRefs (esm, &cell);

            // push the new references on the list of references to manage
            oldcell->postLoad(esm);

            // merge lists of leased references, use newer data in case of conflict
            for (ESM::MovedCellRefTracker::const_iterator it = cell.mMovedRefs.begin(); it != cell.mMovedRefs.end(); ++it) {
                // remove reference from current leased ref tracker and add it to new cell
                ESM::MovedCellRefTracker::iterator itold = std::find(oldcell->mMovedRefs.begin(), oldcell->mMovedRefs.end(), it->mRefNum);
                if (itold != oldcell->mMovedRefs.end()) {
                    ESM::MovedCellRef target0 = *itold;
                    ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(target0.mTarget[0], target0.mTarget[1]));
                    ESM::CellRefTracker::iterator it_lease = std::find(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), it->mRefNum);
                    wipecell->mLeasedRefs.erase(it_lease);
                    *itold = *it;
                }
            }

            // We don't need to merge mLeasedRefs of cell / oldcell. This list is filled when another cell moves a
            // reference to this cell, so the list for the new cell should be empty. The list for oldcell,
            // however, could have leased refs in it and so should be kept.
        } else
        {
            // spawn a new cell
            cell.loadCell(esm, false);

            // handle moved ref (MVRF) subrecords
            handleMovedCellRefs (esm, &cell);

            // push the new references on the list of references to manage
            cell.postLoad(esm);

            mExt[std::make_pair(cell.mData.mX, cell.mData.mY)] = cell;
        }
    }
}
Example #9
0
void Store<ESM::Cell>::load(ESM::ESMReader &esm, const std::string &id)
{
    // Don't automatically assume that a new cell must be spawned. Multiple plugins write to the same cell,
    //  and we merge all this data into one Cell object. However, we can't simply search for the cell id,
    //  as many exterior cells do not have a name. Instead, we need to search by (x,y) coordinates - and they
    //  are not available until both cells have been loaded! So first, proceed as usual.
    
    // All cells have a name record, even nameless exterior cells.
    std::string idLower = Misc::StringUtils::lowerCase(id);
    ESM::Cell *cell = new ESM::Cell;
    cell->mName = id;

    //First part of cell loading
    cell->preLoad(esm);

    //Handling MovedCellRefs, there is no way to do it inside loadcell
    while (esm.isNextSub("MVRF")) {
        ESM::CellRef ref;
        ESM::MovedCellRef cMRef;
        cell->getNextMVRF(esm, cMRef);

        MWWorld::Store<ESM::Cell> &cStore = const_cast<MWWorld::Store<ESM::Cell>&>(mEsmStore->get<ESM::Cell>());
        ESM::Cell *cellAlt = const_cast<ESM::Cell*>(cStore.searchOrCreate(cMRef.mTarget[0], cMRef.mTarget[1]));

        // Get regular moved reference data. Adapted from CellStore::loadRefs. Maybe we can optimize the following
        //  implementation when the oher implementation works as well.
        cell->getNextRef(esm, ref);
        std::string lowerCase;

        std::transform (ref.mRefID.begin(), ref.mRefID.end(), std::back_inserter (lowerCase),
            (int(*)(int)) std::tolower);

        // Add data required to make reference appear in the correct cell.
        // We should not need to test for duplicates, as this part of the code is pre-cell merge.
        cell->mMovedRefs.push_back(cMRef);
        // But there may be duplicates here!
        ESM::CellRefTracker::iterator iter = std::find(cellAlt->mLeasedRefs.begin(), cellAlt->mLeasedRefs.end(), ref.mRefnum);
        if (iter == cellAlt->mLeasedRefs.end())
          cellAlt->mLeasedRefs.push_back(ref);
        else
          *iter = ref;
    }

    //Second part of cell loading
    cell->postLoad(esm);

    if(cell->mData.mFlags & ESM::Cell::Interior)
    {
        // Store interior cell by name, try to merge with existing parent data.
        ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(idLower));
        if (oldcell) {
            // push the new references on the list of references to manage
            oldcell->mContextList.push_back(cell->mContextList.at(0));
            // copy list into new cell
            cell->mContextList = oldcell->mContextList;
            // have new cell replace old cell
            *oldcell = *cell;
        } else
            mInt[idLower] = *cell;
    }
    else
    {
        // Store exterior cells by grid position, try to merge with existing parent data.
        ESM::Cell *oldcell = const_cast<ESM::Cell*>(search(cell->getGridX(), cell->getGridY()));
        if (oldcell) {
            // push the new references on the list of references to manage
            oldcell->mContextList.push_back(cell->mContextList.at(0));
            // copy list into new cell
            cell->mContextList = oldcell->mContextList;
            // merge lists of leased references, use newer data in case of conflict
            for (ESM::MovedCellRefTracker::const_iterator it = cell->mMovedRefs.begin(); it != cell->mMovedRefs.end(); it++) {
                // remove reference from current leased ref tracker and add it to new cell
                ESM::MovedCellRefTracker::iterator itold = std::find(oldcell->mMovedRefs.begin(), oldcell->mMovedRefs.end(), it->mRefnum);
                if (itold != oldcell->mMovedRefs.end()) {
                    ESM::MovedCellRef target0 = *itold;
                    ESM::Cell *wipecell = const_cast<ESM::Cell*>(search(target0.mTarget[0], target0.mTarget[1]));
                    ESM::CellRefTracker::iterator it_lease = std::find(wipecell->mLeasedRefs.begin(), wipecell->mLeasedRefs.end(), it->mRefnum);
                    wipecell->mLeasedRefs.erase(it_lease);
                    *itold = *it;
                }
            }
            cell->mMovedRefs = oldcell->mMovedRefs;
            // have new cell replace old cell
            *oldcell = *cell;
        } else
            mExt[std::make_pair(cell->mData.mX, cell->mData.mY)] = *cell;
    }
    delete cell;
}