mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 22:45:36 +00:00
Move away from fixed record names for body parts
This commit is contained in:
parent
0341a9e778
commit
c519fc360d
7 changed files with 118 additions and 146 deletions
|
@ -439,7 +439,7 @@ void Record<ESM::Apparatus>::print()
|
||||||
template<>
|
template<>
|
||||||
void Record<ESM::BodyPart>::print()
|
void Record<ESM::BodyPart>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Name: " << mData.mName << std::endl;
|
std::cout << " Race: " << mData.mRace << std::endl;
|
||||||
std::cout << " Model: " << mData.mModel << std::endl;
|
std::cout << " Model: " << mData.mModel << std::endl;
|
||||||
std::cout << " Type: " << meshTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << meshTypeLabel(mData.mData.mType)
|
||||||
<< " (" << (int)mData.mData.mType << ")" << std::endl;
|
<< " (" << (int)mData.mData.mType << ")" << std::endl;
|
||||||
|
|
|
@ -24,36 +24,6 @@ int wrap(int index, int max)
|
||||||
else
|
else
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int countParts(const std::string &part, const std::string &race, bool male)
|
|
||||||
{
|
|
||||||
/// \todo loop through the whole store for appropriate bodyparts instead of looking for fixed IDs
|
|
||||||
const MWWorld::Store<ESM::BodyPart> &store =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
|
||||||
|
|
||||||
std::string prefix =
|
|
||||||
"b_n_" + race + ((male) ? "_m_" : "_f_") + part;
|
|
||||||
|
|
||||||
std::string suffix;
|
|
||||||
suffix.reserve(prefix.size() + 3);
|
|
||||||
|
|
||||||
int count = -1;
|
|
||||||
do {
|
|
||||||
++count;
|
|
||||||
suffix = "_" + (boost::format("%02d") % (count + 1)).str();
|
|
||||||
}
|
|
||||||
while (store.search(prefix + suffix) != 0);
|
|
||||||
|
|
||||||
if (count == 0 && part == "hair") {
|
|
||||||
count = -1;
|
|
||||||
do {
|
|
||||||
++count;
|
|
||||||
suffix = (boost::format("%02d") % (count + 1)).str();
|
|
||||||
}
|
|
||||||
while (store.search(prefix + suffix) != 0);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RaceDialog::RaceDialog()
|
RaceDialog::RaceDialog()
|
||||||
|
@ -61,8 +31,6 @@ RaceDialog::RaceDialog()
|
||||||
, mGenderIndex(0)
|
, mGenderIndex(0)
|
||||||
, mFaceIndex(0)
|
, mFaceIndex(0)
|
||||||
, mHairIndex(0)
|
, mHairIndex(0)
|
||||||
, mFaceCount(10)
|
|
||||||
, mHairCount(14)
|
|
||||||
, mCurrentAngle(0)
|
, mCurrentAngle(0)
|
||||||
{
|
{
|
||||||
// Centre dialog
|
// Centre dialog
|
||||||
|
@ -227,67 +195,28 @@ void RaceDialog::onSelectNextGender(MyGUI::Widget*)
|
||||||
|
|
||||||
void RaceDialog::onSelectPreviousFace(MyGUI::Widget*)
|
void RaceDialog::onSelectPreviousFace(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
do
|
mFaceIndex = wrap(mFaceIndex - 1, mAvailableHeads.size());
|
||||||
mFaceIndex = wrap(mFaceIndex - 1, mFaceCount);
|
|
||||||
while (!isFacePlayable());
|
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectNextFace(MyGUI::Widget*)
|
void RaceDialog::onSelectNextFace(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
do
|
mFaceIndex = wrap(mFaceIndex + 1, mAvailableHeads.size());
|
||||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
|
||||||
while (!isFacePlayable());
|
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectPreviousHair(MyGUI::Widget*)
|
void RaceDialog::onSelectPreviousHair(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
do
|
mHairIndex = wrap(mHairIndex - 1, mAvailableHairs.size());
|
||||||
mHairIndex = wrap(mHairIndex - 1, mHairCount);
|
|
||||||
while (!isHairPlayable());
|
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RaceDialog::onSelectNextHair(MyGUI::Widget*)
|
void RaceDialog::onSelectNextHair(MyGUI::Widget*)
|
||||||
{
|
{
|
||||||
do
|
mHairIndex = wrap(mHairIndex + 1, mAvailableHairs.size());
|
||||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
|
||||||
while (!isHairPlayable());
|
|
||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RaceDialog::isFacePlayable()
|
|
||||||
{
|
|
||||||
std::string prefix =
|
|
||||||
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
|
||||||
|
|
||||||
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
|
|
||||||
|
|
||||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
|
||||||
|
|
||||||
if (parts.search(prefix + "head_" + headIndex) == 0)
|
|
||||||
return !(parts.find(prefix + "head" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
|
||||||
else
|
|
||||||
return !(parts.find(prefix + "head_" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RaceDialog::isHairPlayable()
|
|
||||||
{
|
|
||||||
std::string prefix =
|
|
||||||
"b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_");
|
|
||||||
|
|
||||||
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
|
|
||||||
|
|
||||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
|
||||||
if (parts.search(prefix + "hair_" + hairIndex) == 0)
|
|
||||||
return !(parts.find(prefix + "hair" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
|
||||||
else
|
|
||||||
return !(parts.find(prefix + "hair_" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
||||||
{
|
{
|
||||||
if (_index == MyGUI::ITEM_NONE)
|
if (_index == MyGUI::ITEM_NONE)
|
||||||
|
@ -308,18 +237,41 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index)
|
||||||
updateSpellPowers();
|
updateSpellPowers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RaceDialog::getBodyParts (int part, std::vector<std::string>& out)
|
||||||
|
{
|
||||||
|
out.clear();
|
||||||
|
const MWWorld::Store<ESM::BodyPart> &store =
|
||||||
|
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
||||||
|
|
||||||
|
for (MWWorld::Store<ESM::BodyPart>::iterator it = store.begin(); it != store.end(); ++it)
|
||||||
|
{
|
||||||
|
const ESM::BodyPart& bodypart = *it;
|
||||||
|
if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable)
|
||||||
|
continue;
|
||||||
|
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
|
||||||
|
continue;
|
||||||
|
if (bodypart.mData.mPart != static_cast<ESM::BodyPart::MeshPart>(part))
|
||||||
|
continue;
|
||||||
|
if (mGenderIndex != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
|
||||||
|
continue;
|
||||||
|
bool firstPerson = (bodypart.mId.size() >= 3)
|
||||||
|
&& bodypart.mId[bodypart.mId.size()-3] == '1'
|
||||||
|
&& bodypart.mId[bodypart.mId.size()-2] == 's'
|
||||||
|
&& bodypart.mId[bodypart.mId.size()-1] == 't';
|
||||||
|
if (firstPerson)
|
||||||
|
continue;
|
||||||
|
if (Misc::StringUtils::ciEqual(bodypart.mRace, mCurrentRaceId))
|
||||||
|
out.push_back(bodypart.mId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RaceDialog::recountParts()
|
void RaceDialog::recountParts()
|
||||||
{
|
{
|
||||||
mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0);
|
getBodyParts(ESM::BodyPart::MP_Hair, mAvailableHairs);
|
||||||
mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0);
|
getBodyParts(ESM::BodyPart::MP_Head, mAvailableHeads);
|
||||||
|
|
||||||
mFaceIndex = 0;
|
mFaceIndex = 0;
|
||||||
mHairIndex = 0;
|
mHairIndex = 0;
|
||||||
|
|
||||||
while (!isHairPlayable())
|
|
||||||
mHairIndex = wrap(mHairIndex + 1, mHairCount);
|
|
||||||
while (!isFacePlayable())
|
|
||||||
mFaceIndex = wrap(mFaceIndex + 1, mFaceCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update widget content
|
// update widget content
|
||||||
|
@ -330,21 +282,9 @@ void RaceDialog::updatePreview()
|
||||||
record.mRace = mCurrentRaceId;
|
record.mRace = mCurrentRaceId;
|
||||||
record.setIsMale(mGenderIndex == 0);
|
record.setIsMale(mGenderIndex == 0);
|
||||||
|
|
||||||
std::string prefix =
|
record.mHead = mAvailableHeads[mFaceIndex];
|
||||||
"b_n_" + mCurrentRaceId + ((record.isMale()) ? "_m_" : "_f_");
|
record.mHair = mAvailableHairs[mHairIndex];
|
||||||
|
|
||||||
std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str();
|
|
||||||
std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str();
|
|
||||||
|
|
||||||
record.mHead = prefix + "head_" + headIndex;
|
|
||||||
record.mHair = prefix + "hair_" + hairIndex;
|
|
||||||
|
|
||||||
const MWWorld::Store<ESM::BodyPart> &parts =
|
|
||||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::BodyPart>();
|
|
||||||
|
|
||||||
if (parts.search(record.mHair) == 0) {
|
|
||||||
record.mHair = prefix + "hair" + hairIndex;
|
|
||||||
}
|
|
||||||
mPreview->setPrototype(record);
|
mPreview->setPrototype(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,10 @@ namespace MWGui
|
||||||
void updatePreview();
|
void updatePreview();
|
||||||
void recountParts();
|
void recountParts();
|
||||||
|
|
||||||
bool isHairPlayable();
|
void getBodyParts (int part, std::vector<std::string>& out);
|
||||||
bool isFacePlayable();
|
|
||||||
|
std::vector<std::string> mAvailableHeads;
|
||||||
|
std::vector<std::string> mAvailableHairs;
|
||||||
|
|
||||||
MyGUI::ImageBox* mPreviewImage;
|
MyGUI::ImageBox* mPreviewImage;
|
||||||
MyGUI::ListBox* mRaceList;
|
MyGUI::ListBox* mRaceList;
|
||||||
|
@ -90,7 +92,6 @@ namespace MWGui
|
||||||
std::vector<MyGUI::Widget*> mSpellPowerItems;
|
std::vector<MyGUI::Widget*> mSpellPowerItems;
|
||||||
|
|
||||||
int mGenderIndex, mFaceIndex, mHairIndex;
|
int mGenderIndex, mFaceIndex, mHairIndex;
|
||||||
int mFaceCount, mHairCount;
|
|
||||||
|
|
||||||
std::string mCurrentRaceId;
|
std::string mCurrentRaceId;
|
||||||
|
|
||||||
|
|
|
@ -305,56 +305,83 @@ void NpcAnimation::updateParts(bool forceupdate)
|
||||||
if(mViewMode == VM_HeadOnly)
|
if(mViewMode == VM_HeadOnly)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
static const struct {
|
std::map<int, int> bodypartMap;
|
||||||
ESM::PartReferenceType type;
|
bodypartMap[ESM::PRT_Neck] = ESM::BodyPart::MP_Neck;
|
||||||
const char name[2][12];
|
bodypartMap[ESM::PRT_Cuirass] = ESM::BodyPart::MP_Chest;
|
||||||
} PartTypeList[] = {
|
bodypartMap[ESM::PRT_Groin] = ESM::BodyPart::MP_Groin;
|
||||||
{ ESM::PRT_Neck, { "neck", "" } },
|
bodypartMap[ESM::PRT_RHand] = ESM::BodyPart::MP_Hand;
|
||||||
{ ESM::PRT_Cuirass, { "chest", "" } },
|
bodypartMap[ESM::PRT_LHand] = ESM::BodyPart::MP_Hand;
|
||||||
{ ESM::PRT_Groin, { "groin", "" } },
|
bodypartMap[ESM::PRT_RWrist] = ESM::BodyPart::MP_Wrist;
|
||||||
{ ESM::PRT_RHand, { "hand", "hands" } },
|
bodypartMap[ESM::PRT_LWrist] = ESM::BodyPart::MP_Wrist;
|
||||||
{ ESM::PRT_LHand, { "hand", "hands" } },
|
bodypartMap[ESM::PRT_RForearm] = ESM::BodyPart::MP_Forearm;
|
||||||
{ ESM::PRT_RWrist, { "wrist", "" } },
|
bodypartMap[ESM::PRT_LForearm] = ESM::BodyPart::MP_Forearm;
|
||||||
{ ESM::PRT_LWrist, { "wrist", "" } },
|
bodypartMap[ESM::PRT_RUpperarm] = ESM::BodyPart::MP_Upperarm;
|
||||||
{ ESM::PRT_RForearm, { "forearm", "" } },
|
bodypartMap[ESM::PRT_LUpperarm] = ESM::BodyPart::MP_Upperarm;
|
||||||
{ ESM::PRT_LForearm, { "forearm", "" } },
|
bodypartMap[ESM::PRT_RFoot] = ESM::BodyPart::MP_Foot;
|
||||||
{ ESM::PRT_RUpperarm, { "upper arm", "" } },
|
bodypartMap[ESM::PRT_LFoot] = ESM::BodyPart::MP_Foot;
|
||||||
{ ESM::PRT_LUpperarm, { "upper arm", "" } },
|
bodypartMap[ESM::PRT_RAnkle] = ESM::BodyPart::MP_Ankle;
|
||||||
{ ESM::PRT_RFoot, { "foot", "feet" } },
|
bodypartMap[ESM::PRT_LAnkle] = ESM::BodyPart::MP_Ankle;
|
||||||
{ ESM::PRT_LFoot, { "foot", "feet" } },
|
bodypartMap[ESM::PRT_RKnee] = ESM::BodyPart::MP_Knee;
|
||||||
{ ESM::PRT_RAnkle, { "ankle", "" } },
|
bodypartMap[ESM::PRT_LKnee] = ESM::BodyPart::MP_Knee;
|
||||||
{ ESM::PRT_LAnkle, { "ankle", "" } },
|
bodypartMap[ESM::PRT_RLeg] = ESM::BodyPart::MP_Upperleg;
|
||||||
{ ESM::PRT_RKnee, { "knee", "" } },
|
bodypartMap[ESM::PRT_LLeg] = ESM::BodyPart::MP_Upperleg;
|
||||||
{ ESM::PRT_LKnee, { "knee", "" } },
|
bodypartMap[ESM::PRT_Tail] = ESM::BodyPart::MP_Tail;
|
||||||
{ ESM::PRT_RLeg, { "upper leg", "" } },
|
|
||||||
{ ESM::PRT_LLeg, { "upper leg", "" } },
|
|
||||||
{ ESM::PRT_Tail, { "tail", "" } }
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
|
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++)
|
|
||||||
|
const int Flag_Female = 0x01;
|
||||||
|
const int Flag_FirstPerson = 0x02;
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
if (!mNpc->isMale())
|
||||||
|
flags |= Flag_Female;
|
||||||
|
if (mViewMode == VM_FirstPerson)
|
||||||
|
flags |= Flag_FirstPerson;
|
||||||
|
|
||||||
|
// Remember body parts so we only have to search through the store once for each race/gender/viewmode combination
|
||||||
|
static std::map< std::pair<std::string, int> , std::vector<const ESM::BodyPart*> > sRaceMapping;
|
||||||
|
std::string race = Misc::StringUtils::lowerCase(mNpc->mRace);
|
||||||
|
std::pair<std::string, int> thisCombination = std::make_pair(race, flags);
|
||||||
|
if (sRaceMapping.find(thisCombination) == sRaceMapping.end())
|
||||||
{
|
{
|
||||||
if(mPartPriorities[PartTypeList[i].type] < 1)
|
sRaceMapping[thisCombination].resize(ESM::PRT_Count);
|
||||||
{
|
for (int i=0; i<ESM::PRT_Count; ++i)
|
||||||
const ESM::BodyPart *part = NULL;
|
sRaceMapping[thisCombination][i] = NULL;
|
||||||
|
|
||||||
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
||||||
|
|
||||||
if(!mNpc->isMale())
|
for (MWWorld::Store<ESM::BodyPart>::iterator it = partStore.begin(); it != partStore.end(); ++it)
|
||||||
{
|
{
|
||||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]+ext);
|
const ESM::BodyPart& bodypart = *it;
|
||||||
if(part == 0)
|
if (bodypart.mData.mFlags & ESM::BodyPart::BPF_NotPlayable)
|
||||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]+ext);
|
continue;
|
||||||
|
if (bodypart.mData.mType != ESM::BodyPart::MT_Skin)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if(part == 0)
|
if (!mNpc->isMale() != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
|
||||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]+ext);
|
continue;
|
||||||
if(part == 0)
|
if (!Misc::StringUtils::ciEqual(bodypart.mRace, mNpc->mRace))
|
||||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]+ext);
|
continue;
|
||||||
|
|
||||||
if(part)
|
bool firstPerson = (bodypart.mId.size() >= 3)
|
||||||
addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->mModel);
|
&& bodypart.mId[bodypart.mId.size()-3] == '1'
|
||||||
|
&& bodypart.mId[bodypart.mId.size()-2] == 's'
|
||||||
|
&& bodypart.mId[bodypart.mId.size()-1] == 't';
|
||||||
|
if (firstPerson != (mViewMode == VM_FirstPerson))
|
||||||
|
continue;
|
||||||
|
for (std::map<int, int>::iterator bIt = bodypartMap.begin(); bIt != bodypartMap.end(); ++bIt )
|
||||||
|
if (bIt->second == bodypart.mData.mPart)
|
||||||
|
sRaceMapping[thisCombination][bIt->first] = &*it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int part = ESM::PRT_Neck; part < ESM::PRT_Count; ++part)
|
||||||
|
{
|
||||||
|
const ESM::BodyPart* bodypart = sRaceMapping[thisCombination][part];
|
||||||
|
if (mPartPriorities[part] < 1 && bodypart)
|
||||||
|
addOrReplaceIndividualPart(part, -1,1, "meshes\\"+bodypart->mModel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename)
|
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename)
|
||||||
|
|
|
@ -38,7 +38,9 @@ enum PartReferenceType
|
||||||
PRT_RPauldron = 23,
|
PRT_RPauldron = 23,
|
||||||
PRT_LPauldron = 24,
|
PRT_LPauldron = 24,
|
||||||
PRT_Weapon = 25,
|
PRT_Weapon = 25,
|
||||||
PRT_Tail = 26
|
PRT_Tail = 26,
|
||||||
|
|
||||||
|
PRT_Count = 27
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reference to body parts
|
// Reference to body parts
|
||||||
|
|
|
@ -9,13 +9,13 @@ namespace ESM
|
||||||
void BodyPart::load(ESMReader &esm)
|
void BodyPart::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
mModel = esm.getHNString("MODL");
|
mModel = esm.getHNString("MODL");
|
||||||
mName = esm.getHNString("FNAM");
|
mRace = esm.getHNString("FNAM");
|
||||||
esm.getHNT(mData, "BYDT", 4);
|
esm.getHNT(mData, "BYDT", 4);
|
||||||
}
|
}
|
||||||
void BodyPart::save(ESMWriter &esm)
|
void BodyPart::save(ESMWriter &esm)
|
||||||
{
|
{
|
||||||
esm.writeHNCString("MODL", mModel);
|
esm.writeHNCString("MODL", mModel);
|
||||||
esm.writeHNCString("FNAM", mName);
|
esm.writeHNCString("FNAM", mRace);
|
||||||
esm.writeHNT("BYDT", mData, 4);
|
esm.writeHNT("BYDT", mData, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,9 @@ struct BodyPart
|
||||||
MP_Knee = 11,
|
MP_Knee = 11,
|
||||||
MP_Upperleg = 12,
|
MP_Upperleg = 12,
|
||||||
MP_Clavicle = 13,
|
MP_Clavicle = 13,
|
||||||
MP_Tail = 14
|
MP_Tail = 14,
|
||||||
|
|
||||||
|
MP_Count = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Flags
|
enum Flags
|
||||||
|
@ -52,7 +54,7 @@ struct BodyPart
|
||||||
};
|
};
|
||||||
|
|
||||||
BYDTstruct mData;
|
BYDTstruct mData;
|
||||||
std::string mId, mModel, mName;
|
std::string mId, mModel, mRace;
|
||||||
|
|
||||||
void load(ESMReader &esm);
|
void load(ESMReader &esm);
|
||||||
void save(ESMWriter &esm);
|
void save(ESMWriter &esm);
|
||||||
|
|
Loading…
Reference in a new issue