#include "worldview.hpp" #include #include #include #include "../mwclass/container.hpp" #include "../mwworld/class.hpp" #include "../mwworld/timestamp.hpp" namespace MWLua { void WorldView::update() { mObjectRegistry.update(); mActivatorsInScene.updateList(); mActorsInScene.updateList(); mContainersInScene.updateList(); mDoorsInScene.updateList(); mItemsInScene.updateList(); } void WorldView::clear() { mObjectRegistry.clear(); mActivatorsInScene.clear(); mActorsInScene.clear(); mContainersInScene.clear(); mDoorsInScene.clear(); mItemsInScene.clear(); } WorldView::ObjectGroup* WorldView::chooseGroup(const MWWorld::Ptr& ptr) { // It is important to check `isMarker` first. // For example "prisonmarker" has class "Door" despite that it is only an invisible marker. if (isMarker(ptr)) return nullptr; const MWWorld::Class& cls = ptr.getClass(); if (cls.isActivator()) return &mActivatorsInScene; if (cls.isActor()) return &mActorsInScene; if (cls.isDoor()) return &mDoorsInScene; if (typeid(cls) == typeid(MWClass::Container)) return &mContainersInScene; if (cls.hasToolTip(ptr)) return &mItemsInScene; return nullptr; } void WorldView::objectAddedToScene(const MWWorld::Ptr& ptr) { mObjectRegistry.registerPtr(ptr); ObjectGroup* group = chooseGroup(ptr); if (group) addToGroup(*group, ptr); } void WorldView::objectRemovedFromScene(const MWWorld::Ptr& ptr) { ObjectGroup* group = chooseGroup(ptr); if (group) removeFromGroup(*group, ptr); } double WorldView::getGameTimeInHours() const { MWBase::World* world = MWBase::Environment::get().getWorld(); MWWorld::TimeStamp timeStamp = world->getTimeStamp(); return static_cast(timeStamp.getDay()) * 24 + timeStamp.getHour(); } void WorldView::load(ESM::ESMReader& esm) { esm.getHNT(mGameSeconds, "LUAW"); ObjectId lastAssignedId; lastAssignedId.load(esm, true); mObjectRegistry.setLastAssignedId(lastAssignedId); } void WorldView::save(ESM::ESMWriter& esm) const { esm.writeHNT("LUAW", mGameSeconds); mObjectRegistry.getLastAssignedId().save(esm, true); } void WorldView::ObjectGroup::updateList() { if (mChanged) { mList->clear(); for (const ObjectId& id : mSet) mList->push_back(id); mChanged = false; } } void WorldView::ObjectGroup::clear() { mChanged = false; mList->clear(); mSet.clear(); } void WorldView::addToGroup(ObjectGroup& group, const MWWorld::Ptr& ptr) { group.mSet.insert(getId(ptr)); group.mChanged = true; } void WorldView::removeFromGroup(ObjectGroup& group, const MWWorld::Ptr& ptr) { group.mSet.erase(getId(ptr)); group.mChanged = true; } // TODO: If Lua scripts will use several threads at the same time, then `find*Cell` functions should have critical sections. MWWorld::CellStore* WorldView::findCell(const std::string& name, osg::Vec3f position) { MWBase::World* world = MWBase::Environment::get().getWorld(); bool exterior = name.empty() || world->getExterior(name); if (exterior) { int cellX, cellY; world->positionToIndex(position.x(), position.y(), cellX, cellY); return world->getExterior(cellX, cellY); } else return world->getInterior(name); } MWWorld::CellStore* WorldView::findNamedCell(const std::string& name) { MWBase::World* world = MWBase::Environment::get().getWorld(); const ESM::Cell* esmCell = world->getExterior(name); if (esmCell) return world->getExterior(esmCell->getGridX(), esmCell->getGridY()); else return world->getInterior(name); } MWWorld::CellStore* WorldView::findExteriorCell(int x, int y) { MWBase::World* world = MWBase::Environment::get().getWorld(); return world->getExterior(x, y); } }