|
|
|
#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
|
|
|
|
std::string id = esm.getHString();
|
|
|
|
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"))
|
|
|
|
{
|
|
|
|
std::string id = esm.getHString();
|
|
|
|
|
|
|
|
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 std::string& id = entry.first.first;
|
|
|
|
const int count = entry.second;
|
|
|
|
for(auto& item : mItems)
|
|
|
|
{
|
|
|
|
if(item.mCount == count && Misc::StringUtils::ciEqual(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 (std::map<std::pair<std::string, std::string>, int>::const_iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it)
|
|
|
|
{
|
|
|
|
esm.writeHNString ("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.writeHNString("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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|