From 2fe135d85f3b73be2554d5ce524591e3d7c1b1bb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 2 Dec 2013 16:25:26 +0100 Subject: [PATCH 01/12] journals subview was bound to the wrong universal ID type --- apps/opencs/view/world/subviews.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 48c32e171..74ce03cce 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -58,7 +58,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Topics, new CSVDoc::SubViewFactoryWithCreator); - manager.add (CSMWorld::UniversalId::Type_Journal, + manager.add (CSMWorld::UniversalId::Type_Journals, new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_TopicInfos, From 47c60a703767c407e21f4ce7e0e06f6770afa12f Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Wed, 4 Dec 2013 21:48:25 +0100 Subject: [PATCH 02/12] Fix C4716 (Must return a value) error on Windows MSVC --- components/nifogre/particles.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/nifogre/particles.cpp b/components/nifogre/particles.cpp index 006a570dc..d902387b9 100644 --- a/components/nifogre/particles.cpp +++ b/components/nifogre/particles.cpp @@ -27,6 +27,7 @@ public: Ogre::String doGet(const void *target) const { assert(false && "Unimplemented"); + return ""; } void doSet(void *target, const Ogre::String &val) { @@ -41,6 +42,7 @@ public: Ogre::String doGet(const void *target) const { assert(false && "Unimplemented"); + return ""; } void doSet(void *target, const Ogre::String &val) { @@ -563,6 +565,7 @@ public: Ogre::String doGet(const void *target) const { assert(false && "Unimplemented"); + return ""; } void doSet(void *target, const Ogre::String &val) { @@ -577,6 +580,7 @@ public: Ogre::String doGet(const void *target) const { assert(false && "Unimplemented"); + return ""; } void doSet(void *target, const Ogre::String &val) { From bfd79bfbe6135430f02e58deb4bc6157110c039e Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 6 Dec 2013 07:36:16 +0100 Subject: [PATCH 03/12] Various fixes for CppCheck warnings. Signed-off-by: Lukasz Gromanowski --- apps/esmtool/record.hpp | 7 ++++++- apps/launcher/datafilespage.cpp | 10 ++-------- apps/opencs/model/filter/andnode.hpp | 2 -- apps/opencs/model/filter/ornode.hpp | 2 -- apps/opencs/model/filter/parser.cpp | 8 ++++---- apps/opencs/model/settings/settingsitem.hpp | 6 +++++- apps/openmw/mwmechanics/aisequence.cpp | 1 + apps/openmw/mwmechanics/character.cpp | 2 +- apps/openmw/mwworld/weather.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 2 +- components/esm/loadland.cpp | 4 ++-- components/esm/loadland.hpp | 4 ++-- extern/oics/tinyxml.h | 2 +- libs/openengine/bullet/BtOgre.cpp | 2 ++ 14 files changed, 28 insertions(+), 26 deletions(-) diff --git a/apps/esmtool/record.hpp b/apps/esmtool/record.hpp index 78cf5d436..45b6d0426 100644 --- a/apps/esmtool/record.hpp +++ b/apps/esmtool/record.hpp @@ -24,7 +24,12 @@ namespace EsmTool bool mPrintPlain; public: - RecordBase () { mPrintPlain = false; } + RecordBase () + : mFlags(0) + , mPrintPlain(false) + { + } + virtual ~RecordBase() {} const std::string &getId() const { diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index d5eb458f8..362d7562c 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -75,14 +75,8 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile) mLauncherSettings.setValue(QString("Profiles/currentprofile"), ui.profilesComboBox->currentText()); foreach(const ContentSelectorModel::EsmFile *item, items) { - - if (item->gameFiles().size() == 0) { - mLauncherSettings.setMultiValue(QString("Profiles/") + profileName, item->fileName()); - mGameSettings.setMultiValue(QString("content"), item->fileName()); - } else { - mLauncherSettings.setMultiValue(QString("Profiles/") + profileName, item->fileName()); - mGameSettings.setMultiValue(QString("content"), item->fileName()); - } + mLauncherSettings.setMultiValue(QString("Profiles/") + profileName, item->fileName()); + mGameSettings.setMultiValue(QString("content"), item->fileName()); } } diff --git a/apps/opencs/model/filter/andnode.hpp b/apps/opencs/model/filter/andnode.hpp index 980ea554c..887175700 100644 --- a/apps/opencs/model/filter/andnode.hpp +++ b/apps/opencs/model/filter/andnode.hpp @@ -7,8 +7,6 @@ namespace CSMFilter { class AndNode : public NAryNode { - bool mAnd; - public: AndNode (const std::vector >& nodes); diff --git a/apps/opencs/model/filter/ornode.hpp b/apps/opencs/model/filter/ornode.hpp index 63ed2f10c..c39e35095 100644 --- a/apps/opencs/model/filter/ornode.hpp +++ b/apps/opencs/model/filter/ornode.hpp @@ -7,8 +7,6 @@ namespace CSMFilter { class OrNode : public NAryNode { - bool mAnd; - public: OrNode (const std::vector >& nodes); diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index 8f4fcb70c..6e286d943 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -61,11 +61,11 @@ namespace CSMFilter bool isString() const; }; - Token::Token (Type type) : mType (type) {} + Token::Token (Type type) : mType (type), mNumber(0.0) {} - Token::Token (Type type, const std::string& string) : mType (type), mString (string) {} + Token::Token (Type type, const std::string& string) : mType (type), mString (string), mNumber(0.0) {} - Token::Token (const std::string& string) : mType (Type_String), mString (string) {} + Token::Token (const std::string& string) : mType (Type_String), mString (string), mNumber(0.0) {} Token::Token (double number) : mType (Type_Number), mNumber (number) {} @@ -614,4 +614,4 @@ boost::shared_ptr CSMFilter::Parser::getFilter() const throw std::logic_error ("No filter available"); return mFilter; -} \ No newline at end of file +} diff --git a/apps/opencs/model/settings/settingsitem.hpp b/apps/opencs/model/settings/settingsitem.hpp index a1daee4ac..87a85e8e4 100644 --- a/apps/opencs/model/settings/settingsitem.hpp +++ b/apps/opencs/model/settings/settingsitem.hpp @@ -44,7 +44,11 @@ namespace CSMSettings inline QStringPair *getValuePair() { return mValuePair; } /// set value range (spinbox / integer use) - inline void setValuePair (QStringPair valuePair) { mValuePair = new QStringPair(valuePair); } + inline void setValuePair (QStringPair valuePair) + { + delete mValuePair; + mValuePair = new QStringPair(valuePair); + } inline bool isMultivalue () { return mIsMultiValue; } diff --git a/apps/openmw/mwmechanics/aisequence.cpp b/apps/openmw/mwmechanics/aisequence.cpp index d5fb76ede..6d461e5f6 100644 --- a/apps/openmw/mwmechanics/aisequence.cpp +++ b/apps/openmw/mwmechanics/aisequence.cpp @@ -37,6 +37,7 @@ MWMechanics::AiSequence& MWMechanics::AiSequence::operator= (const AiSequence& s { clear(); copy (sequence); + mDone = sequence.mDone; } return *this; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 7505d3405..68f87ef4c 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1109,7 +1109,7 @@ void CharacterController::resurrect() if(mAnimation) mAnimation->disable(mCurrentDeath); - mCurrentDeath.empty(); + mCurrentDeath.clear(); mDeathState = CharState_None; } diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index 6f5dbe23f..8b05d2256 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -473,7 +473,7 @@ void WeatherManager::update(float duration) { // pick a random sound int sound = rand() % 4; - std::string* soundName; + std::string* soundName = NULL; if (sound == 0) soundName = &mThunderSoundID0; else if (sound == 1) soundName = &mThunderSoundID1; else if (sound == 2) soundName = &mThunderSoundID2; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 87a8d7d6f..a1aad0011 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -214,7 +214,7 @@ namespace MWWorld : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mCells (mStore, mEsm), mActivationDistanceOverride (mActivationDistanceOverride), - mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true), + mFallback(fallbackMap), mPlayIntro(0), mTeleportEnabled(true), mLevitationEnabled(false), mFacedDistance(FLT_MAX), mGodMode(false) { mPhysics = new PhysicsSystem(renderer); diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index ede200d79..9c97eaa4d 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -160,10 +160,10 @@ void Land::loadData(int flags) } mEsm->restoreContext(mContext); - memset(mLandData->mNormals, 0, LAND_NUM_VERTS * 3); + memset(mLandData->mNormals, 0, sizeof(mLandData->mNormals)); if (mEsm->isNextSub("VNML")) { - condLoad(actual, DATA_VNML, mLandData->mNormals, sizeof(VNML)); + condLoad(actual, DATA_VNML, mLandData->mNormals, sizeof(mLandData->mNormals)); } if (mEsm->isNextSub("VHGT")) { diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 5649f9980..32abb7799 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -72,13 +72,13 @@ struct Land }; #pragma pack(pop) - typedef signed char VNML[LAND_NUM_VERTS * 3]; + typedef signed char VNML; struct LandData { float mHeightOffset; float mHeights[LAND_NUM_VERTS]; - VNML mNormals; + VNML mNormals[LAND_NUM_VERTS * 3]; uint16_t mTextures[LAND_NUM_TEXTURES]; bool mUsingColours; diff --git a/extern/oics/tinyxml.h b/extern/oics/tinyxml.h index e69913b59..50ad417fe 100644 --- a/extern/oics/tinyxml.h +++ b/extern/oics/tinyxml.h @@ -349,7 +349,7 @@ protected: { //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { + for( int i=0; i<*length && p[i]; ++i ) { _value[i] = p[i]; } return p + (*length); diff --git a/libs/openengine/bullet/BtOgre.cpp b/libs/openengine/bullet/BtOgre.cpp index b0fa07fd6..de9ea6f57 100644 --- a/libs/openengine/bullet/BtOgre.cpp +++ b/libs/openengine/bullet/BtOgre.cpp @@ -819,6 +819,8 @@ namespace BtOgre { */ DynamicRenderable::DynamicRenderable() + : mVertexBufferCapacity(0) + , mIndexBufferCapacity(0) { } From baacf91de4bab1487061d3f838adf965f8a399a8 Mon Sep 17 00:00:00 2001 From: "Alexander \"Ace\" Olofsson" Date: Fri, 6 Dec 2013 11:37:29 +0100 Subject: [PATCH 04/12] Another windows build fix --- apps/openmw/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index b1bbb14f2..0dcc5b36d 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -282,9 +282,11 @@ int main(int argc, char**argv) } catch (std::exception &e) { +#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE if (isatty(fileno(stdin))) std::cerr << "\nERROR: " << e.what() << std::endl; else +#endif SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL); return 1; From e01085cac533300f0cb1cacb3bca1597a6547d49 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 7 Dec 2013 02:57:30 +0100 Subject: [PATCH 05/12] Fixes #1015: Player status window scroll state resets on status change Removed resetting scroll state position. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwgui/statswindow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 9facdac40..fabf1bccc 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -420,8 +420,6 @@ namespace MWGui } mSkillWidgets.clear(); - mSkillView->setViewOffset (MyGUI::IntPoint(0,0)); - const int valueSize = 40; MyGUI::IntCoord coord1(10, 0, mSkillView->getWidth() - (10 + valueSize) - 24, 18); MyGUI::IntCoord coord2(coord1.left + coord1.width, coord1.top, valueSize, coord1.height); From 8d63f8eea221e2aff758673e15cb373d64b4381b Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 7 Dec 2013 21:00:46 +0100 Subject: [PATCH 06/12] Fixes #998: Setting the max health should also set the current health Added setting current value of dynamic stat in OpSetDynamic class. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwscript/statsextensions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 603515ff4..6cd483ae1 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -209,6 +209,7 @@ namespace MWScript .getDynamic (mIndex)); stat.setModified (value, 0); + stat.setCurrent(value); MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); } From 594cc693b27f5c4a6621ce7d8f63a9c5b27edcab Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sun, 8 Dec 2013 21:47:43 +0100 Subject: [PATCH 07/12] Fixes #1006: Many NPCs have 0 skill Added calculation of skill values for NPC with mNpdtType set to NPC_WITH_AUTOCALCULATED_STATS (their NPDT is 12). Signed-off-by: Lukasz Gromanowski --- apps/esmtool/record.cpp | 5 +- apps/openmw/mwclass/npc.cpp | 93 ++++++++++++++++++++++++++-- apps/openmw/mwmechanics/npcstats.cpp | 4 +- components/esm/loadnpc.cpp | 12 ++-- components/esm/loadnpc.hpp | 9 ++- 5 files changed, 106 insertions(+), 17 deletions(-) diff --git a/apps/esmtool/record.cpp b/apps/esmtool/record.cpp index e9fb1c537..cc09452c9 100644 --- a/apps/esmtool/record.cpp +++ b/apps/esmtool/record.cpp @@ -989,8 +989,7 @@ void Record::print() std::cout << " Faction: " << mData.mFaction << std::endl; std::cout << " Flags: " << npcFlags(mData.mFlags) << std::endl; - // Seriously? - if (mData.mNpdt52.mGold == -10) + if (mData.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) { std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl; std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl; @@ -1022,7 +1021,7 @@ void Record::print() std::cout << " Luck: " << (int)mData.mNpdt52.mLuck << std::endl; std::cout << " Skills:" << std::endl; - for (int i = 0; i != 27; i++) + for (int i = 0; i != ESM::Skill::Length; i++) std::cout << " " << skillLabel(i) << ": " << (int)((unsigned char)mData.mNpdt52.mSkills[i]) << std::endl; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 8ff8081bc..e7c10d3c8 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -63,7 +63,6 @@ namespace bool male = (npc->mFlags & ESM::NPC::Female) == 0; int level = creatureStats.getLevel(); - for (int i=0; imData.mAttributeValues[i]; @@ -85,7 +84,7 @@ namespace } // skill bonus - for (int attribute=0; attribute (0.5 * (strength + endurance)) + multiplier * (creatureStats.getLevel() - 1)); } + + /** + * @brief autoCalculateSkills + * + * Skills are calculated with following formulae ( http://www.uesp.net/wiki/Morrowind:NPCs#Skills ): + * + * Skills: (Level - 1) × (Majority Multiplier + Specialization Multiplier) + * + * The Majority Multiplier is 1.0 for a Major or Minor Skill, or 0.1 for a Miscellaneous Skill. + * + * The Specialization Multiplier is 0.5 for a Skill in the same Specialization as the class, + * zero for other Skills. + * + * and by adding class, race, specialization bonus. + */ + void autoCalculateSkills(const ESM::NPC* npc, MWMechanics::NpcStats& npcStats) + { + const ESM::Class *class_ = + MWBase::Environment::get().getWorld()->getStore().get().find(npc->mClass); + + unsigned int level = npcStats.getLevel(); + + const ESM::Race *race = MWBase::Environment::get().getWorld()->getStore().get().find(npc->mRace); + + + for (int i = 0; i < 2; ++i) + { + int bonus = (i==0) ? 10 : 25; + + for (int i2 = 0; i2 < 5; ++i2) + { + int index = class_->mData.mSkills[i2][i]; + if (index >= 0 && index < ESM::Skill::Length) + { + npcStats.getSkill(index).setBase (npcStats.getSkill(index).getBase() + bonus); + } + } + } + + for (int skillIndex = 0; skillIndex < ESM::Skill::Length; ++skillIndex) + { + float majorMultiplier = 0.1f; + float specMultiplier = 0.0f; + + int raceBonus = 0; + int specBonus = 0; + + for (int raceSkillIndex = 0; raceSkillIndex < 7; ++raceSkillIndex) + { + if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex) + { + raceBonus = race->mData.mBonus[raceSkillIndex].mBonus; + break; + } + } + + for (int k = 0; k < 5; ++k) + { + // is this a minor or major skill? + if ((class_->mData.mSkills[k][0] == skillIndex) || (class_->mData.mSkills[k][1] == skillIndex)) + { + majorMultiplier = 1.0f; + break; + } + } + + // is this skill in the same Specialization as the class? + const ESM::Skill* skill = MWBase::Environment::get().getWorld()->getStore().get().find(skillIndex); + if (skill->mData.mSpecialization == class_->mData.mSpecialization) + { + specMultiplier = 0.5f; + specBonus = 5; + } + + npcStats.getSkill(skillIndex).setBase( + std::min( + npcStats.getSkill(skillIndex).getBase() + + 5 + + raceBonus + + specBonus + + static_cast((level-1) * (majorMultiplier + specMultiplier)), 100.0f)); + } + } } namespace MWClass @@ -173,7 +255,7 @@ namespace MWClass { std::string faction = ref->mBase->mFaction; Misc::StringUtils::toLower(faction); - if(ref->mBase->mNpdt52.mGold != -10) + if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) { data->mNpcStats.getFactionRanks()[faction] = (int)ref->mBase->mNpdt52.mRank; } @@ -185,11 +267,11 @@ namespace MWClass // creature stats int gold=0; - if(ref->mBase->mNpdt52.mGold != -10) + if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) { gold = ref->mBase->mNpdt52.mGold; - for (int i=0; i<27; ++i) + for (unsigned int i=0; i< ESM::Skill::Length; ++i) data->mNpcStats.getSkill (i).setBase (ref->mBase->mNpdt52.mSkills[i]); data->mNpcStats.getAttribute(0).set (ref->mBase->mNpdt52.mStrength); @@ -220,6 +302,7 @@ namespace MWClass data->mNpcStats.setReputation(ref->mBase->mNpdt12.mReputation); autoCalculateAttributes(ref->mBase, data->mNpcStats); + autoCalculateSkills(ref->mBase, data->mNpcStats); } data->mNpcStats.getAiSequence().fill(ref->mBase->mAiPackage); diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 0b3698289..1fdefc84f 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -86,7 +86,7 @@ void MWMechanics::NpcStats::setMovementFlag (Flag flag, bool state) const MWMechanics::Stat& MWMechanics::NpcStats::getSkill (int index) const { - if (index<0 || index>=27) + if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); @@ -94,7 +94,7 @@ const MWMechanics::Stat& MWMechanics::NpcStats::getSkill (int index) cons MWMechanics::Stat& MWMechanics::NpcStats::getSkill (int index) { - if (index<0 || index>=27) + if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 9fff2d885..e5b851bf0 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -10,7 +10,7 @@ namespace ESM void NPC::load(ESMReader &esm) { - mNpdt52.mGold = -10; + //mNpdt52.mGold = -10; mPersistent = esm.getRecordFlags() & 0x0400; @@ -29,12 +29,12 @@ void NPC::load(ESMReader &esm) esm.getSubHeader(); if (esm.getSubSize() == 52) { - mNpdtType = 52; + mNpdtType = NPC_DEFAULT; esm.getExact(&mNpdt52, 52); } else if (esm.getSubSize() == 12) { - mNpdtType = 12; + mNpdtType = NPC_WITH_AUTOCALCULATED_STATS; esm.getExact(&mNpdt12, 12); } else @@ -76,9 +76,9 @@ void NPC::save(ESMWriter &esm) const esm.writeHNCString("KNAM", mHair); esm.writeHNOCString("SCRI", mScript); - if (mNpdtType == 52) + if (mNpdtType == NPC_DEFAULT) esm.writeHNT("NPDT", mNpdt52, 52); - else if (mNpdtType == 12) + else if (mNpdtType == NPC_WITH_AUTOCALCULATED_STATS) esm.writeHNT("NPDT", mNpdt12, 12); esm.writeHNT("FLAG", mFlags); @@ -114,7 +114,7 @@ void NPC::save(ESMWriter &esm) const mNpdt52.mLevel = 0; mNpdt52.mStrength = mNpdt52.mIntelligence = mNpdt52.mWillpower = mNpdt52.mAgility = mNpdt52.mSpeed = mNpdt52.mEndurance = mNpdt52.mPersonality = mNpdt52.mLuck = 0; - for (int i=0; i<27; ++i) mNpdt52.mSkills[i] = 0; + for (int i=0; i< Skill::Length; ++i) mNpdt52.mSkills[i] = 0; mNpdt52.mReputation = 0; mNpdt52.mHealth = mNpdt52.mMana = mNpdt52.mFatigue = 0; mNpdt52.mDisposition = 0; diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index d9e691669..1eac8d64f 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -8,6 +8,7 @@ #include "loadcont.hpp" #include "aipackage.hpp" #include "spelllist.hpp" +#include "loadskil.hpp" namespace ESM { @@ -58,6 +59,12 @@ struct NPC Metal = 0x0800 // Metal blood effect (golden?) }; + enum NpcType + { + NPC_WITH_AUTOCALCULATED_STATS = 12, + NPC_DEFAULT = 52 + }; + #pragma pack(push) #pragma pack(1) @@ -73,7 +80,7 @@ struct NPC mPersonality, mLuck; - char mSkills[27]; + char mSkills[Skill::Length]; char mReputation; short mHealth, mMana, mFatigue; char mDisposition, mFactionID, mRank; From fc8bd1aacb9ae79f89fe37a7a1c7e409b7d6f3e5 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Mon, 9 Dec 2013 21:13:06 +0100 Subject: [PATCH 08/12] Allow fatigue stat to become negative when fatigue damages are taken --- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwmechanics/stat.hpp | 22 +++++++++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 983480782..2e7f00dd3 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -199,7 +199,7 @@ namespace MWClass else { MWMechanics::DynamicStat fatigue(getCreatureStats(ptr).getFatigue()); - fatigue.setCurrent(fatigue.getCurrent() - damage); + fatigue.setCurrent(fatigue.getCurrent() - damage, true); getCreatureStats(ptr).setFatigue(fatigue); } } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e7c10d3c8..5f9b2de47 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -669,7 +669,7 @@ namespace MWClass else { MWMechanics::DynamicStat fatigue(getCreatureStats(ptr).getFatigue()); - fatigue.setCurrent(fatigue.getCurrent() - damage); + fatigue.setCurrent(fatigue.getCurrent() - damage, true); getCreatureStats(ptr).setFatigue(fatigue); } } diff --git a/apps/openmw/mwmechanics/stat.hpp b/apps/openmw/mwmechanics/stat.hpp index 65d47c9c0..cb6c09014 100644 --- a/apps/openmw/mwmechanics/stat.hpp +++ b/apps/openmw/mwmechanics/stat.hpp @@ -162,14 +162,26 @@ namespace MWMechanics setCurrent (getCurrent()+diff); } - void setCurrent (const T& value) + void setCurrent (const T& value, bool allowDecreaseBelowZero = false) { - mCurrent = value; + if (value > mCurrent) + { + // increase + mCurrent = value; - if (mCurrent<0) + if (mCurrent > getModified()) + mCurrent = getModified(); + } + else if (value > 0 || allowDecreaseBelowZero) + { + // allowed decrease + mCurrent = value; + } + else if (mCurrent > 0) + { + // capped decrease mCurrent = 0; - else if (mCurrent>getModified()) - mCurrent = getModified(); + } } void setModifier (const T& modifier) From 357ecd92b2c387dd7f7f93c91b0ff185df947cb3 Mon Sep 17 00:00:00 2001 From: Emanuel Guevel Date: Tue, 10 Dec 2013 00:41:36 +0100 Subject: [PATCH 09/12] Do not display negative stat values Display zero instead of negative values. Also remove useless for loops and some unused attributes. --- apps/openmw/mwgui/hud.cpp | 56 ++++++++++++-------------- apps/openmw/mwgui/statswindow.cpp | 50 +++++++++-------------- apps/openmw/mwgui/windowmanagerimp.cpp | 27 ------------- apps/openmw/mwgui/windowmanagerimp.hpp | 2 - 4 files changed, 45 insertions(+), 90 deletions(-) diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index f0843834d..a78b1a6d1 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -174,38 +174,32 @@ namespace MWGui void HUD::setValue(const std::string& id, const MWMechanics::DynamicStat& value) { - static const char *ids[] = - { - "HBar", "MBar", "FBar", 0 - }; + int current = std::max(0, static_cast(value.getCurrent())); + int modified = static_cast(value.getModified()); - for (int i=0; ids[i]; ++i) - if (ids[i]==id) - { - MyGUI::Widget* w; - std::string valStr = boost::lexical_cast(value.getCurrent()) + "/" + boost::lexical_cast(value.getModified()); - switch (i) - { - case 0: - mHealth->setProgressRange (value.getModified()); - mHealth->setProgressPosition (value.getCurrent()); - getWidget(w, "HealthFrame"); - w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); - break; - case 1: - mMagicka->setProgressRange (value.getModified()); - mMagicka->setProgressPosition (value.getCurrent()); - getWidget(w, "MagickaFrame"); - w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); - break; - case 2: - mStamina->setProgressRange (value.getModified()); - mStamina->setProgressPosition (value.getCurrent()); - getWidget(w, "FatigueFrame"); - w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); - break; - } - } + MyGUI::Widget* w; + std::string valStr = boost::lexical_cast(current) + "/" + boost::lexical_cast(modified); + if (id == "HBar") + { + mHealth->setProgressRange(modified); + mHealth->setProgressPosition(current); + getWidget(w, "HealthFrame"); + w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); + } + else if (id == "MBar") + { + mMagicka->setProgressRange (modified); + mMagicka->setProgressPosition (current); + getWidget(w, "MagickaFrame"); + w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); + } + else if (id == "FBar") + { + mStamina->setProgressRange (modified); + mStamina->setProgressPosition (current); + getWidget(w, "FatigueFrame"); + w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); + } } void HUD::setDrowningTimeLeft(float time) diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 136328f57..ab6096b7e 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -134,38 +134,28 @@ namespace MWGui void StatsWindow::setValue (const std::string& id, const MWMechanics::DynamicStat& value) { - static const char *ids[] = - { - "HBar", "MBar", "FBar", - 0 - }; + int current = std::max(0, static_cast(value.getCurrent())); + int modified = static_cast(value.getModified()); - for (int i=0; ids[i]; ++i) - { - if (ids[i]==id) - { - std::string id (ids[i]); - setBar (id, id + "T", static_cast(value.getCurrent()), static_cast(value.getModified())); + setBar (id, id + "T", current, modified); - // health, magicka, fatigue tooltip - MyGUI::Widget* w; - std::string valStr = boost::lexical_cast(int(value.getCurrent())) + "/" + boost::lexical_cast(int(value.getModified())); - if (i==0) - { - getWidget(w, "Health"); - w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); - } - else if (i==1) - { - getWidget(w, "Magicka"); - w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); - } - else if (i==2) - { - getWidget(w, "Fatigue"); - w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); - } - } + // health, magicka, fatigue tooltip + MyGUI::Widget* w; + std::string valStr = boost::lexical_cast(current) + "/" + boost::lexical_cast(modified); + if (id == "HBar") + { + getWidget(w, "Health"); + w->setUserString("Caption_HealthDescription", "#{sHealthDesc}\n" + valStr); + } + else if (id == "MBar") + { + getWidget(w, "Magicka"); + w->setUserString("Caption_HealthDescription", "#{sIntDesc}\n" + valStr); + } + else if (id == "FBar") + { + getWidget(w, "Fatigue"); + w->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr); } } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 78986a052..afa020082 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -112,9 +112,6 @@ namespace MWGui , mPlayerMinorSkills() , mPlayerMajorSkills() , mPlayerSkillValues() - , mPlayerHealth() - , mPlayerMagicka() - , mPlayerFatigue() , mGui(NULL) , mGuiModes() , mCursorManager(NULL) @@ -590,31 +587,7 @@ namespace MWGui mStatsWindow->setValue (id, value); mHud->setValue (id, value); mCharGen->setValue(id, value); - if (id == "HBar") - { - mPlayerHealth = value; - } - else if (id == "MBar") - { - mPlayerMagicka = value; - } - else if (id == "FBar") - { - mPlayerFatigue = value; - } - } - - #if 0 - MWMechanics::DynamicStat WindowManager::getValue(const std::string& id) - { - if(id == "HBar") - return mPlayerHealth; - else if (id == "MBar") - return mPlayerMagicka; - else if (id == "FBar") - return mPlayerFatigue; } - #endif void WindowManager::setValue (const std::string& id, const std::string& value) { diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 4f1960295..743160aa8 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -346,8 +346,6 @@ namespace MWGui std::map > mPlayerAttributes; SkillList mPlayerMajorSkills, mPlayerMinorSkills; std::map > mPlayerSkillValues; - MWMechanics::DynamicStat mPlayerHealth, mPlayerMagicka, mPlayerFatigue; - MyGUI::Gui *mGui; // Gui std::vector mGuiModes; From 7a9b64c6f4823f16cd2f6e6a6de6812578c106d6 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Thu, 12 Dec 2013 16:08:07 +0200 Subject: [PATCH 10/12] bug fix http://bugs.openmw.org/issues/985 --- apps/openmw/mwworld/actiontalk.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index 905497f85..6b5e274f5 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -1,15 +1,23 @@ #include "actiontalk.hpp" +#include "class.hpp" + #include "../mwbase/environment.hpp" #include "../mwbase/dialoguemanager.hpp" +#include "../mwmechanics/creaturestats.hpp" + namespace MWWorld { ActionTalk::ActionTalk (const Ptr& actor) : Action (false, actor) {} void ActionTalk::executeImp (const Ptr& actor) { - MWBase::Environment::get().getDialogueManager()->startDialogue (getTarget()); + MWWorld::Ptr talkTo = getTarget(); //because 'actor' is always the player! + if ( MWWorld::Class::get(talkTo).getCreatureStats(talkTo).isHostile() ) + return; + + MWBase::Environment::get().getDialogueManager()->startDialogue (talkTo); } } From c8bf69b91affbfd4082b24d70854ec15c878d260 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Fri, 13 Dec 2013 19:02:25 +0200 Subject: [PATCH 11/12] Revert "bug fix http://bugs.openmw.org/issues/985" This reverts commit 7a9b64c6f4823f16cd2f6e6a6de6812578c106d6. --- apps/openmw/mwworld/actiontalk.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/apps/openmw/mwworld/actiontalk.cpp b/apps/openmw/mwworld/actiontalk.cpp index 6b5e274f5..905497f85 100644 --- a/apps/openmw/mwworld/actiontalk.cpp +++ b/apps/openmw/mwworld/actiontalk.cpp @@ -1,23 +1,15 @@ #include "actiontalk.hpp" -#include "class.hpp" - #include "../mwbase/environment.hpp" #include "../mwbase/dialoguemanager.hpp" -#include "../mwmechanics/creaturestats.hpp" - namespace MWWorld { ActionTalk::ActionTalk (const Ptr& actor) : Action (false, actor) {} void ActionTalk::executeImp (const Ptr& actor) { - MWWorld::Ptr talkTo = getTarget(); //because 'actor' is always the player! - if ( MWWorld::Class::get(talkTo).getCreatureStats(talkTo).isHostile() ) - return; - - MWBase::Environment::get().getDialogueManager()->startDialogue (talkTo); + MWBase::Environment::get().getDialogueManager()->startDialogue (getTarget()); } } From 8b3a393a6b1b0a93cc7ac58353cbd197c3aaf346 Mon Sep 17 00:00:00 2001 From: mrcheko Date: Fri, 13 Dec 2013 19:33:01 +0200 Subject: [PATCH 12/12] bug fix at http://bugs.openmw.org/issues/985 --- apps/openmw/mwclass/npc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index e7c10d3c8..5e9801c49 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -711,6 +711,8 @@ namespace MWClass return boost::shared_ptr(new MWWorld::ActionOpen(ptr, true)); if(get(actor).getStance(actor, MWWorld::Class::Sneak)) return boost::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing + if(get(ptr).getCreatureStats(ptr).isHostile()) + return boost::shared_ptr(new MWWorld::FailedAction("#{sActorInCombat}")); return boost::shared_ptr(new MWWorld::ActionTalk(ptr)); }