diff --git a/apps/essimporter/converter.cpp b/apps/essimporter/converter.cpp index c51e91ed7..ce3cea675 100644 --- a/apps/essimporter/converter.cpp +++ b/apps/essimporter/converter.cpp @@ -108,7 +108,7 @@ namespace ESSImport } std::vector cellrefs; - while (esm.hasMoreSubs()) + while (esm.hasMoreSubs() && esm.isNextSub("FRMR")) { CellRef ref; ref.load (esm); @@ -121,6 +121,36 @@ namespace ESSImport cellrefs.push_back(ref); } + while (esm.isNextSub("MPCD")) + { + float notepos[3]; + esm.getHT(notepos, 3*sizeof(float)); + + // Markers seem to be arranged in a 32*32 grid, notepos has grid-indices. + // This seems to be the reason markers can't be placed everywhere in interior cells, + // i.e. when the grid is exceeded. + // Converting the interior markers correctly could be rather tricky, but is probably similar logic + // as used for the FoW texture placement, which we need to figure out anyway + notepos[1] += 31.f; + notepos[0] += 0.5; + notepos[1] += 0.5; + notepos[0] = 8192 * notepos[0] / 32.f; + notepos[1] = 8192 * notepos[1] / 32.f; + if (cell.isExterior()) + { + notepos[0] += 8192 * cell.mData.mX; + notepos[1] += 8192 * cell.mData.mY; + } + // TODO: what encoding is this in? + std::string note = esm.getHNString("MPNT"); + ESM::CustomMarker marker; + marker.mWorldX = notepos[0]; + marker.mWorldY = notepos[1]; + marker.mNote = note; + marker.mCell = cell.getCellId(); + mMarkers.push_back(marker); + } + newcell.mRefs = cellrefs; // FIXME: map by ID for exterior cells @@ -199,6 +229,13 @@ namespace ESSImport esm.endRecord(ESM::REC_CSTA); } + + for (std::vector::const_iterator it = mMarkers.begin(); it != mMarkers.end(); ++it) + { + esm.startRecord(ESM::REC_MARK); + it->save(esm); + esm.endRecord(ESM::REC_MARK); + } } } diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index 3f8b4cbbe..5f1961717 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -9,6 +9,8 @@ #include #include #include +#include + #include "importcrec.hpp" #include "importercontext.hpp" @@ -240,6 +242,7 @@ private: std::map mCells; + std::vector mMarkers; }; } diff --git a/apps/essimporter/importacdt.cpp b/apps/essimporter/importacdt.cpp index 5bec5bd82..d961720a7 100644 --- a/apps/essimporter/importacdt.cpp +++ b/apps/essimporter/importacdt.cpp @@ -49,6 +49,13 @@ namespace ESSImport while (esm.isNextSub("FGTN")) esm.getHString(); // fight target? + // unsure at which point between TGTN and CRED + if (esm.isNextSub("AADT")) + { + // occured when a creature was in the middle of its attack, 44 bytes + esm.skipHSub(); + } + // unsure at which point between FGTN and CHRD if (esm.isNextSub("PWPC")) esm.skipHSub(); diff --git a/apps/essimporter/importcellref.cpp b/apps/essimporter/importcellref.cpp index 454690adc..8c2b8f36d 100644 --- a/apps/essimporter/importcellref.cpp +++ b/apps/essimporter/importcellref.cpp @@ -7,7 +7,8 @@ namespace ESSImport void CellRef::load(ESM::ESMReader &esm) { - esm.getHNT(mRefNum.mIndex, "FRMR"); + // (FRMR subrecord name is already read by the loop in ConvertCell) + esm.getHT(mRefNum.mIndex); // FRMR // this is required since openmw supports more than 255 content files int pluginIndex = (mRefNum.mIndex & 0xff000000) >> 24; diff --git a/apps/essimporter/importer.cpp b/apps/essimporter/importer.cpp index 572489d9a..12136cdea 100644 --- a/apps/essimporter/importer.cpp +++ b/apps/essimporter/importer.cpp @@ -213,6 +213,7 @@ namespace ESSImport converters[ESM::REC_LEVC] = boost::shared_ptr(new DefaultConverter()); converters[ESM::REC_LEVI] = boost::shared_ptr(new DefaultConverter()); + std::set unknownRecords; for (std::map >::const_iterator it = converters.begin(); it != converters.end(); ++it) @@ -232,7 +233,9 @@ namespace ESSImport } else { - std::cerr << "unknown record " << n.toString() << std::endl; + if (unknownRecords.insert(n.val).second) + std::cerr << "unknown record " << n.toString() << std::endl; + esm.skipRecord(); } } diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 4de9af108..abd1256d7 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -86,35 +86,16 @@ namespace namespace MWGui { - void CustomMarker::save(ESM::ESMWriter &esm) const - { - esm.writeHNT("POSX", mWorldX); - esm.writeHNT("POSY", mWorldY); - mCell.save(esm); - if (!mNote.empty()) - esm.writeHNString("NOTE", mNote); - } - - void CustomMarker::load(ESM::ESMReader &esm) - { - esm.getHNT(mWorldX, "POSX"); - esm.getHNT(mWorldY, "POSY"); - mCell.load(esm); - mNote = esm.getHNOString("NOTE"); - } - - // ------------------------------------------------------ - - void CustomMarkerCollection::addMarker(const CustomMarker &marker, bool triggerEvent) + void CustomMarkerCollection::addMarker(const ESM::CustomMarker &marker, bool triggerEvent) { mMarkers.push_back(marker); if (triggerEvent) eventMarkersChanged(); } - void CustomMarkerCollection::deleteMarker(const CustomMarker &marker) + void CustomMarkerCollection::deleteMarker(const ESM::CustomMarker &marker) { - std::vector::iterator it = std::find(mMarkers.begin(), mMarkers.end(), marker); + std::vector::iterator it = std::find(mMarkers.begin(), mMarkers.end(), marker); if (it != mMarkers.end()) mMarkers.erase(it); else @@ -123,9 +104,9 @@ namespace MWGui eventMarkersChanged(); } - void CustomMarkerCollection::updateMarker(const CustomMarker &marker, const std::string &newNote) + void CustomMarkerCollection::updateMarker(const ESM::CustomMarker &marker, const std::string &newNote) { - std::vector::iterator it = std::find(mMarkers.begin(), mMarkers.end(), marker); + std::vector::iterator it = std::find(mMarkers.begin(), mMarkers.end(), marker); if (it != mMarkers.end()) it->mNote = newNote; else @@ -140,12 +121,12 @@ namespace MWGui eventMarkersChanged(); } - std::vector::const_iterator CustomMarkerCollection::begin() const + std::vector::const_iterator CustomMarkerCollection::begin() const { return mMarkers.begin(); } - std::vector::const_iterator CustomMarkerCollection::end() const + std::vector::const_iterator CustomMarkerCollection::end() const { return mMarkers.end(); } @@ -295,9 +276,9 @@ namespace MWGui MyGUI::Gui::getInstance().destroyWidget(*it); mCustomMarkerWidgets.clear(); - for (std::vector::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) + for (std::vector::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) { - const CustomMarker& marker = *it; + const ESM::CustomMarker& marker = *it; if (marker.mCell.mPaged != !mInterior) continue; @@ -654,7 +635,7 @@ namespace MWGui void MapWindow::onCustomMarkerDoubleClicked(MyGUI::Widget *sender) { - mEditingMarker = *sender->getUserData(); + mEditingMarker = *sender->getUserData(); mEditNoteDialog.setText(mEditingMarker.mNote); mEditNoteDialog.showDeleteButton(true); mEditNoteDialog.setVisible(true); diff --git a/apps/openmw/mwgui/mapwindow.hpp b/apps/openmw/mwgui/mapwindow.hpp index 118fee0f6..684069467 100644 --- a/apps/openmw/mwgui/mapwindow.hpp +++ b/apps/openmw/mwgui/mapwindow.hpp @@ -7,6 +7,8 @@ #include +#include + namespace MWRender { class GlobalMap; @@ -26,43 +28,25 @@ namespace Loading namespace MWGui { - struct CustomMarker - { - float mWorldX; - float mWorldY; - - ESM::CellId mCell; - - std::string mNote; - - bool operator == (const CustomMarker& other) - { - return mNote == other.mNote && mCell == other.mCell && mWorldX == other.mWorldX && mWorldY == other.mWorldY; - } - - void load (ESM::ESMReader& reader); - void save (ESM::ESMWriter& writer) const; - }; - class CustomMarkerCollection { public: - void addMarker(const CustomMarker& marker, bool triggerEvent=true); - void deleteMarker (const CustomMarker& marker); - void updateMarker(const CustomMarker& marker, const std::string& newNote); + void addMarker(const ESM::CustomMarker& marker, bool triggerEvent=true); + void deleteMarker (const ESM::CustomMarker& marker); + void updateMarker(const ESM::CustomMarker& marker, const std::string& newNote); void clear(); size_t size() const; - std::vector::const_iterator begin() const; - std::vector::const_iterator end() const; + std::vector::const_iterator begin() const; + std::vector::const_iterator end() const; typedef MyGUI::delegates::CMultiDelegate0 EventHandle_Void; EventHandle_Void eventMarkersChanged; private: - std::vector mMarkers; + std::vector mMarkers; }; class LocalMapBase @@ -233,7 +217,7 @@ namespace MWGui MWRender::GlobalMap* mGlobalMapRender; EditNoteDialog mEditNoteDialog; - CustomMarker mEditingMarker; + ESM::CustomMarker mEditingMarker; virtual void onPinToggled(); virtual void onTitleDoubleClicked(); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index d5a71bc77..5b2bbee90 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1612,7 +1612,7 @@ namespace MWGui writer.endRecord(ESM::REC_ASPL); } - for (std::vector::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) + for (std::vector::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) { writer.startRecord(ESM::REC_MARK); (*it).save(writer); @@ -1633,7 +1633,7 @@ namespace MWGui } else if (type == ESM::REC_MARK) { - CustomMarker marker; + ESM::CustomMarker marker; marker.load(reader); mCustomMarkers.addMarker(marker, false); } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index a3e79758f..0578a44b0 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -63,7 +63,7 @@ add_component_dir (esm loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile - aisequence magiceffects util + aisequence magiceffects util custommarkerstate ) add_component_dir (esmterrain diff --git a/components/esm/custommarkerstate.cpp b/components/esm/custommarkerstate.cpp new file mode 100644 index 000000000..dc81c123d --- /dev/null +++ b/components/esm/custommarkerstate.cpp @@ -0,0 +1,26 @@ +#include "custommarkerstate.hpp" + +#include "esmwriter.hpp" +#include "esmreader.hpp" + +namespace ESM +{ + +void CustomMarker::save(ESM::ESMWriter &esm) const +{ + esm.writeHNT("POSX", mWorldX); + esm.writeHNT("POSY", mWorldY); + mCell.save(esm); + if (!mNote.empty()) + esm.writeHNString("NOTE", mNote); +} + +void CustomMarker::load(ESM::ESMReader &esm) +{ + esm.getHNT(mWorldX, "POSX"); + esm.getHNT(mWorldY, "POSY"); + mCell.load(esm); + mNote = esm.getHNOString("NOTE"); +} + +} diff --git a/components/esm/custommarkerstate.hpp b/components/esm/custommarkerstate.hpp new file mode 100644 index 000000000..fc9286bfe --- /dev/null +++ b/components/esm/custommarkerstate.hpp @@ -0,0 +1,30 @@ +#ifndef OPENMW_ESM_CUSTOMMARKERSTATE_H +#define OPENMW_ESM_CUSTOMMARKERSTATE_H + +#include "cellid.hpp" + +namespace ESM +{ + +// format 0, saved games only +struct CustomMarker +{ + float mWorldX; + float mWorldY; + + ESM::CellId mCell; + + std::string mNote; + + bool operator == (const CustomMarker& other) + { + return mNote == other.mNote && mCell == other.mCell && mWorldX == other.mWorldX && mWorldY == other.mWorldY; + } + + void load (ESM::ESMReader& reader); + void save (ESM::ESMWriter& writer) const; +}; + +} + +#endif