mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-10 21:40:15 +00:00
Merge branch 'schooled' into 'master'
Merge magic schools into skills See merge request OpenMW/openmw!3148
This commit is contained in:
commit
fc5d73648a
@ -1032,8 +1032,8 @@ namespace EsmTool
|
||||
std::cout << " Area Static: " << mData.mArea << std::endl;
|
||||
if (!mData.mAreaSound.empty())
|
||||
std::cout << " Area Sound: " << mData.mAreaSound << std::endl;
|
||||
std::cout << " School: " << schoolLabel(mData.mData.mSchool) << " (" << mData.mData.mSchool << ")"
|
||||
<< std::endl;
|
||||
std::cout << " School: " << schoolLabel(ESM::MagicSchool::skillRefIdToIndex(mData.mData.mSchool)) << " ("
|
||||
<< mData.mData.mSchool << ")" << std::endl;
|
||||
std::cout << " Base Cost: " << mData.mData.mBaseCost << std::endl;
|
||||
std::cout << " Unknown 1: " << mData.mData.mUnknown1 << std::endl;
|
||||
std::cout << " Speed: " << mData.mData.mSpeed << std::endl;
|
||||
|
@ -2040,13 +2040,16 @@ namespace CSMWorld
|
||||
{
|
||||
}
|
||||
|
||||
QVariant get(const Record<ESXRecordT>& record) const override { return record.get().mData.mSchool; }
|
||||
QVariant get(const Record<ESXRecordT>& record) const override
|
||||
{
|
||||
return ESM::MagicSchool::skillRefIdToIndex(record.get().mData.mSchool);
|
||||
}
|
||||
|
||||
void set(Record<ESXRecordT>& record, const QVariant& data) override
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
|
||||
record2.mData.mSchool = data.toInt();
|
||||
record2.mData.mSchool = ESM::MagicSchool::indexToSkillRefId(data.toInt());
|
||||
|
||||
record.setModified(record2);
|
||||
}
|
||||
|
@ -31,9 +31,6 @@
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
std::string ToolTips::sSchoolNames[] = { "#{sSchoolAlteration}", "#{sSchoolConjuration}", "#{sSchoolDestruction}",
|
||||
"#{sSchoolIllusion}", "#{sSchoolMysticism}", "#{sSchoolRestoration}" };
|
||||
|
||||
ToolTips::ToolTips()
|
||||
: Layout("openmw_tooltips.layout")
|
||||
, mFocusToolTipX(0.0)
|
||||
@ -227,8 +224,9 @@ namespace MWGui
|
||||
{
|
||||
ToolTipInfo info;
|
||||
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getESMStore()->get<ESM::Spell>().find(
|
||||
ESM::RefId::deserialize(focus->getUserString("Spell")));
|
||||
const auto& store = MWBase::Environment::get().getESMStore();
|
||||
const ESM::Spell* spell
|
||||
= store->get<ESM::Spell>().find(ESM::RefId::deserialize(focus->getUserString("Spell")));
|
||||
info.caption = spell->mName;
|
||||
Widgets::SpellEffectList effects;
|
||||
for (const ESM::ENAMstruct& spellEffect : spell->mEffects.mList)
|
||||
@ -250,8 +248,9 @@ namespace MWGui
|
||||
spell)) // display school of spells that contribute to skill progress
|
||||
{
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
int school = MWMechanics::getSpellSchool(spell, player);
|
||||
info.text = "#{sSchool}: " + sSchoolNames[school];
|
||||
const auto& school
|
||||
= store->get<ESM::Skill>().find(MWMechanics::getSpellSchool(spell, player))->mSchool;
|
||||
info.text = "#{sSchool}: " + MyGUI::TextIterator::toTagsString(school->mName).asUTF8();
|
||||
}
|
||||
const std::string& cost = focus->getUserString("SpellCost");
|
||||
if (!cost.empty() && cost != "0")
|
||||
@ -944,7 +943,8 @@ namespace MWGui
|
||||
|
||||
void ToolTips::createMagicEffectToolTip(MyGUI::Widget* widget, short id)
|
||||
{
|
||||
const ESM::MagicEffect* effect = MWBase::Environment::get().getESMStore()->get<ESM::MagicEffect>().find(id);
|
||||
const auto& store = MWBase::Environment::get().getESMStore();
|
||||
const ESM::MagicEffect* effect = store->get<ESM::MagicEffect>().find(id);
|
||||
const std::string& name = ESM::MagicEffect::indexToGmstString(id);
|
||||
|
||||
std::string icon = effect->mIcon;
|
||||
@ -956,7 +956,11 @@ namespace MWGui
|
||||
widget->setUserString("ToolTipLayout", "MagicEffectToolTip");
|
||||
widget->setUserString("Caption_MagicEffectName", "#{" + name + "}");
|
||||
widget->setUserString("Caption_MagicEffectDescription", effect->mDescription);
|
||||
widget->setUserString("Caption_MagicEffectSchool", "#{sSchool}: " + sSchoolNames[effect->mData.mSchool]);
|
||||
widget->setUserString("Caption_MagicEffectSchool",
|
||||
"#{sSchool}: "
|
||||
+ MyGUI::TextIterator::toTagsString(
|
||||
store->get<ESM::Skill>().find(effect->mData.mSchool)->mSchool->mName)
|
||||
.asUTF8());
|
||||
widget->setUserString("ImageTexture_MagicEffectImage", icon);
|
||||
}
|
||||
|
||||
|
@ -122,8 +122,6 @@ namespace MWGui
|
||||
/// Adjust position for a tooltip so that it doesn't leave the screen and does not obscure the mouse cursor
|
||||
void position(MyGUI::IntPoint& position, MyGUI::IntSize size, MyGUI::IntSize viewportSize);
|
||||
|
||||
static std::string sSchoolNames[6];
|
||||
|
||||
int mHorizontalScrollIndex;
|
||||
|
||||
float mDelay;
|
||||
|
@ -358,8 +358,8 @@ namespace MWLua
|
||||
.find(ESM::MagicEffect::indexToGmstString(rec.mIndex))
|
||||
->mValue.getString();
|
||||
});
|
||||
magicEffectT["school"]
|
||||
= sol::readonly_property([](const ESM::MagicEffect& rec) -> int { return rec.mData.mSchool; });
|
||||
magicEffectT["school"] = sol::readonly_property(
|
||||
[](const ESM::MagicEffect& rec) -> int { return ESM::MagicSchool::skillRefIdToIndex(rec.mData.mSchool); });
|
||||
magicEffectT["baseCost"]
|
||||
= sol::readonly_property([](const ESM::MagicEffect& rec) -> float { return rec.mData.mBaseCost; });
|
||||
magicEffectT["color"] = sol::readonly_property([](const ESM::MagicEffect& rec) -> Misc::Color {
|
||||
|
@ -35,30 +35,18 @@ namespace MWMechanics
|
||||
static const float fNPCbaseMagickaMult = gmst.find("fNPCbaseMagickaMult")->mValue.getFloat();
|
||||
float baseMagicka = fNPCbaseMagickaMult * actorAttributes.at(ESM::Attribute::Intelligence).getBase();
|
||||
|
||||
static const std::string schools[]
|
||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||
static int iAutoSpellSchoolMax[6];
|
||||
static bool init = false;
|
||||
if (!init)
|
||||
{
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
const std::string& gmstName = "iAutoSpell" + schools[i] + "Max";
|
||||
iAutoSpellSchoolMax[i] = gmst.find(gmstName)->mValue.getInteger();
|
||||
}
|
||||
init = true;
|
||||
}
|
||||
|
||||
std::map<int, SchoolCaps> schoolCaps;
|
||||
for (int i = 0; i < 6; ++i)
|
||||
std::map<ESM::RefId, SchoolCaps> schoolCaps;
|
||||
for (const ESM::Skill& skill : MWBase::Environment::get().getESMStore()->get<ESM::Skill>())
|
||||
{
|
||||
if (!skill.mSchool)
|
||||
continue;
|
||||
SchoolCaps caps;
|
||||
caps.mCount = 0;
|
||||
caps.mLimit = iAutoSpellSchoolMax[i];
|
||||
caps.mReachedLimit = iAutoSpellSchoolMax[i] <= 0;
|
||||
caps.mLimit = skill.mSchool->mAutoCalcMax;
|
||||
caps.mReachedLimit = skill.mSchool->mAutoCalcMax <= 0;
|
||||
caps.mMinCost = std::numeric_limits<int>::max();
|
||||
caps.mWeakestSpell = ESM::RefId();
|
||||
schoolCaps[i] = caps;
|
||||
schoolCaps[skill.mId] = caps;
|
||||
}
|
||||
|
||||
std::vector<ESM::RefId> selectedSpells;
|
||||
@ -84,10 +72,10 @@ namespace MWMechanics
|
||||
if (!attrSkillCheck(&spell, actorSkills, actorAttributes))
|
||||
continue;
|
||||
|
||||
int school;
|
||||
ESM::RefId school;
|
||||
float skillTerm;
|
||||
calcWeakestSchool(&spell, actorSkills, school, skillTerm);
|
||||
assert(school >= 0 && school < 6);
|
||||
assert(!school.empty());
|
||||
SchoolCaps& cap = schoolCaps[school];
|
||||
|
||||
if (cap.mReachedLimit && spellCost <= cap.mMinCost)
|
||||
@ -183,7 +171,7 @@ namespace MWMechanics
|
||||
|
||||
static const float fAutoPCSpellChance
|
||||
= esmStore.get<ESM::GameSetting>().find("fAutoPCSpellChance")->mValue.getFloat();
|
||||
if (calcAutoCastChance(&spell, actorSkills, actorAttributes, -1) < fAutoPCSpellChance)
|
||||
if (calcAutoCastChance(&spell, actorSkills, actorAttributes, {}) < fAutoPCSpellChance)
|
||||
continue;
|
||||
|
||||
if (!attrSkillCheck(&spell, actorSkills, actorAttributes))
|
||||
@ -260,7 +248,7 @@ namespace MWMechanics
|
||||
}
|
||||
|
||||
void calcWeakestSchool(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
int& effectiveSchool, float& skillTerm)
|
||||
ESM::RefId& effectiveSchool, float& skillTerm)
|
||||
{
|
||||
// Morrowind for some reason uses a formula slightly different from magicka cost calculation
|
||||
float minChance = std::numeric_limits<float>::max();
|
||||
@ -299,8 +287,7 @@ namespace MWMechanics
|
||||
x *= 1.5f;
|
||||
|
||||
float s = 0.f;
|
||||
ESM::RefId skill = spellSchoolToSkill(magicEffect->mData.mSchool);
|
||||
auto found = actorSkills.find(skill);
|
||||
auto found = actorSkills.find(magicEffect->mData.mSchool);
|
||||
if (found != actorSkills.end())
|
||||
s = 2.f * found->second.getBase();
|
||||
if (s - x < minChance)
|
||||
@ -313,7 +300,7 @@ namespace MWMechanics
|
||||
}
|
||||
|
||||
float calcAutoCastChance(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, int effectiveSchool)
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, ESM::RefId effectiveSchool)
|
||||
{
|
||||
if (spell->mData.mType != ESM::Spell::ST_Spell)
|
||||
return 100.f;
|
||||
@ -322,10 +309,9 @@ namespace MWMechanics
|
||||
return 100.f;
|
||||
|
||||
float skillTerm = 0;
|
||||
if (effectiveSchool != -1)
|
||||
if (!effectiveSchool.empty())
|
||||
{
|
||||
ESM::RefId skill = spellSchoolToSkill(effectiveSchool);
|
||||
auto found = actorSkills.find(skill);
|
||||
auto found = actorSkills.find(effectiveSchool);
|
||||
if (found != actorSkills.end())
|
||||
skillTerm = 2.f * found->second.getBase();
|
||||
}
|
||||
|
@ -31,10 +31,10 @@ namespace MWMechanics
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes);
|
||||
|
||||
void calcWeakestSchool(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
int& effectiveSchool, float& skillTerm);
|
||||
ESM::RefId& effectiveSchool, float& skillTerm);
|
||||
|
||||
float calcAutoCastChance(const ESM::Spell* spell, const std::map<ESM::RefId, SkillValue>& actorSkills,
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, int effectiveSchool);
|
||||
const std::map<ESM::Attribute::AttributeID, AttributeValue>& actorAttributes, ESM::RefId effectiveSchool);
|
||||
|
||||
}
|
||||
|
||||
|
@ -83,15 +83,14 @@ namespace MWMechanics
|
||||
mHitPosition, static_cast<float>(effectInfo.mArea * 2));
|
||||
|
||||
// Play explosion sound (make sure to use NoTrack, since we will delete the projectile now)
|
||||
static const std::string schools[]
|
||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||
{
|
||||
MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
if (!effect->mAreaSound.empty())
|
||||
sndMgr->playSound3D(mHitPosition, effect->mAreaSound, 1.0f, 1.0f);
|
||||
else
|
||||
sndMgr->playSound3D(
|
||||
mHitPosition, ESM::RefId::stringRefId(schools[effect->mData.mSchool] + " area"), 1.0f, 1.0f);
|
||||
sndMgr->playSound3D(mHitPosition,
|
||||
world->getStore().get<ESM::Skill>().find(effect->mData.mSchool)->mSchool->mAreaSound, 1.0f,
|
||||
1.0f);
|
||||
}
|
||||
// Get the actors in range of the effect
|
||||
std::vector<MWWorld::Ptr> objects;
|
||||
@ -300,8 +299,8 @@ namespace MWMechanics
|
||||
mSourceName = item.getClass().getName(item);
|
||||
mId = item.getCellRef().getRefId();
|
||||
|
||||
const ESM::Enchantment* enchantment
|
||||
= MWBase::Environment::get().getESMStore()->get<ESM::Enchantment>().find(enchantmentName);
|
||||
const auto& store = MWBase::Environment::get().getESMStore();
|
||||
const ESM::Enchantment* enchantment = store->get<ESM::Enchantment>().find(enchantmentName);
|
||||
|
||||
mSlot = slot;
|
||||
|
||||
@ -332,20 +331,17 @@ namespace MWMechanics
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicInsufficientCharge}");
|
||||
|
||||
// Failure sound
|
||||
int school = 0;
|
||||
ESM::RefId school = ESM::Skill::Alteration;
|
||||
if (!enchantment->mEffects.mList.empty())
|
||||
{
|
||||
short effectId = enchantment->mEffects.mList.front().mEffectID;
|
||||
const ESM::MagicEffect* magicEffect
|
||||
= MWBase::Environment::get().getESMStore()->get<ESM::MagicEffect>().find(effectId);
|
||||
const ESM::MagicEffect* magicEffect = store->get<ESM::MagicEffect>().find(effectId);
|
||||
school = magicEffect->mData.mSchool;
|
||||
}
|
||||
|
||||
static const std::string schools[]
|
||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||
MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
sndMgr->playSound3D(
|
||||
mCaster, ESM::RefId::stringRefId("Spell Failure " + schools[school]), 1.0f, 1.0f);
|
||||
mCaster, store->get<ESM::Skill>().find(school)->mSchool->mFailureSound, 1.0f, 1.0f);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -401,7 +397,7 @@ namespace MWMechanics
|
||||
mSourceName = spell->mName;
|
||||
mId = spell->mId;
|
||||
|
||||
int school = 0;
|
||||
ESM::RefId school = ESM::Skill::Alteration;
|
||||
|
||||
bool godmode = mCaster == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
|
||||
|
||||
@ -428,12 +424,9 @@ namespace MWMechanics
|
||||
if (fail)
|
||||
{
|
||||
// Failure sound
|
||||
static const std::string schools[]
|
||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||
|
||||
MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
sndMgr->playSound3D(
|
||||
mCaster, ESM::RefId::stringRefId("Spell Failure " + schools[school]), 1.0f, 1.0f);
|
||||
const ESM::Skill* skill = MWBase::Environment::get().getESMStore()->get<ESM::Skill>().find(school);
|
||||
sndMgr->playSound3D(mCaster, skill->mSchool->mFailureSound, 1.0f, 1.0f);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -444,7 +437,7 @@ namespace MWMechanics
|
||||
}
|
||||
|
||||
if (!mManualSpell && mCaster == getPlayer() && spellIncreasesSkill(spell))
|
||||
mCaster.getClass().skillUsageSucceeded(mCaster, spellSchoolToSkill(school), 0);
|
||||
mCaster.getClass().skillUsageSucceeded(mCaster, school, 0);
|
||||
|
||||
// A non-actor doesn't play its spell cast effects from a character controller, so play them here
|
||||
if (!mCaster.getClass().isActor())
|
||||
@ -595,9 +588,6 @@ namespace MWMechanics
|
||||
if (animation && !mCaster.getClass().isActor())
|
||||
animation->addSpellCastGlow(effect);
|
||||
|
||||
static const std::string schools[]
|
||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||
|
||||
addedEffects.push_back(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel, vfs));
|
||||
|
||||
MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
@ -605,32 +595,29 @@ namespace MWMechanics
|
||||
sndMgr->playSound3D(mCaster, effect->mCastSound, 1.0f, 1.0f);
|
||||
else
|
||||
sndMgr->playSound3D(
|
||||
mCaster, ESM::RefId::stringRefId(schools[effect->mData.mSchool] + " cast"), 1.0f, 1.0f);
|
||||
mCaster, store.get<ESM::Skill>().find(effect->mData.mSchool)->mSchool->mCastSound, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void playEffects(const MWWorld::Ptr& target, const ESM::MagicEffect& magicEffect, bool playNonLooping)
|
||||
{
|
||||
const auto& store = MWBase::Environment::get().getESMStore();
|
||||
if (playNonLooping)
|
||||
{
|
||||
static const std::string schools[]
|
||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||
|
||||
MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
if (!magicEffect.mHitSound.empty())
|
||||
sndMgr->playSound3D(target, magicEffect.mHitSound, 1.0f, 1.0f);
|
||||
else
|
||||
sndMgr->playSound3D(
|
||||
target, ESM::RefId::stringRefId(schools[magicEffect.mData.mSchool] + " hit"), 1.0f, 1.0f);
|
||||
target, store->get<ESM::Skill>().find(magicEffect.mData.mSchool)->mSchool->mHitSound, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
// Add VFX
|
||||
const ESM::Static* castStatic;
|
||||
if (!magicEffect.mHit.empty())
|
||||
castStatic = MWBase::Environment::get().getESMStore()->get<ESM::Static>().find(magicEffect.mHit);
|
||||
castStatic = store->get<ESM::Static>().find(magicEffect.mHit);
|
||||
else
|
||||
castStatic = MWBase::Environment::get().getESMStore()->get<ESM::Static>().find(
|
||||
ESM::RefId::stringRefId("VFX_DefaultHit"));
|
||||
castStatic = store->get<ESM::Static>().find(ESM::RefId::stringRefId("VFX_DefaultHit"));
|
||||
|
||||
bool loop = (magicEffect.mData.mFlags & ESM::MagicEffect::ContinuousVfx) != 0;
|
||||
MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(target);
|
||||
|
@ -37,19 +37,6 @@ namespace MWMechanics
|
||||
}
|
||||
}
|
||||
|
||||
ESM::RefId spellSchoolToSkill(int school)
|
||||
{
|
||||
static const std::array<ESM::RefId, 6> schoolSkillArray{
|
||||
ESM::Skill::Alteration,
|
||||
ESM::Skill::Conjuration,
|
||||
ESM::Skill::Destruction,
|
||||
ESM::Skill::Illusion,
|
||||
ESM::Skill::Mysticism,
|
||||
ESM::Skill::Restoration,
|
||||
};
|
||||
return schoolSkillArray.at(school);
|
||||
}
|
||||
|
||||
float calcEffectCost(
|
||||
const ESM::ENAMstruct& effect, const ESM::MagicEffect* magicEffect, const EffectCostMethod method)
|
||||
{
|
||||
@ -153,7 +140,7 @@ namespace MWMechanics
|
||||
return enchantment.mData.mCharge;
|
||||
}
|
||||
|
||||
float calcSpellBaseSuccessChance(const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool)
|
||||
float calcSpellBaseSuccessChance(const ESM::Spell* spell, const MWWorld::Ptr& actor, ESM::RefId* effectiveSchool)
|
||||
{
|
||||
// Morrowind for some reason uses a formula slightly different from magicka cost calculation
|
||||
float y = std::numeric_limits<float>::max();
|
||||
@ -180,7 +167,7 @@ namespace MWMechanics
|
||||
->mValue.getFloat();
|
||||
x *= fEffectCostMult;
|
||||
|
||||
float s = 2.0f * actor.getClass().getSkill(actor, spellSchoolToSkill(magicEffect->mData.mSchool));
|
||||
float s = 2.0f * actor.getClass().getSkill(actor, magicEffect->mData.mSchool);
|
||||
if (s - x < y)
|
||||
{
|
||||
y = s - x;
|
||||
@ -201,7 +188,7 @@ namespace MWMechanics
|
||||
}
|
||||
|
||||
float getSpellSuccessChance(
|
||||
const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap, bool checkMagicka)
|
||||
const ESM::Spell* spell, const MWWorld::Ptr& actor, ESM::RefId* effectiveSchool, bool cap, bool checkMagicka)
|
||||
{
|
||||
// NB: Base chance is calculated here because the effective school pointer must be filled
|
||||
float baseChance = calcSpellBaseSuccessChance(spell, actor, effectiveSchool);
|
||||
@ -239,23 +226,23 @@ namespace MWMechanics
|
||||
}
|
||||
|
||||
float getSpellSuccessChance(
|
||||
const ESM::RefId& spellId, const MWWorld::Ptr& actor, int* effectiveSchool, bool cap, bool checkMagicka)
|
||||
const ESM::RefId& spellId, const MWWorld::Ptr& actor, ESM::RefId* effectiveSchool, bool cap, bool checkMagicka)
|
||||
{
|
||||
if (const auto spell = MWBase::Environment::get().getESMStore()->get<ESM::Spell>().search(spellId))
|
||||
return getSpellSuccessChance(spell, actor, effectiveSchool, cap, checkMagicka);
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
int getSpellSchool(const ESM::RefId& spellId, const MWWorld::Ptr& actor)
|
||||
ESM::RefId getSpellSchool(const ESM::RefId& spellId, const MWWorld::Ptr& actor)
|
||||
{
|
||||
int school = 0;
|
||||
ESM::RefId school;
|
||||
getSpellSuccessChance(spellId, actor, &school);
|
||||
return school;
|
||||
}
|
||||
|
||||
int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor)
|
||||
ESM::RefId getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor)
|
||||
{
|
||||
int school = 0;
|
||||
ESM::RefId school;
|
||||
getSpellSuccessChance(spell, actor, &school);
|
||||
return school;
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ namespace MWWorld
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
ESM::RefId spellSchoolToSkill(int school);
|
||||
|
||||
enum class EffectCostMethod
|
||||
{
|
||||
GameSpell,
|
||||
@ -44,14 +42,14 @@ namespace MWMechanics
|
||||
* @note actor can be an NPC or a creature
|
||||
* @return success chance from 0 to 100 (in percent), if cap=false then chance above 100 may be returned.
|
||||
*/
|
||||
float calcSpellBaseSuccessChance(const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool);
|
||||
float getSpellSuccessChance(const ESM::Spell* spell, const MWWorld::Ptr& actor, int* effectiveSchool = nullptr,
|
||||
bool cap = true, bool checkMagicka = true);
|
||||
float getSpellSuccessChance(const ESM::RefId& spellId, const MWWorld::Ptr& actor, int* effectiveSchool = nullptr,
|
||||
bool cap = true, bool checkMagicka = true);
|
||||
float calcSpellBaseSuccessChance(const ESM::Spell* spell, const MWWorld::Ptr& actor, ESM::RefId* effectiveSchool);
|
||||
float getSpellSuccessChance(const ESM::Spell* spell, const MWWorld::Ptr& actor,
|
||||
ESM::RefId* effectiveSchool = nullptr, bool cap = true, bool checkMagicka = true);
|
||||
float getSpellSuccessChance(const ESM::RefId& spellId, const MWWorld::Ptr& actor,
|
||||
ESM::RefId* effectiveSchool = nullptr, bool cap = true, bool checkMagicka = true);
|
||||
|
||||
int getSpellSchool(const ESM::RefId& spellId, const MWWorld::Ptr& actor);
|
||||
int getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor);
|
||||
ESM::RefId getSpellSchool(const ESM::RefId& spellId, const MWWorld::Ptr& actor);
|
||||
ESM::RefId getSpellSchool(const ESM::Spell* spell, const MWWorld::Ptr& actor);
|
||||
|
||||
/// Get whether or not the given spell contributes to skill progress.
|
||||
bool spellIncreasesSkill(const ESM::Spell* spell);
|
||||
|
@ -98,12 +98,14 @@ namespace
|
||||
else
|
||||
projectileIDs.push_back(magicEffect->mBolt);
|
||||
|
||||
static const std::string schools[]
|
||||
= { "alteration", "conjuration", "destruction", "illusion", "mysticism", "restoration" };
|
||||
if (!magicEffect->mBoltSound.empty())
|
||||
sounds.emplace(magicEffect->mBoltSound);
|
||||
else
|
||||
sounds.emplace(ESM::RefId::stringRefId(schools[magicEffect->mData.mSchool] + " bolt"));
|
||||
sounds.emplace(MWBase::Environment::get()
|
||||
.getESMStore()
|
||||
->get<ESM::Skill>()
|
||||
.find(magicEffect->mData.mSchool)
|
||||
->mSchool->mBoltSound);
|
||||
projectileEffects.mList.push_back(*iter);
|
||||
}
|
||||
|
||||
|
@ -932,35 +932,35 @@ namespace MWWorld
|
||||
|
||||
void Store<ESM::Skill>::setUp(const MWWorld::Store<ESM::GameSetting>& settings)
|
||||
{
|
||||
constexpr std::string_view skillValues[ESM::Skill::Length][3] = {
|
||||
{ "sSkillBlock", "icons\\k\\combat_block.dds", "fWerewolfBlock" },
|
||||
{ "sSkillArmorer", "icons\\k\\combat_armor.dds", "fWerewolfArmorer" },
|
||||
{ "sSkillMediumarmor", "icons\\k\\combat_mediumarmor.dds", "fWerewolfMediumarmor" },
|
||||
{ "sSkillHeavyarmor", "icons\\k\\combat_heavyarmor.dds", "fWerewolfHeavyarmor" },
|
||||
{ "sSkillBluntweapon", "icons\\k\\combat_blunt.dds", "fWerewolfBluntweapon" },
|
||||
{ "sSkillLongblade", "icons\\k\\combat_longblade.dds", "fWerewolfLongblade" },
|
||||
{ "sSkillAxe", "icons\\k\\combat_axe.dds", "fWerewolfAxe" },
|
||||
{ "sSkillSpear", "icons\\k\\combat_spear.dds", "fWerewolfSpear" },
|
||||
{ "sSkillAthletics", "icons\\k\\combat_athletics.dds", "fWerewolfAthletics" },
|
||||
{ "sSkillEnchant", "icons\\k\\magic_enchant.dds", "fWerewolfEnchant" },
|
||||
{ "sSkillDestruction", "icons\\k\\magic_destruction.dds", "fWerewolfDestruction" },
|
||||
{ "sSkillAlteration", "icons\\k\\magic_alteration.dds", "fWerewolfAlteration" },
|
||||
{ "sSkillIllusion", "icons\\k\\magic_illusion.dds", "fWerewolfIllusion" },
|
||||
{ "sSkillConjuration", "icons\\k\\magic_conjuration.dds", "fWerewolfConjuration" },
|
||||
{ "sSkillMysticism", "icons\\k\\magic_mysticism.dds", "fWerewolfMysticism" },
|
||||
{ "sSkillRestoration", "icons\\k\\magic_restoration.dds", "fWerewolfRestoration" },
|
||||
{ "sSkillAlchemy", "icons\\k\\magic_alchemy.dds", "fWerewolfAlchemy" },
|
||||
{ "sSkillUnarmored", "icons\\k\\magic_unarmored.dds", "fWerewolfUnarmored" },
|
||||
{ "sSkillSecurity", "icons\\k\\stealth_security.dds", "fWerewolfSecurity" },
|
||||
{ "sSkillSneak", "icons\\k\\stealth_sneak.dds", "fWerewolfSneak" },
|
||||
{ "sSkillAcrobatics", "icons\\k\\stealth_acrobatics.dds", "fWerewolfAcrobatics" },
|
||||
{ "sSkillLightarmor", "icons\\k\\stealth_lightarmor.dds", "fWerewolfLightarmor" },
|
||||
{ "sSkillShortblade", "icons\\k\\stealth_shortblade.dds", "fWerewolfShortblade" },
|
||||
{ "sSkillMarksman", "icons\\k\\stealth_marksman.dds", "fWerewolfMarksman" },
|
||||
constexpr std::string_view skillValues[ESM::Skill::Length][4] = {
|
||||
{ "sSkillBlock", "icons\\k\\combat_block.dds", "fWerewolfBlock", {} },
|
||||
{ "sSkillArmorer", "icons\\k\\combat_armor.dds", "fWerewolfArmorer", {} },
|
||||
{ "sSkillMediumarmor", "icons\\k\\combat_mediumarmor.dds", "fWerewolfMediumarmor", {} },
|
||||
{ "sSkillHeavyarmor", "icons\\k\\combat_heavyarmor.dds", "fWerewolfHeavyarmor", {} },
|
||||
{ "sSkillBluntweapon", "icons\\k\\combat_blunt.dds", "fWerewolfBluntweapon", {} },
|
||||
{ "sSkillLongblade", "icons\\k\\combat_longblade.dds", "fWerewolfLongblade", {} },
|
||||
{ "sSkillAxe", "icons\\k\\combat_axe.dds", "fWerewolfAxe", {} },
|
||||
{ "sSkillSpear", "icons\\k\\combat_spear.dds", "fWerewolfSpear", {} },
|
||||
{ "sSkillAthletics", "icons\\k\\combat_athletics.dds", "fWerewolfAthletics", {} },
|
||||
{ "sSkillEnchant", "icons\\k\\magic_enchant.dds", "fWerewolfEnchant", {} },
|
||||
{ "sSkillDestruction", "icons\\k\\magic_destruction.dds", "fWerewolfDestruction", "destruction" },
|
||||
{ "sSkillAlteration", "icons\\k\\magic_alteration.dds", "fWerewolfAlteration", "alteration" },
|
||||
{ "sSkillIllusion", "icons\\k\\magic_illusion.dds", "fWerewolfIllusion", "illusion" },
|
||||
{ "sSkillConjuration", "icons\\k\\magic_conjuration.dds", "fWerewolfConjuration", "conjuration" },
|
||||
{ "sSkillMysticism", "icons\\k\\magic_mysticism.dds", "fWerewolfMysticism", "mysticism" },
|
||||
{ "sSkillRestoration", "icons\\k\\magic_restoration.dds", "fWerewolfRestoration", "restoration" },
|
||||
{ "sSkillAlchemy", "icons\\k\\magic_alchemy.dds", "fWerewolfAlchemy", {} },
|
||||
{ "sSkillUnarmored", "icons\\k\\magic_unarmored.dds", "fWerewolfUnarmored", {} },
|
||||
{ "sSkillSecurity", "icons\\k\\stealth_security.dds", "fWerewolfSecurity", {} },
|
||||
{ "sSkillSneak", "icons\\k\\stealth_sneak.dds", "fWerewolfSneak", {} },
|
||||
{ "sSkillAcrobatics", "icons\\k\\stealth_acrobatics.dds", "fWerewolfAcrobatics", {} },
|
||||
{ "sSkillLightarmor", "icons\\k\\stealth_lightarmor.dds", "fWerewolfLightarmor", {} },
|
||||
{ "sSkillShortblade", "icons\\k\\stealth_shortblade.dds", "fWerewolfShortblade", {} },
|
||||
{ "sSkillMarksman", "icons\\k\\stealth_marksman.dds", "fWerewolfMarksman", {} },
|
||||
// "Mercantile"! >_<
|
||||
{ "sSkillMercantile", "icons\\k\\stealth_mercantile.dds", "fWerewolfMerchantile" },
|
||||
{ "sSkillSpeechcraft", "icons\\k\\stealth_speechcraft.dds", "fWerewolfSpeechcraft" },
|
||||
{ "sSkillHandtohand", "icons\\k\\stealth_handtohand.dds", "fWerewolfHandtohand" },
|
||||
{ "sSkillMercantile", "icons\\k\\stealth_mercantile.dds", "fWerewolfMerchantile", {} },
|
||||
{ "sSkillSpeechcraft", "icons\\k\\stealth_speechcraft.dds", "fWerewolfSpeechcraft", {} },
|
||||
{ "sSkillHandtohand", "icons\\k\\stealth_handtohand.dds", "fWerewolfHandtohand", {} },
|
||||
};
|
||||
for (ESM::Skill* skill : mShared)
|
||||
{
|
||||
@ -969,6 +969,21 @@ namespace MWWorld
|
||||
skill->mName = getGMSTString(settings, skillValues[skill->mIndex][0]);
|
||||
skill->mIcon = skillValues[skill->mIndex][1];
|
||||
skill->mWerewolfValue = getGMSTFloat(settings, skillValues[skill->mIndex][2]);
|
||||
const auto& school = skillValues[skill->mIndex][3];
|
||||
if (!school.empty())
|
||||
{
|
||||
if (!skill->mSchool)
|
||||
skill->mSchool = ESM::MagicSchool{};
|
||||
const std::string id{ school };
|
||||
skill->mSchool->mAreaSound = ESM::RefId::stringRefId(id + " area");
|
||||
skill->mSchool->mBoltSound = ESM::RefId::stringRefId(id + " bolt");
|
||||
skill->mSchool->mCastSound = ESM::RefId::stringRefId(id + " cast");
|
||||
skill->mSchool->mFailureSound = ESM::RefId::stringRefId("Spell Failure " + id);
|
||||
skill->mSchool->mHitSound = ESM::RefId::stringRefId(id + " hit");
|
||||
const std::string name = "sSchool" + id;
|
||||
skill->mSchool->mName = getGMSTString(settings, name);
|
||||
skill->mSchool->mAutoCalcMax = int(getGMSTFloat(settings, "iAutoSpell" + id + "Max"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "esmreader.hpp"
|
||||
#include "esmwriter.hpp"
|
||||
#include "loadskil.hpp"
|
||||
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
|
||||
@ -33,7 +34,20 @@ namespace ESM
|
||||
|
||||
mId = indexToRefId(mIndex);
|
||||
|
||||
esm.getHNTSized<36>(mData, "MEDT");
|
||||
esm.getSubNameIs("MEDT");
|
||||
esm.getSubHeader();
|
||||
int school;
|
||||
esm.getT(school);
|
||||
mData.mSchool = MagicSchool::indexToSkillRefId(school);
|
||||
esm.getT(mData.mBaseCost);
|
||||
esm.getT(mData.mFlags);
|
||||
esm.getT(mData.mRed);
|
||||
esm.getT(mData.mGreen);
|
||||
esm.getT(mData.mBlue);
|
||||
esm.getT(mData.mUnknown1);
|
||||
esm.getT(mData.mSpeed);
|
||||
esm.getT(mData.mUnknown2);
|
||||
|
||||
if (esm.getFormatVersion() == DefaultFormatVersion)
|
||||
{
|
||||
// don't allow mods to change fixed flags in the legacy format
|
||||
@ -91,7 +105,17 @@ namespace ESM
|
||||
{
|
||||
esm.writeHNT("INDX", mIndex);
|
||||
|
||||
esm.writeHNT("MEDT", mData, 36);
|
||||
esm.startSubRecord("MEDT");
|
||||
esm.writeT(MagicSchool::skillRefIdToIndex(mData.mSchool));
|
||||
esm.writeT(mData.mBaseCost);
|
||||
esm.writeT(mData.mFlags);
|
||||
esm.writeT(mData.mRed);
|
||||
esm.writeT(mData.mGreen);
|
||||
esm.writeT(mData.mBlue);
|
||||
esm.writeT(mData.mUnknown1);
|
||||
esm.writeT(mData.mSpeed);
|
||||
esm.writeT(mData.mUnknown2);
|
||||
esm.endRecord("MEDT");
|
||||
|
||||
esm.writeHNOCString("ITEX", mIcon);
|
||||
esm.writeHNOCString("PTEX", mParticle);
|
||||
@ -558,7 +582,7 @@ namespace ESM
|
||||
void MagicEffect::blank()
|
||||
{
|
||||
mRecordFlags = 0;
|
||||
mData.mSchool = 0;
|
||||
mData.mSchool = ESM::Skill::Alteration;
|
||||
mData.mBaseCost = 0;
|
||||
mData.mFlags = 0;
|
||||
mData.mRed = 0;
|
||||
|
@ -70,7 +70,7 @@ namespace ESM
|
||||
|
||||
struct MEDTstruct
|
||||
{
|
||||
int mSchool; // SpellSchool, see defs.hpp
|
||||
RefId mSchool; // Skill id
|
||||
float mBaseCost;
|
||||
int mFlags;
|
||||
// Glow color for enchanted items with this effect
|
||||
|
@ -107,4 +107,30 @@ namespace ESM
|
||||
return RefId();
|
||||
return RefId::index(sRecordId, static_cast<std::uint32_t>(index));
|
||||
}
|
||||
|
||||
const std::array<RefId, MagicSchool::Length> sMagicSchools = {
|
||||
Skill::Alteration,
|
||||
Skill::Conjuration,
|
||||
Skill::Destruction,
|
||||
Skill::Illusion,
|
||||
Skill::Mysticism,
|
||||
Skill::Restoration,
|
||||
};
|
||||
|
||||
RefId MagicSchool::indexToSkillRefId(int index)
|
||||
{
|
||||
if (index < 0 || index >= Length)
|
||||
return {};
|
||||
return sMagicSchools[index];
|
||||
}
|
||||
|
||||
int MagicSchool::skillRefIdToIndex(RefId id)
|
||||
{
|
||||
for (size_t i = 0; i < sMagicSchools.size(); ++i)
|
||||
{
|
||||
if (id == sMagicSchools[i])
|
||||
return static_cast<int>(i);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define OPENMW_ESM_SKIL_H
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "components/esm/defs.hpp"
|
||||
@ -13,6 +14,22 @@ namespace ESM
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
struct MagicSchool
|
||||
{
|
||||
ESM::RefId mAreaSound;
|
||||
ESM::RefId mBoltSound;
|
||||
ESM::RefId mCastSound;
|
||||
ESM::RefId mFailureSound;
|
||||
ESM::RefId mHitSound;
|
||||
std::string mName;
|
||||
int mAutoCalcMax;
|
||||
|
||||
static constexpr int Length = 6;
|
||||
|
||||
static RefId indexToSkillRefId(int index);
|
||||
static int skillRefIdToIndex(RefId id);
|
||||
};
|
||||
|
||||
/*
|
||||
* Skill information
|
||||
*
|
||||
@ -47,6 +64,7 @@ namespace ESM
|
||||
std::string mName;
|
||||
std::string mIcon;
|
||||
float mWerewolfValue{};
|
||||
std::optional<MagicSchool> mSchool;
|
||||
|
||||
static constexpr IndexRefId Block{ sRecordId, 0 };
|
||||
static constexpr IndexRefId Armorer{ sRecordId, 1 };
|
||||
|
Loading…
x
Reference in New Issue
Block a user