You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/components/esm3/inventorystate.cpp

179 lines
5.0 KiB
C++

#include "inventorystate.hpp"
#include "esmreader.hpp"
#include "esmwriter.hpp"
#include <components/misc/strings/algorithm.hpp>
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<std::pair<float, float>> 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<int>(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<std::pair<float, float>>& params = it->second;
for (std::vector<std::pair<float, float>>::const_iterator pIt = params.begin(); pIt != params.end(); ++pIt)
{
esm.writeHNT("RAND", pIt->first);
esm.writeHNT("MULT", pIt->second);
}
}
int slotsCount = static_cast<int>(mEquipmentSlots.size());
if (slotsCount > 0)
{
esm.startSubRecord("EQIP");
esm.writeT(slotsCount);
for (std::map<int, int>::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);
}
}