#include "inventorystate.hpp" #include "esmreader.hpp" #include "esmwriter.hpp" #include namespace ESM { void InventoryState::load(ESMReader& esm) { // obsolete int index = 0; while (esm.isNextSub("IOBJ")) { int unused; // no longer used esm.getHT(unused); ObjectState state; // obsolete if (esm.isNextSub("SLOT")) { int slot; esm.getHT(slot); mEquipmentSlots[index] = slot; } state.mRef.loadId(esm, true); state.load(esm); if (state.mCount == 0) continue; mItems.push_back(state); ++index; } int itemsCount = 0; esm.getHNOT(itemsCount, "ICNT"); for (int i = 0; i < itemsCount; i++) { ObjectState state; state.mRef.loadId(esm, true); state.load(esm); if (state.mCount == 0) continue; mItems.push_back(state); } // Next item is Levelled item while (esm.isNextSub("LEVM")) { // Get its name ESM::RefId id = esm.getRefId(); int count; std::string parentGroup; // Then get its count esm.getHNT(count, "COUN"); // Old save formats don't have information about parent group; check for that if (esm.isNextSub("LGRP")) // Newest saves contain parent group parentGroup = esm.getHString(); mLevelledItemMap[std::make_pair(id, parentGroup)] = count; } while (esm.isNextSub("MAGI")) { ESM::RefId id = esm.getRefId(); std::vector> params; while (esm.isNextSub("RAND")) { float rand, multiplier; esm.getHT(rand); esm.getHNT(multiplier, "MULT"); params.emplace_back(rand, multiplier); } mPermanentMagicEffectMagnitudes[id] = params; } while (esm.isNextSub("EQUI")) { esm.getSubHeader(); int equipIndex; esm.getT(equipIndex); int slot; esm.getT(slot); mEquipmentSlots[equipIndex] = slot; } if (esm.isNextSub("EQIP")) { esm.getSubHeader(); int slotsCount = 0; esm.getT(slotsCount); for (int i = 0; i < slotsCount; i++) { int equipIndex; esm.getT(equipIndex); int slot; esm.getT(slot); mEquipmentSlots[equipIndex] = slot; } } mSelectedEnchantItem = -1; esm.getHNOT(mSelectedEnchantItem, "SELE"); // Old saves had restocking levelled items in a special map // This turns items from that map into negative quantities for (const auto& entry : mLevelledItemMap) { const ESM::RefId& id = entry.first.first; const int count = entry.second; for (auto& item : mItems) { if (item.mCount == count && id == item.mRef.mRefID) item.mCount = -count; } } } void InventoryState::save(ESMWriter& esm) const { int itemsCount = static_cast(mItems.size()); if (itemsCount > 0) { esm.writeHNT("ICNT", itemsCount); for (const ObjectState& state : mItems) { state.save(esm, true); } } for (auto it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it) { esm.writeHNRefId("LEVM", it->first.first); esm.writeHNT("COUN", it->second); esm.writeHNString("LGRP", it->first.second); } for (TEffectMagnitudes::const_iterator it = mPermanentMagicEffectMagnitudes.begin(); it != mPermanentMagicEffectMagnitudes.end(); ++it) { esm.writeHNRefId("MAGI", it->first); const std::vector>& params = it->second; for (std::vector>::const_iterator pIt = params.begin(); pIt != params.end(); ++pIt) { esm.writeHNT("RAND", pIt->first); esm.writeHNT("MULT", pIt->second); } } int slotsCount = static_cast(mEquipmentSlots.size()); if (slotsCount > 0) { esm.startSubRecord("EQIP"); esm.writeT(slotsCount); for (std::map::const_iterator it = mEquipmentSlots.begin(); it != mEquipmentSlots.end(); ++it) { esm.writeT(it->first); esm.writeT(it->second); } esm.endRecord("EQIP"); } if (mSelectedEnchantItem != -1) esm.writeHNT("SELE", mSelectedEnchantItem); } }