#include "cells.hpp" #include #include #include "world.hpp" #include "class.hpp" #include "containerstore.hpp" MWWorld::Ptr::CellStore *MWWorld::Cells::getCellStore (const ESM::Cell *cell) { if (cell->data.flags & ESM::Cell::Interior) { std::map::iterator result = mInteriors.find (cell->name); if (result==mInteriors.end()) { result = mInteriors.insert (std::make_pair (cell->name, Ptr::CellStore (cell))).first; } return &result->second; } else { std::map, Ptr::CellStore>::iterator result = mExteriors.find (std::make_pair (cell->data.gridX, cell->data.gridY)); if (result==mExteriors.end()) { result = mExteriors.insert (std::make_pair ( std::make_pair (cell->data.gridX, cell->data.gridY), Ptr::CellStore (cell))).first; } return &result->second; } } void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore) { for (ESMS::CellRefList::List::iterator iter ( cellStore.containers.list.begin()); iter!=cellStore.containers.list.end(); ++iter) { Ptr container (&*iter, &cellStore); Class::get (container).getContainerStore (container).fill ( iter->base->inventory, mStore); } for (ESMS::CellRefList::List::iterator iter ( cellStore.creatures.list.begin()); iter!=cellStore.creatures.list.end(); ++iter) { Ptr container (&*iter, &cellStore); Class::get (container).getContainerStore (container).fill ( iter->base->inventory, mStore); } for (ESMS::CellRefList::List::iterator iter ( cellStore.npcs.list.begin()); iter!=cellStore.npcs.list.end(); ++iter) { Ptr container (&*iter, &cellStore); Class::get (container).getContainerStore (container).fill ( iter->base->inventory, mStore); } } MWWorld::Cells::Cells (const ESMS::ESMStore& store, ESM::ESMReader& reader, MWWorld::World& world) : mStore (store), mReader (reader), mWorld (world) {} MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y) { std::map, Ptr::CellStore>::iterator result = mExteriors.find (std::make_pair (x, y)); bool fill = false; if (result==mExteriors.end()) { const ESM::Cell *cell = mStore.cells.searchExt (x, y); if (!cell) { // Cell isn't predefined. Make one on the fly. ESM::Cell record; record.data.flags = 0; record.data.gridX = x; record.data.gridY = y; record.water = 0; record.mapColor = 0; cell = mWorld.createRecord (record); } result = mExteriors.insert (std::make_pair ( std::make_pair (x, y), Ptr::CellStore (cell))).first; fill = true; } if (result->second.mState!=Ptr::CellStore::State_Loaded) result->second.load (mStore, mReader); if (fill) fillContainers (result->second); return &result->second; } MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name) { std::map::iterator result = mInteriors.find (name); bool fill = false; if (result==mInteriors.end()) { const ESM::Cell *cell = mStore.cells.findInt (name); result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; fill = true; } if (result->second.mState!=Ptr::CellStore::State_Loaded) result->second.load (mStore, mReader); if (fill) fillContainers (result->second); return &result->second; } MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name, Ptr::CellStore& cell) { if (cell.mState==Ptr::CellStore::State_Unloaded) cell.preload (mStore, mReader); if (cell.mState==Ptr::CellStore::State_Preloaded) { std::string lowerCase; std::transform (name.begin(), name.end(), std::back_inserter (lowerCase), (int(*)(int)) std::tolower); if (std::binary_search (cell.mIds.begin(), cell.mIds.end(), lowerCase)) cell.load (mStore, mReader); else return Ptr(); } if (ESMS::LiveCellRef *ref = cell.activators.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.potions.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.appas.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.armors.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.books.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.clothes.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.containers.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.creatures.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.doors.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.ingreds.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.creatureLists.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.itemLists.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.lights.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.lockpicks.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.miscItems.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.npcs.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.probes.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.repairs.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.statics.find (name)) return Ptr (ref, &cell); if (ESMS::LiveCellRef *ref = cell.weapons.find (name)) return Ptr (ref, &cell); return Ptr(); } MWWorld::Ptr MWWorld::Cells::getPtr (const std::string& name) { // First check cells that are already listed for (std::map::iterator iter = mInteriors.begin(); iter!=mInteriors.end(); ++iter) { Ptr ptr = getPtr (name, iter->second); if (!ptr.isEmpty()) return ptr; } for (std::map, Ptr::CellStore>::iterator iter = mExteriors.begin(); iter!=mExteriors.end(); ++iter) { Ptr ptr = getPtr (name, iter->second); if (!ptr.isEmpty()) return ptr; } // Now try the other cells for (ESMS::CellList::IntCells::const_iterator iter = mStore.cells.intCells.begin(); iter!=mStore.cells.intCells.end(); ++iter) { Ptr::CellStore *cellStore = getCellStore (iter->second); Ptr ptr = getPtr (name, *cellStore); if (!ptr.isEmpty()) return ptr; } for (ESMS::CellList::ExtCells::const_iterator iter = mStore.cells.extCells.begin(); iter!=mStore.cells.extCells.end(); ++iter) { Ptr::CellStore *cellStore = getCellStore (iter->second); Ptr ptr = getPtr (name, *cellStore); if (!ptr.isEmpty()) return ptr; } // giving up return Ptr(); }