From d544551f61f51605d59ddc0bc1bbefbb320dcaa0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 15 Jan 2014 15:50:45 +0100 Subject: [PATCH] Added getSkill to Class interface, since creatures also have skills (which are provided by generalized Combat, Magic and Stealth attributes which substitute for the specific skills, in the same way as specialization) Information provided by Hrnchamd. --- apps/openmw/mwclass/creature.cpp | 20 +++++++++++++++++++ apps/openmw/mwclass/creature.hpp | 2 ++ apps/openmw/mwclass/npc.cpp | 5 +++++ apps/openmw/mwclass/npc.hpp | 2 ++ apps/openmw/mwgui/pickpocketitemmodel.cpp | 2 +- apps/openmw/mwgui/tradewindow.cpp | 4 ++-- apps/openmw/mwmechanics/character.cpp | 2 +- .../mwmechanics/mechanicsmanagerimp.cpp | 11 ++-------- apps/openmw/mwmechanics/pickpocket.cpp | 5 ++--- apps/openmw/mwmechanics/spellcasting.hpp | 11 +++++----- apps/openmw/mwscript/statsextensions.cpp | 4 +--- apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 2 ++ apps/openmw/mwworld/inventorystore.cpp | 16 +++++++-------- components/esm/loadcrea.hpp | 4 +++- 15 files changed, 60 insertions(+), 35 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 480c335c2..ac8f85d13 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -461,6 +461,26 @@ namespace MWClass throw std::runtime_error(std::string("Unexpected soundgen type: ")+name); } + int Creature::getSkill(const MWWorld::Ptr &ptr, int skill) const + { + MWWorld::LiveCellRef *ref = + ptr.get(); + + const ESM::Skill* skillRecord = MWBase::Environment::get().getWorld()->getStore().get().find(skill); + + switch (skillRecord->mData.mSpecialization) + { + case ESM::Class::Combat: + return ref->mBase->mData.mCombat; + case ESM::Class::Magic: + return ref->mBase->mData.mMagic; + case ESM::Class::Stealth: + return ref->mBase->mData.mStealth; + default: + throw std::runtime_error("invalid specialisation"); + } + } + const ESM::GameSetting* Creature::fMinWalkSpeedCreature; const ESM::GameSetting* Creature::fMaxWalkSpeedCreature; } diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index 34e19ebdc..461410a49 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -101,6 +101,8 @@ namespace MWClass } virtual bool isFlying (const MWWorld::Ptr &ptr) const; + + virtual int getSkill(const MWWorld::Ptr &ptr, int skill) const; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index c89822843..8d51fd1cf 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1211,6 +1211,11 @@ namespace MWClass return MWWorld::Ptr(&cell.mNpcs.insert(*ref), &cell); } + int Npc::getSkill(const MWWorld::Ptr& ptr, int skill) const + { + return ptr.getClass().getNpcStats(ptr).getSkill(skill).getModified(); + } + const ESM::GameSetting *Npc::fMinWalkSpeed; const ESM::GameSetting *Npc::fMaxWalkSpeed; const ESM::GameSetting *Npc::fEncumberedMoveEffect; diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 9977866cd..b729d0151 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -140,6 +140,8 @@ namespace MWClass virtual std::string getModel(const MWWorld::Ptr &ptr) const; + virtual int getSkill(const MWWorld::Ptr& ptr, int skill) const; + virtual bool isActor() const { return true; } diff --git a/apps/openmw/mwgui/pickpocketitemmodel.cpp b/apps/openmw/mwgui/pickpocketitemmodel.cpp index 13ee4396d..0196bf02d 100644 --- a/apps/openmw/mwgui/pickpocketitemmodel.cpp +++ b/apps/openmw/mwgui/pickpocketitemmodel.cpp @@ -9,7 +9,7 @@ namespace MWGui PickpocketItemModel::PickpocketItemModel(const MWWorld::Ptr& thief, ItemModel *sourceModel) { mSourceModel = sourceModel; - int chance = MWWorld::Class::get(thief).getNpcStats(thief).getSkill(ESM::Skill::Sneak).getModified(); + int chance = thief.getClass().getSkill(thief, ESM::Skill::Sneak); mSourceModel->update(); for (size_t i = 0; igetItemCount(); ++i) diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 14024dec6..f86044841 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -296,10 +296,10 @@ namespace MWGui const MWMechanics::NpcStats &sellerStats = mPtr.getClass().getNpcStats(mPtr); const MWMechanics::NpcStats &playerStats = player.getClass().getNpcStats(player); - float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100); + float a1 = std::min(player.getClass().getSkill(player, ESM::Skill::Mercantile), 100); float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); - float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100); + float d1 = std::min(mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile), 100); float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f); float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 39c421907..5104a0f57 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1017,7 +1017,7 @@ void CharacterController::update(float duration) cls.getCreatureStats(mPtr).setHealth(health); cls.onHit(mPtr, realHealthLost, true, MWWorld::Ptr(), MWWorld::Ptr(), true); - const float acrobaticsSkill = cls.getNpcStats(mPtr).getSkill(ESM::Skill::Acrobatics).getModified(); + const float acrobaticsSkill = cls.getSkill(mPtr, ESM::Skill::Acrobatics); if (healthLost > (acrobaticsSkill * fatigueTerm)) { cls.getCreatureStats(mPtr).setKnockedDown(true); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 4514c077c..0dee4706a 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -902,12 +902,7 @@ namespace MWMechanics { static float fSneakSkillMult = store.find("fSneakSkillMult")->getFloat(); static float fSneakBootMult = store.find("fSneakBootMult")->getFloat(); - float sneak = 0; - // TODO: According to Hrnchamd Research:Movement, "Creatures have generalized combat, magic and stealth - // stats which substitute for the specific skills (in the same way as specializations)." - // This probably applies to a large part of the code base. - if (ptr.getClass().isNpc()) - sneak = ptr.getClass().getNpcStats(ptr).getSkill(ESM::Skill::Sneak).getModified(); + float sneak = ptr.getClass().getSkill(ptr, ESM::Skill::Sneak); int agility = stats.getAttribute(ESM::Attribute::Agility).getModified(); int luck = stats.getAttribute(ESM::Attribute::Luck).getModified(); float bootWeight = 0; @@ -935,9 +930,7 @@ namespace MWMechanics int obsAgility = observerStats.getAttribute(ESM::Attribute::Agility).getModified(); int obsLuck = observerStats.getAttribute(ESM::Attribute::Luck).getModified(); float obsBlind = observerStats.getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude; - int obsSneak = 0; - if (observer.getClass().isNpc()) - obsSneak = observer.getClass().getNpcStats(observer).getSkill(ESM::Skill::Sneak).getModified(); + int obsSneak = observer.getClass().getSkill(observer, ESM::Skill::Sneak); float obsTerm = obsSneak + 0.2 * obsAgility + 0.1 * obsLuck - obsBlind; diff --git a/apps/openmw/mwmechanics/pickpocket.cpp b/apps/openmw/mwmechanics/pickpocket.cpp index 8e8a70d88..53681caf8 100644 --- a/apps/openmw/mwmechanics/pickpocket.cpp +++ b/apps/openmw/mwmechanics/pickpocket.cpp @@ -19,7 +19,7 @@ namespace MWMechanics NpcStats& stats = ptr.getClass().getNpcStats(ptr); float agility = stats.getAttribute(ESM::Attribute::Agility).getModified(); float luck = stats.getAttribute(ESM::Attribute::Luck).getModified(); - float sneak = stats.getSkill(ESM::Skill::Sneak).getModified(); + float sneak = ptr.getClass().getSkill(ptr, ESM::Skill::Sneak); return (add + 0.2 * agility + 0.1 * luck + sneak) * stats.getFatigueTerm(); } @@ -30,8 +30,7 @@ namespace MWMechanics float t = 2*x - y; - NpcStats& pcStats = mThief.getClass().getNpcStats(mThief); - float pcSneak = pcStats.getSkill(ESM::Skill::Sneak).getModified(); + float pcSneak = mThief.getClass().getSkill(mThief, ESM::Skill::Sneak); int iPickMinChance = MWBase::Environment::get().getWorld()->getStore().get() .find("iPickMinChance")->getInt(); int iPickMaxChance = MWBase::Environment::get().getWorld()->getStore().get() diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index a1ae254f6..52af26ad1 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -16,9 +16,9 @@ namespace MWMechanics { - inline int spellSchoolToSkill(int school) + inline ESM::Skill::SkillEnum spellSchoolToSkill(int school) { - std::map schoolSkillMap; // maps spell school to skill id + std::map schoolSkillMap; // maps spell school to skill id schoolSkillMap[0] = ESM::Skill::Alteration; schoolSkillMap[1] = ESM::Skill::Conjuration; schoolSkillMap[3] = ESM::Skill::Illusion; @@ -38,10 +38,9 @@ namespace MWMechanics */ inline float getSpellSuccessChance (const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool = NULL) { - NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); - CreatureStats& creatureStats = MWWorld::Class::get(actor).getCreatureStats(actor); + CreatureStats& stats = actor.getClass().getCreatureStats(actor); - if (creatureStats.getMagicEffects().get(ESM::MagicEffect::Silence).mMagnitude) + if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).mMagnitude) return 0; float y = FLT_MAX; @@ -63,7 +62,7 @@ namespace MWMechanics "fEffectCostMult")->getFloat(); x *= fEffectCostMult; - float s = 2 * stats.getSkill(spellSchoolToSkill(magicEffect->mData.mSchool)).getModified(); + float s = 2 * actor.getClass().getSkill(actor, spellSchoolToSkill(magicEffect->mData.mSchool)); if (s - x < y) { y = s - x; diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 095fad7ab..7a59e9689 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -306,9 +306,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - Interpreter::Type_Integer value = - MWWorld::Class::get (ptr).getNpcStats (ptr).getSkill (mIndex). - getModified(); + Interpreter::Type_Integer value = ptr.getClass().getSkill(ptr, mIndex); runtime.push (value); } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 07bd90571..f3128780b 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -358,4 +358,9 @@ namespace MWWorld return false; } + int Class::getSkill(const MWWorld::Ptr& ptr, int skill) const + { + throw std::runtime_error("class does not support skills"); + } + } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 5c1c063a3..bbc74323c 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -294,6 +294,8 @@ namespace MWWorld virtual bool isFlying(const MWWorld::Ptr& ptr) const; + virtual int getSkill(const MWWorld::Ptr& ptr, int skill) const; + static const Class& get (const std::string& key); ///< If there is no class for this \a key, an exception is thrown. diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index e8938b2c0..82b827e75 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -164,8 +164,6 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::getSlot (int slot) void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) { - const MWMechanics::NpcStats& stats = MWWorld::Class::get(actor).getNpcStats(actor); - TSlots slots_; initSlots (slots_); @@ -190,10 +188,10 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))) continue; - int testSkill = MWWorld::Class::get (test).getEquipmentSkill (test); + int testSkill = test.getClass().getEquipmentSkill (test); std::pair, bool> itemsSlots = - MWWorld::Class::get (*iter).getEquipmentSlots (*iter); + iter->getClass().getEquipmentSlots (*iter); for (std::vector::const_iterator iter2 (itemsSlots.first.begin()); iter2!=itemsSlots.first.end(); ++iter2) @@ -210,16 +208,16 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) { // check skill int oldSkill = - MWWorld::Class::get (old).getEquipmentSkill (old); + old.getClass().getEquipmentSkill (old); if (testSkill!=-1 && oldSkill==-1) use = true; else if (testSkill!=-1 && oldSkill!=-1 && testSkill!=oldSkill) { - if (stats.getSkill (oldSkill).getModified()>stats.getSkill (testSkill).getModified()) + if (actor.getClass().getSkill(actor, oldSkill) > actor.getClass().getSkill (actor, testSkill)) continue; // rejected, because old item better matched the NPC's skills. - if (stats.getSkill (oldSkill).getModified()= - MWWorld::Class::get (test).getValue (test)) + if (old.getClass().getValue (old)>= + test.getClass().getValue (test)) { continue; } diff --git a/components/esm/loadcrea.hpp b/components/esm/loadcrea.hpp index b5ea49508..c0523025b 100644 --- a/components/esm/loadcrea.hpp +++ b/components/esm/loadcrea.hpp @@ -63,7 +63,9 @@ struct Creature int mHealth, mMana, mFatigue; // Stats int mSoul; // The creatures soul value (used with soul gems.) - int mCombat, mMagic, mStealth; // Don't know yet. + // Creatures have generalized combat, magic and stealth stats which substitute for + // the specific skills (in the same way as specializations). + int mCombat, mMagic, mStealth; int mAttack[6]; // AttackMin1, AttackMax1, ditto2, ditto3 int mGold; }; // 96 byte