From e27e53f607550f65c6b7b962fc5151f20b2d7101 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 30 Mar 2013 20:04:05 +0100 Subject: [PATCH] Fix not playable body parts appearing in the race selection menu. --- apps/esmtool/labels.cpp | 4 +- apps/openmw/mwgui/container.cpp | 3 - apps/openmw/mwgui/race.cpp | 138 ++++++++++++++++++++---------- apps/openmw/mwgui/race.hpp | 3 + apps/openmw/mwgui/tradewindow.cpp | 3 - components/esm/loadbody.hpp | 2 +- 6 files changed, 99 insertions(+), 54 deletions(-) diff --git a/apps/esmtool/labels.cpp b/apps/esmtool/labels.cpp index f08c31003c..3fb1166e8e 100644 --- a/apps/esmtool/labels.cpp +++ b/apps/esmtool/labels.cpp @@ -627,10 +627,10 @@ std::string bodyPartFlags(int flags) std::string properties = ""; if (flags == 0) properties += "[None] "; if (flags & ESM::BodyPart::BPF_Female) properties += "Female "; - if (flags & ESM::BodyPart::BPF_Playable) properties += "Playable "; + if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable "; int unused = (0xFFFFFFFF ^ (ESM::BodyPart::BPF_Female| - ESM::BodyPart::BPF_Playable)); + ESM::BodyPart::BPF_NotPlayable)); if (flags & unused) properties += "Invalid "; properties += str(boost::format("(0x%08X)") % flags); return properties; diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 36e32c822d..7836fee16e 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -140,9 +140,6 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) if (isInventory()) { - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - // the player is trying to sell an item, check if the merchant accepts it if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)) { diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 1436995c53..be693eb2ba 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -19,6 +19,49 @@ using namespace MWGui; using namespace Widgets; +namespace +{ +int wrap(int index, int max) +{ + if (index < 0) + return max - 1; + else if (index >= max) + return 0; + else + 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 &store = + MWBase::Environment::get().getWorld()->getStore().get(); + + 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(MWBase::WindowManager& parWindowManager) : WindowModal("openmw_chargen_race.layout", parWindowManager) , mGenderIndex(0) @@ -144,45 +187,6 @@ void RaceDialog::setRaceId(const std::string &raceId) updateSpellPowers(); } -int wrap(int index, int max) -{ - if (index < 0) - return max - 1; - else if (index >= max) - return 0; - else - return index; -} - -int countParts(const std::string &part, const std::string &race, bool male) -{ - const MWWorld::Store &store = - MWBase::Environment::get().getWorld()->getStore().get(); - - 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; -} - void RaceDialog::close() { delete mPreview; @@ -229,28 +233,67 @@ void RaceDialog::onSelectNextGender(MyGUI::Widget*) void RaceDialog::onSelectPreviousFace(MyGUI::Widget*) { - mFaceIndex = wrap(mFaceIndex - 1, mFaceCount); + do + mFaceIndex = wrap(mFaceIndex - 1, mFaceCount); + while (!isFacePlayable()); updatePreview(); } void RaceDialog::onSelectNextFace(MyGUI::Widget*) { - mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); + do + mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); + while (!isFacePlayable()); updatePreview(); } void RaceDialog::onSelectPreviousHair(MyGUI::Widget*) { - mHairIndex = wrap(mHairIndex - 1, mHairCount); + do + mHairIndex = wrap(mHairIndex - 1, mHairCount); + while (!isHairPlayable()); updatePreview(); } void RaceDialog::onSelectNextHair(MyGUI::Widget*) { - mHairIndex = wrap(mHairIndex + 1, mHairCount); + do + mHairIndex = wrap(mHairIndex + 1, mHairCount); + while (!isHairPlayable()); 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 &parts = + MWBase::Environment::get().getWorld()->getStore().get(); + + 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 &parts = + MWBase::Environment::get().getWorld()->getStore().get(); + 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) { if (_index == MyGUI::ITEM_NONE) @@ -273,11 +316,16 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) void RaceDialog::recountParts() { + mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); + mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); + mFaceIndex = 0; mHairIndex = 0; - mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); - mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); + while (!isHairPlayable()) + mHairIndex = wrap(mHairIndex + 1, mHairCount); + while (!isFacePlayable()) + mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); } // update widget content diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index efd08f4395..0ca440ad53 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -81,6 +81,9 @@ namespace MWGui void updatePreview(); void recountParts(); + bool isHairPlayable(); + bool isFacePlayable(); + MyGUI::ImageBox* mPreviewImage; MyGUI::ListBox* mRaceList; MyGUI::ScrollBar* mHeadRotate; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index f474f756df..ab9f3a3101 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -129,9 +129,6 @@ namespace MWGui MWWorld::Ptr gold; MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore(); - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - for (MWWorld::ContainerStoreIterator it = playerStore.begin(); it != playerStore.end(); ++it) { diff --git a/components/esm/loadbody.hpp b/components/esm/loadbody.hpp index c91bb40bf2..c467b36251 100644 --- a/components/esm/loadbody.hpp +++ b/components/esm/loadbody.hpp @@ -33,7 +33,7 @@ struct BodyPart enum Flags { BPF_Female = 1, - BPF_Playable = 2 + BPF_NotPlayable = 2 }; enum MeshType