forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
ee621245bb
42 changed files with 482 additions and 209 deletions
|
@ -137,8 +137,8 @@ namespace MWBase
|
|||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount) = 0;
|
||||
|
||||
/// Set value for the given ID.
|
||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value) = 0;
|
||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value) = 0;
|
||||
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value) = 0;
|
||||
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value) = 0;
|
||||
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value) = 0;
|
||||
virtual void setValue (const std::string& id, const std::string& value) = 0;
|
||||
virtual void setValue (const std::string& id, int value) = 0;
|
||||
|
@ -236,8 +236,8 @@ namespace MWBase
|
|||
virtual void onFrame (float frameDuration) = 0;
|
||||
|
||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
||||
virtual std::map<int, MWMechanics::Stat<float> > getPlayerSkillValues() = 0;
|
||||
virtual std::map<int, MWMechanics::Stat<int> > getPlayerAttributeValues() = 0;
|
||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues() = 0;
|
||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues() = 0;
|
||||
virtual SkillList getPlayerMinorSkills() = 0;
|
||||
virtual SkillList getPlayerMajorSkills() = 0;
|
||||
|
||||
|
|
|
@ -242,7 +242,11 @@ namespace MWClass
|
|||
item.get<ESM::Miscellaneous>();
|
||||
|
||||
return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc)
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001");
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_005")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_010")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_025")
|
||||
&& !Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_100");
|
||||
}
|
||||
|
||||
float Miscellaneous::getWeight(const MWWorld::Ptr &ptr) const
|
||||
|
|
|
@ -179,29 +179,29 @@ namespace
|
|||
|
||||
for (int raceSkillIndex = 0; raceSkillIndex < 7; ++raceSkillIndex)
|
||||
{
|
||||
if (race->mData.mBonus[raceSkillIndex].mSkill == skillIndex)
|
||||
{
|
||||
raceBonus = race->mData.mBonus[raceSkillIndex].mBonus;
|
||||
break;
|
||||
}
|
||||
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 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<ESM::Skill>().find(skillIndex);
|
||||
if (skill->mData.mSpecialization == class_->mData.mSpecialization)
|
||||
{
|
||||
specMultiplier = 0.5f;
|
||||
specBonus = 5;
|
||||
specMultiplier = 0.5f;
|
||||
specBonus = 5;
|
||||
}
|
||||
|
||||
npcStats.getSkill(skillIndex).setBase(
|
||||
|
@ -210,7 +210,7 @@ namespace
|
|||
+ 5
|
||||
+ raceBonus
|
||||
+ specBonus
|
||||
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100.0f));
|
||||
+ static_cast<int>((level-1) * (majorMultiplier + specMultiplier)), 100));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -450,8 +450,8 @@ namespace MWClass
|
|||
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||
hitchance *= stats.getFatigueTerm();
|
||||
hitchance += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyAttack)).mMagnitude -
|
||||
mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
|
||||
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
|
||||
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
|
||||
hitchance -= otherstats.getEvasion();
|
||||
|
||||
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
|
||||
|
@ -848,10 +848,11 @@ namespace MWClass
|
|||
float moveSpeed;
|
||||
if(normalizedEncumbrance >= 1.0f)
|
||||
moveSpeed = 0.0f;
|
||||
else if(mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude > 0)
|
||||
else if(mageffects.get(ESM::MagicEffect::Levitate).mMagnitude > 0 &&
|
||||
world->isLevitationEnabled())
|
||||
{
|
||||
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
|
||||
mageffects.get(MWMechanics::EffectKey(10/*levitate*/)).mMagnitude);
|
||||
mageffects.get(ESM::MagicEffect::Levitate).mMagnitude);
|
||||
flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat());
|
||||
flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
|
||||
flySpeed = std::max(0.0f, flySpeed);
|
||||
|
@ -862,7 +863,7 @@ namespace MWClass
|
|||
float swimSpeed = walkSpeed;
|
||||
if(Npc::getStance(ptr, Run, false))
|
||||
swimSpeed = runSpeed;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(MWMechanics::EffectKey(1/*swift swim*/)).mMagnitude;
|
||||
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).mMagnitude;
|
||||
swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
|
||||
fSwimRunAthleticsMult->getFloat();
|
||||
moveSpeed = swimSpeed;
|
||||
|
@ -896,7 +897,7 @@ namespace MWClass
|
|||
float x = fJumpAcrobaticsBase->getFloat() +
|
||||
std::pow(a / 15.0f, fJumpAcroMultiplier->getFloat());
|
||||
x += 3.0f * b * fJumpAcroMultiplier->getFloat();
|
||||
x += mageffects.get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude * 64;
|
||||
x += mageffects.get(ESM::MagicEffect::Jump).mMagnitude * 64;
|
||||
x *= encumbranceTerm;
|
||||
|
||||
if(Npc::getStance(ptr, Run, false))
|
||||
|
@ -919,7 +920,7 @@ namespace MWClass
|
|||
{
|
||||
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
|
||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude;
|
||||
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(ESM::MagicEffect::Jump).mMagnitude;
|
||||
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
|
||||
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
||||
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
||||
|
@ -1024,8 +1025,8 @@ namespace MWClass
|
|||
if(!stats.isWerewolf())
|
||||
{
|
||||
weight = getContainerStore(ptr).getWeight();
|
||||
weight -= stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Feather)).mMagnitude;
|
||||
weight += stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Burden)).mMagnitude;
|
||||
weight -= stats.getMagicEffects().get(ESM::MagicEffect::Feather).mMagnitude;
|
||||
weight += stats.getMagicEffects().get(ESM::MagicEffect::Burden).mMagnitude;
|
||||
if(weight < 0.0f)
|
||||
weight = 0.0f;
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace MWGui
|
|||
mGenerateClassSpecializations[2] = 0;
|
||||
}
|
||||
|
||||
void CharacterCreation::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
||||
void CharacterCreation::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
if (mReviewDialog)
|
||||
{
|
||||
|
@ -113,7 +113,7 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
||||
void CharacterCreation::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
if (mReviewDialog)
|
||||
mReviewDialog->setSkillValue(parSkill, value);
|
||||
|
@ -229,8 +229,8 @@ namespace MWGui
|
|||
}
|
||||
|
||||
{
|
||||
std::map<int, MWMechanics::Stat<int> > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
||||
for (std::map<int, MWMechanics::Stat<int> >::iterator it = attributes.begin();
|
||||
std::map<int, MWMechanics::AttributeValue > attributes = MWBase::Environment::get().getWindowManager()->getPlayerAttributeValues();
|
||||
for (std::map<int, MWMechanics::AttributeValue >::iterator it = attributes.begin();
|
||||
it != attributes.end(); ++it)
|
||||
{
|
||||
mReviewDialog->setAttribute(static_cast<ESM::Attribute::AttributeID> (it->first), it->second);
|
||||
|
@ -238,8 +238,8 @@ namespace MWGui
|
|||
}
|
||||
|
||||
{
|
||||
std::map<int, MWMechanics::Stat<float> > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
||||
for (std::map<int, MWMechanics::Stat<float> >::iterator it = skills.begin();
|
||||
std::map<int, MWMechanics::SkillValue > skills = MWBase::Environment::get().getWindowManager()->getPlayerSkillValues();
|
||||
for (std::map<int, MWMechanics::SkillValue >::iterator it = skills.begin();
|
||||
it != skills.end(); ++it)
|
||||
{
|
||||
mReviewDialog->setSkillValue(static_cast<ESM::Skill::SkillEnum> (it->first), it->second);
|
||||
|
|
|
@ -31,9 +31,9 @@ namespace MWGui
|
|||
//Show a dialog
|
||||
void spawnDialog(const char id);
|
||||
|
||||
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
|
||||
void configureSkills (const SkillList& major, const SkillList& minor);
|
||||
void doRenderUpdate();
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ namespace MWGui
|
|||
// increase attributes
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
MWMechanics::Stat<int> attribute = creatureStats.getAttribute(mSpentAttributes[i]);
|
||||
MWMechanics::AttributeValue attribute = creatureStats.getAttribute(mSpentAttributes[i]);
|
||||
attribute.setBase (attribute.getBase () + pcStats.getLevelupAttributeMultiplier (mSpentAttributes[i]));
|
||||
|
||||
if (attribute.getBase() >= 100)
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace MWGui
|
|||
getWidget(attribute, std::string("Attribute") + boost::lexical_cast<std::string>(idx));
|
||||
mAttributeWidgets.insert(std::make_pair(static_cast<int>(ESM::Attribute::sAttributeIds[idx]), attribute));
|
||||
attribute->setAttributeId(ESM::Attribute::sAttributeIds[idx]);
|
||||
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue(0, 0));
|
||||
attribute->setAttributeValue(Widgets::MWAttribute::AttributeValue());
|
||||
}
|
||||
|
||||
// Setup skills
|
||||
|
@ -74,7 +74,7 @@ namespace MWGui
|
|||
|
||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||
{
|
||||
mSkillValues.insert(std::make_pair(i, MWMechanics::Stat<float>()));
|
||||
mSkillValues.insert(std::make_pair(i, MWMechanics::SkillValue()));
|
||||
mSkillWidgetMap.insert(std::make_pair(i, static_cast<MyGUI::TextBox*> (0)));
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ namespace MWGui
|
|||
mFatigue->setUserString("Caption_HealthDescription", "#{sFatDesc}\n" + valStr);
|
||||
}
|
||||
|
||||
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value)
|
||||
void ReviewDialog::setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
std::map<int, Widgets::MWAttributePtr>::iterator attr = mAttributeWidgets.find(static_cast<int>(attributeId));
|
||||
if (attr == mAttributeWidgets.end())
|
||||
|
@ -161,7 +161,7 @@ namespace MWGui
|
|||
attr->second->setAttributeValue(value);
|
||||
}
|
||||
|
||||
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value)
|
||||
void ReviewDialog::setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
mSkillValues[skillId] = value;
|
||||
MyGUI::TextBox* widget = mSkillWidgetMap[skillId];
|
||||
|
@ -279,9 +279,9 @@ namespace MWGui
|
|||
continue;
|
||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
||||
float base = stat.getBase();
|
||||
float modified = stat.getModified();
|
||||
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||
int base = stat.getBase();
|
||||
int modified = stat.getModified();
|
||||
|
||||
std::string state = "normal";
|
||||
if (modified > base)
|
||||
|
|
|
@ -38,10 +38,10 @@ namespace MWGui
|
|||
void setMagicka(const MWMechanics::DynamicStat<float>& value);
|
||||
void setFatigue(const MWMechanics::DynamicStat<float>& value);
|
||||
|
||||
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::Stat<int>& value);
|
||||
void setAttribute(ESM::Attribute::AttributeID attributeId, const MWMechanics::AttributeValue& value);
|
||||
|
||||
void configureSkills(const SkillList& major, const SkillList& minor);
|
||||
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::Stat<float>& value);
|
||||
void setSkillValue(ESM::Skill::SkillEnum skillId, const MWMechanics::SkillValue& value);
|
||||
|
||||
virtual void open();
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace MWGui
|
|||
std::map<int, Widgets::MWAttributePtr> mAttributeWidgets;
|
||||
|
||||
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mSkillValues;
|
||||
std::map<int, MWMechanics::SkillValue > mSkillValues;
|
||||
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
||||
std::string mName, mRaceId, mBirthSignId;
|
||||
ESM::Class mKlass;
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace MWGui
|
|||
{
|
||||
|
||||
void EffectSourceVisitor::visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, float magnitude, float remainingTime)
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime)
|
||||
{
|
||||
MagicEffectInfo newEffectSource;
|
||||
newEffectSource.mKey = key;
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace MWGui
|
|||
std::map <int, std::vector<MagicEffectInfo> > mEffectSources;
|
||||
|
||||
virtual void visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, float magnitude, float remainingTime = -1);
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime = -1);
|
||||
};
|
||||
|
||||
class SpellIcons
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace MWGui
|
|||
|
||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||
{
|
||||
mSkillValues.insert(std::pair<int, MWMechanics::Stat<float> >(i, MWMechanics::Stat<float>()));
|
||||
mSkillValues.insert(std::pair<int, MWMechanics::SkillValue >(i, MWMechanics::SkillValue()));
|
||||
mSkillWidgetMap.insert(std::pair<int, MyGUI::TextBox*>(i, (MyGUI::TextBox*)NULL));
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace MWGui
|
|||
adjustWindowCaption();
|
||||
}
|
||||
|
||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
||||
void StatsWindow::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
static const char *ids[] =
|
||||
{
|
||||
|
@ -179,7 +179,7 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value)
|
||||
void StatsWindow::setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
mSkillValues[parSkill] = value;
|
||||
MyGUI::TextBox* widget = mSkillWidgetMap[(int)parSkill];
|
||||
|
@ -358,22 +358,20 @@ namespace MWGui
|
|||
continue;
|
||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||
const MWMechanics::Stat<float> &stat = mSkillValues.find(skillId)->second;
|
||||
float base = stat.getBase();
|
||||
float modified = stat.getModified();
|
||||
int progressPercent = (modified - float(static_cast<int>(modified))) * 100;
|
||||
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||
int base = stat.getBase();
|
||||
int modified = stat.getModified();
|
||||
int progressPercent = stat.getProgress() * 100;
|
||||
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
const ESM::Skill* skill = esmStore.get<ESM::Skill>().find(skillId);
|
||||
assert(skill);
|
||||
|
||||
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
|
||||
|
||||
const ESM::Attribute* attr =
|
||||
esmStore.get<ESM::Attribute>().find(skill->mData.mAttribute);
|
||||
assert(attr);
|
||||
|
||||
std::string state = "normal";
|
||||
if (modified > base)
|
||||
|
@ -484,7 +482,6 @@ namespace MWGui
|
|||
ESM::RankData rankData = faction->mData.mRankData[it->second+1];
|
||||
const ESM::Attribute* attr1 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[0]);
|
||||
const ESM::Attribute* attr2 = store.get<ESM::Attribute>().find(faction->mData.mAttribute[1]);
|
||||
assert(attr1 && attr2);
|
||||
|
||||
text += "\n#BF9959#{" + attr1->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute1)
|
||||
+ ", #{" + attr2->mName + "}: " + boost::lexical_cast<std::string>(rankData.mAttribute2);
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace MWGui
|
|||
void setPlayerName(const std::string& playerName);
|
||||
|
||||
/// Set value for the given ID.
|
||||
void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||
void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||
void setValue (const std::string& id, const std::string& value);
|
||||
void setValue (const std::string& id, int value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::Stat<float>& value);
|
||||
void setValue(const ESM::Skill::SkillEnum parSkill, const MWMechanics::SkillValue& value);
|
||||
|
||||
void configureSkills (const SkillList& major, const SkillList& minor);
|
||||
void setReputation (int reputation) { if (reputation != mReputation) mChanged = true; this->mReputation = reputation; }
|
||||
|
@ -61,7 +61,7 @@ namespace MWGui
|
|||
MyGUI::ScrollView* mSkillView;
|
||||
|
||||
SkillList mMajorSkills, mMinorSkills, mMiscSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mSkillValues;
|
||||
std::map<int, MWMechanics::SkillValue > mSkillValues;
|
||||
std::map<int, MyGUI::TextBox*> mSkillWidgetMap;
|
||||
std::map<std::string, MyGUI::Widget*> mFactionWidgetMap;
|
||||
FactionList mFactions; ///< Stores a list of factions and the current rank
|
||||
|
|
|
@ -296,10 +296,10 @@ namespace MWGui
|
|||
const MWMechanics::NpcStats &sellerStats = MWWorld::Class::get(mPtr).getNpcStats(mPtr);
|
||||
const MWMechanics::NpcStats &playerStats = MWWorld::Class::get(playerPtr).getNpcStats(playerPtr);
|
||||
|
||||
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||
float a1 = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 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.f);
|
||||
float d1 = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 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);
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ namespace MWGui
|
|||
|
||||
float hourlyHealthDelta = stats.getAttribute(ESM::Attribute::Endurance).getModified() * 0.1;
|
||||
|
||||
bool stunted = (stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0);
|
||||
bool stunted = (stats.getMagicEffects().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0);
|
||||
float fRestMagicMult = store.get<ESM::GameSetting>().find("fRestMagicMult")->getFloat();
|
||||
float hourlyMagickaDelta = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ namespace MWGui
|
|||
}
|
||||
if (mAttributeValueWidget)
|
||||
{
|
||||
AttributeValue::Type modified = mValue.getModified(), base = mValue.getBase();
|
||||
int modified = mValue.getModified(), base = mValue.getBase();
|
||||
static_cast<MyGUI::TextBox*>(mAttributeValueWidget)->setCaption(boost::lexical_cast<std::string>(modified));
|
||||
if (modified > base)
|
||||
mAttributeValueWidget->_setWidgetState("increased");
|
||||
|
@ -528,14 +528,9 @@ namespace MWGui
|
|||
|
||||
if (mBarTextWidget)
|
||||
{
|
||||
if (mValue >= 0 && mMax > 0)
|
||||
{
|
||||
std::stringstream out;
|
||||
out << mValue << "/" << mMax;
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
|
||||
}
|
||||
else
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption("");
|
||||
std::stringstream out;
|
||||
out << mValue << "/" << mMax;
|
||||
static_cast<MyGUI::TextBox*>(mBarTextWidget)->setCaption(out.str().c_str());
|
||||
}
|
||||
}
|
||||
void MWDynamicStat::setTitle(const std::string& text)
|
||||
|
|
|
@ -133,7 +133,7 @@ namespace MWGui
|
|||
public:
|
||||
MWAttribute();
|
||||
|
||||
typedef MWMechanics::Stat<int> AttributeValue;
|
||||
typedef MWMechanics::AttributeValue AttributeValue;
|
||||
|
||||
void setAttributeId(int attributeId);
|
||||
void setAttributeValue(const AttributeValue& value);
|
||||
|
|
|
@ -249,12 +249,12 @@ namespace MWGui
|
|||
// Setup player stats
|
||||
for (int i = 0; i < ESM::Attribute::Length; ++i)
|
||||
{
|
||||
mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::Stat<int>()));
|
||||
mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::AttributeValue()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < ESM::Skill::Length; ++i)
|
||||
{
|
||||
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::Stat<float>()));
|
||||
mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::SkillValue()));
|
||||
}
|
||||
|
||||
// Set up visibility
|
||||
|
@ -544,7 +544,7 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void WindowManager::setValue (const std::string& id, const MWMechanics::Stat<int>& value)
|
||||
void WindowManager::setValue (const std::string& id, const MWMechanics::AttributeValue& value)
|
||||
{
|
||||
mStatsWindow->setValue (id, value);
|
||||
mCharGen->setValue(id, value);
|
||||
|
@ -575,7 +575,7 @@ namespace MWGui
|
|||
}
|
||||
|
||||
|
||||
void WindowManager::setValue (int parSkill, const MWMechanics::Stat<float>& value)
|
||||
void WindowManager::setValue (int parSkill, const MWMechanics::SkillValue& value)
|
||||
{
|
||||
/// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we
|
||||
/// allow custom skills.
|
||||
|
@ -1178,12 +1178,12 @@ namespace MWGui
|
|||
return mGuiModes.back();
|
||||
}
|
||||
|
||||
std::map<int, MWMechanics::Stat<float> > WindowManager::getPlayerSkillValues()
|
||||
std::map<int, MWMechanics::SkillValue > WindowManager::getPlayerSkillValues()
|
||||
{
|
||||
return mPlayerSkillValues;
|
||||
}
|
||||
|
||||
std::map<int, MWMechanics::Stat<int> > WindowManager::getPlayerAttributeValues()
|
||||
std::map<int, MWMechanics::AttributeValue > WindowManager::getPlayerAttributeValues()
|
||||
{
|
||||
return mPlayerAttributes;
|
||||
}
|
||||
|
|
|
@ -152,8 +152,8 @@ namespace MWGui
|
|||
virtual void wmUpdateFps(float fps, unsigned int triangleCount, unsigned int batchCount);
|
||||
|
||||
///< Set value for the given ID.
|
||||
virtual void setValue (const std::string& id, const MWMechanics::Stat<int>& value);
|
||||
virtual void setValue (int parSkill, const MWMechanics::Stat<float>& value);
|
||||
virtual void setValue (const std::string& id, const MWMechanics::AttributeValue& value);
|
||||
virtual void setValue (int parSkill, const MWMechanics::SkillValue& value);
|
||||
virtual void setValue (const std::string& id, const MWMechanics::DynamicStat<float>& value);
|
||||
virtual void setValue (const std::string& id, const std::string& value);
|
||||
virtual void setValue (const std::string& id, int value);
|
||||
|
@ -229,8 +229,8 @@ namespace MWGui
|
|||
virtual void onFrame (float frameDuration);
|
||||
|
||||
/// \todo get rid of this stuff. Move it to the respective UI element classes, if needed.
|
||||
virtual std::map<int, MWMechanics::Stat<float> > getPlayerSkillValues();
|
||||
virtual std::map<int, MWMechanics::Stat<int> > getPlayerAttributeValues();
|
||||
virtual std::map<int, MWMechanics::SkillValue > getPlayerSkillValues();
|
||||
virtual std::map<int, MWMechanics::AttributeValue > getPlayerAttributeValues();
|
||||
virtual SkillList getPlayerMinorSkills();
|
||||
virtual SkillList getPlayerMajorSkills();
|
||||
|
||||
|
@ -346,9 +346,9 @@ namespace MWGui
|
|||
// Various stats about player as needed by window manager
|
||||
std::string mPlayerName;
|
||||
std::string mPlayerRaceId;
|
||||
std::map<int, MWMechanics::Stat<int> > mPlayerAttributes;
|
||||
std::map<int, MWMechanics::AttributeValue > mPlayerAttributes;
|
||||
SkillList mPlayerMajorSkills, mPlayerMinorSkills;
|
||||
std::map<int, MWMechanics::Stat<float> > mPlayerSkillValues;
|
||||
std::map<int, MWMechanics::SkillValue > mPlayerSkillValues;
|
||||
|
||||
MyGUI::Gui *mGui; // Gui
|
||||
std::vector<GuiMode> mGuiModes;
|
||||
|
|
|
@ -126,7 +126,8 @@ namespace MWMechanics
|
|||
return mSpells;
|
||||
}
|
||||
|
||||
void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector<Effect> effects, const std::string &displayName)
|
||||
void ActiveSpells::addSpell(const std::string &id, bool stack, std::vector<Effect> effects,
|
||||
const std::string &displayName, const std::string& casterHandle)
|
||||
{
|
||||
bool exists = false;
|
||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||
|
@ -139,6 +140,7 @@ namespace MWMechanics
|
|||
params.mTimeStamp = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
params.mEffects = effects;
|
||||
params.mDisplayName = displayName;
|
||||
params.mCasterHandle = casterHandle;
|
||||
|
||||
if (!exists || stack)
|
||||
mSpells.insert (std::make_pair(id, params));
|
||||
|
@ -148,6 +150,12 @@ namespace MWMechanics
|
|||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::removeEffects(const std::string &id)
|
||||
{
|
||||
mSpells.erase(Misc::StringUtils::lowerCase(id));
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::visitEffectSources(EffectSourceVisitor &visitor) const
|
||||
{
|
||||
for (TContainer::const_iterator it = begin(); it != end(); ++it)
|
||||
|
@ -164,14 +172,22 @@ namespace MWMechanics
|
|||
float magnitude = effectIt->mMagnitude;
|
||||
|
||||
if (magnitude)
|
||||
visitor.visit(effectIt->mKey, name, magnitude, remainingTime);
|
||||
visitor.visit(effectIt->mKey, name, it->second.mCasterHandle, magnitude, remainingTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveSpells::purgeAll()
|
||||
void ActiveSpells::purgeAll(float chance)
|
||||
{
|
||||
mSpells.clear();
|
||||
for (TContainer::iterator it = mSpells.begin(); it != mSpells.end(); )
|
||||
{
|
||||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (roll < chance)
|
||||
mSpells.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
|
||||
void ActiveSpells::purgeEffect(short effectId)
|
||||
|
@ -187,6 +203,6 @@ namespace MWMechanics
|
|||
effectIt++;
|
||||
}
|
||||
}
|
||||
|
||||
mSpellsChanged = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,8 +37,8 @@ namespace MWMechanics
|
|||
MWWorld::TimeStamp mTimeStamp;
|
||||
std::string mDisplayName;
|
||||
|
||||
// TODO: To handle CASTER_LINKED flag (spell is purged when caster dies),
|
||||
// we should probably store a handle to the caster here.
|
||||
// Handle to the caster that that inflicted this spell on us
|
||||
std::string mCasterHandle;
|
||||
};
|
||||
|
||||
typedef std::multimap<std::string, ActiveSpellParams > TContainer;
|
||||
|
@ -76,14 +76,19 @@ namespace MWMechanics
|
|||
/// \param stack If false, the spell is not added if one with the same ID exists already.
|
||||
/// \param effects
|
||||
/// \param displayName Name for display in magic menu.
|
||||
/// \param casterHandle
|
||||
///
|
||||
void addSpell (const std::string& id, bool stack, std::vector<Effect> effects, const std::string& displayName);
|
||||
void addSpell (const std::string& id, bool stack, std::vector<Effect> effects,
|
||||
const std::string& displayName, const std::string& casterHandle);
|
||||
|
||||
/// Remove all active effects with this id
|
||||
/// Removes the active effects from this spell/potion/.. with \a id
|
||||
void removeEffects (const std::string& id);
|
||||
|
||||
/// Remove all active effects with this effect id
|
||||
void purgeEffect (short effectId);
|
||||
|
||||
/// Remove all active effects
|
||||
void purgeAll ();
|
||||
/// Remove all active effects, if roll succeeds (for each effect)
|
||||
void purgeAll (float chance);
|
||||
|
||||
bool isSpellActive (std::string id) const;
|
||||
///< case insensitive
|
||||
|
|
|
@ -88,6 +88,68 @@ bool disintegrateSlot (MWWorld::Ptr ptr, int slot, float disintegrate)
|
|||
|
||||
namespace MWMechanics
|
||||
{
|
||||
|
||||
class SoulTrap : public MWMechanics::EffectSourceVisitor
|
||||
{
|
||||
MWWorld::Ptr mCreature;
|
||||
MWWorld::Ptr mActor;
|
||||
public:
|
||||
SoulTrap(MWWorld::Ptr trappedCreature)
|
||||
: mCreature(trappedCreature) {}
|
||||
|
||||
virtual void visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime = -1)
|
||||
{
|
||||
if (key.mId != ESM::MagicEffect::Soultrap)
|
||||
return;
|
||||
if (magnitude <= 0)
|
||||
return;
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
||||
MWWorld::Ptr caster = world->searchPtrViaHandle(casterHandle);
|
||||
if (caster.isEmpty() || !caster.getClass().isActor())
|
||||
return;
|
||||
|
||||
static const float fSoulgemMult = world->getStore().get<ESM::GameSetting>().find("fSoulgemMult")->getFloat();
|
||||
|
||||
float creatureSoulValue = mCreature.get<ESM::Creature>()->mBase->mData.mSoul;
|
||||
|
||||
// Use the smallest soulgem that is large enough to hold the soul
|
||||
MWWorld::ContainerStore& container = caster.getClass().getContainerStore(caster);
|
||||
MWWorld::ContainerStoreIterator gem = container.end();
|
||||
float gemCapacity = std::numeric_limits<float>().max();
|
||||
std::string soulgemFilter = "misc_soulgem"; // no other way to check for soulgems? :/
|
||||
for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous);
|
||||
it != container.end(); ++it)
|
||||
{
|
||||
const std::string& id = it->getCellRef().mRefID;
|
||||
if (id.size() >= soulgemFilter.size()
|
||||
&& id.substr(0,soulgemFilter.size()) == soulgemFilter)
|
||||
{
|
||||
float thisGemCapacity = it->get<ESM::Miscellaneous>()->mBase->mData.mValue * fSoulgemMult;
|
||||
if (thisGemCapacity >= creatureSoulValue && thisGemCapacity < gemCapacity
|
||||
&& it->getCellRef().mSoul.empty())
|
||||
{
|
||||
gem = it;
|
||||
gemCapacity = thisGemCapacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gem == container.end())
|
||||
return;
|
||||
|
||||
// Set the soul on just one of the gems, not the whole stack
|
||||
gem->getContainerStore()->unstack(*gem, caster);
|
||||
gem->getCellRef().mSoul = mCreature.getCellRef().mRefID;
|
||||
|
||||
if (caster.getRefData().getHandle() == "player")
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sSoultrapSuccess}");
|
||||
}
|
||||
};
|
||||
|
||||
void Actors::updateActor (const MWWorld::Ptr& ptr, float duration)
|
||||
{
|
||||
// magic effects
|
||||
|
@ -216,7 +278,7 @@ namespace MWMechanics
|
|||
{
|
||||
// the actor is sleeping, restore health and magicka
|
||||
|
||||
bool stunted = stats.getMagicEffects ().get(MWMechanics::EffectKey(ESM::MagicEffect::StuntedMagicka)).mMagnitude > 0;
|
||||
bool stunted = stats.getMagicEffects ().get(ESM::MagicEffect::StuntedMagicka).mMagnitude > 0;
|
||||
|
||||
DynamicStat<float> health = stats.getHealth();
|
||||
health.setCurrent (health.getCurrent() + 0.1 * endurance);
|
||||
|
@ -255,7 +317,7 @@ namespace MWMechanics
|
|||
// attributes
|
||||
for(int i = 0;i < ESM::Attribute::Length;++i)
|
||||
{
|
||||
Stat<int> stat = creatureStats.getAttribute(i);
|
||||
AttributeValue stat = creatureStats.getAttribute(i);
|
||||
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyAttribute, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainAttribute, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::AbsorbAttribute, i)).mMagnitude);
|
||||
|
@ -267,23 +329,23 @@ namespace MWMechanics
|
|||
for(int i = 0;i < 3;++i)
|
||||
{
|
||||
DynamicStat<float> stat = creatureStats.getDynamic(i);
|
||||
stat.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifyHealth+i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainHealth+i)).mMagnitude);
|
||||
stat.setModifier(effects.get(ESM::MagicEffect::FortifyHealth+i).mMagnitude -
|
||||
effects.get(ESM::MagicEffect::DrainHealth+i).mMagnitude);
|
||||
|
||||
|
||||
float currentDiff = creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::RestoreHealth+i)).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::DamageHealth+i)).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth+i)).mMagnitude;
|
||||
float currentDiff = creatureStats.getMagicEffects().get(ESM::MagicEffect::RestoreHealth+i).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth+i).mMagnitude
|
||||
- creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth+i).mMagnitude;
|
||||
stat.setCurrent(stat.getCurrent() + currentDiff * duration);
|
||||
|
||||
creatureStats.setDynamic(i, stat);
|
||||
}
|
||||
|
||||
// Apply disintegration (reduces item health)
|
||||
float disintegrateWeapon = effects.get(EffectKey(ESM::MagicEffect::DisintegrateWeapon)).mMagnitude;
|
||||
float disintegrateWeapon = effects.get(ESM::MagicEffect::DisintegrateWeapon).mMagnitude;
|
||||
if (disintegrateWeapon > 0)
|
||||
disintegrateSlot(ptr, MWWorld::InventoryStore::Slot_CarriedRight, disintegrateWeapon*duration);
|
||||
float disintegrateArmor = effects.get(EffectKey(ESM::MagicEffect::DisintegrateArmor)).mMagnitude;
|
||||
float disintegrateArmor = effects.get(ESM::MagicEffect::DisintegrateArmor).mMagnitude;
|
||||
if (disintegrateArmor > 0)
|
||||
{
|
||||
// According to UESP
|
||||
|
@ -315,7 +377,7 @@ namespace MWMechanics
|
|||
DynamicStat<float> health = creatureStats.getHealth();
|
||||
for (unsigned int i=0; i<sizeof(damageEffects)/sizeof(int); ++i)
|
||||
{
|
||||
float magnitude = creatureStats.getMagicEffects().get(EffectKey(damageEffects[i])).mMagnitude;
|
||||
float magnitude = creatureStats.getMagicEffects().get(damageEffects[i]).mMagnitude;
|
||||
|
||||
if (damageEffects[i] == ESM::MagicEffect::SunDamage)
|
||||
{
|
||||
|
@ -362,7 +424,7 @@ namespace MWMechanics
|
|||
for (std::map<int, std::string>::iterator it = boundItemsMap.begin(); it != boundItemsMap.end(); ++it)
|
||||
{
|
||||
bool found = creatureStats.mBoundItems.find(it->first) != creatureStats.mBoundItems.end();
|
||||
int magnitude = creatureStats.getMagicEffects().get(EffectKey(it->first)).mMagnitude;
|
||||
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude;
|
||||
if (found != (magnitude > 0))
|
||||
{
|
||||
std::string item = "bound_" + it->second;
|
||||
|
@ -410,7 +472,7 @@ namespace MWMechanics
|
|||
for (std::map<int, std::string>::iterator it = summonMap.begin(); it != summonMap.end(); ++it)
|
||||
{
|
||||
bool found = creatureStats.mSummonedCreatures.find(it->first) != creatureStats.mSummonedCreatures.end();
|
||||
int magnitude = creatureStats.getMagicEffects().get(EffectKey(it->first)).mMagnitude;
|
||||
int magnitude = creatureStats.getMagicEffects().get(it->first).mMagnitude;
|
||||
if (found != (magnitude > 0))
|
||||
{
|
||||
if (magnitude > 0)
|
||||
|
@ -461,7 +523,7 @@ namespace MWMechanics
|
|||
// skills
|
||||
for(int i = 0;i < ESM::Skill::Length;++i)
|
||||
{
|
||||
Stat<float>& skill = npcStats.getSkill(i);
|
||||
SkillValue& skill = npcStats.getSkill(i);
|
||||
skill.setModifier(effects.get(EffectKey(ESM::MagicEffect::FortifySkill, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::DrainSkill, i)).mMagnitude -
|
||||
effects.get(EffectKey(ESM::MagicEffect::AbsorbSkill, i)).mMagnitude);
|
||||
|
@ -705,6 +767,13 @@ namespace MWMechanics
|
|||
|
||||
iter->second->kill();
|
||||
|
||||
// Apply soultrap
|
||||
if (iter->first.getTypeName() == typeid(ESM::Creature).name())
|
||||
{
|
||||
SoulTrap soulTrap (iter->first);
|
||||
stats.getActiveSpells().visitEffectSources(soulTrap);
|
||||
}
|
||||
|
||||
// Reset magic effects and recalculate derived effects
|
||||
// One case where we need this is to make sure bound items are removed upon death
|
||||
stats.setMagicEffects(MWMechanics::MagicEffects());
|
||||
|
@ -714,6 +783,7 @@ namespace MWMechanics
|
|||
|
||||
if(cls.isEssential(iter->first))
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace MWMechanics
|
|||
- gmst.find ("fFatigueMult")->getFloat() * (1-normalised);
|
||||
}
|
||||
|
||||
const Stat<int> &CreatureStats::getAttribute(int index) const
|
||||
const AttributeValue &CreatureStats::getAttribute(int index) const
|
||||
{
|
||||
if (index < 0 || index > 7) {
|
||||
throw std::runtime_error("attribute index is out of range");
|
||||
|
@ -158,20 +158,20 @@ namespace MWMechanics
|
|||
|
||||
void CreatureStats::setAttribute(int index, int base)
|
||||
{
|
||||
MWMechanics::Stat<int> current = getAttribute(index);
|
||||
AttributeValue current = getAttribute(index);
|
||||
current.setBase(base);
|
||||
setAttribute(index, current);
|
||||
}
|
||||
|
||||
void CreatureStats::setAttribute(int index, const Stat<int> &value)
|
||||
void CreatureStats::setAttribute(int index, const AttributeValue &value)
|
||||
{
|
||||
if (index < 0 || index > 7) {
|
||||
throw std::runtime_error("attribute index is out of range");
|
||||
}
|
||||
|
||||
const Stat<int>& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index];
|
||||
const AttributeValue& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index];
|
||||
|
||||
if (value.getModified() != currentValue.getModified())
|
||||
if (value != currentValue)
|
||||
{
|
||||
if (index != ESM::Attribute::Luck
|
||||
&& index != ESM::Attribute::Personality
|
||||
|
@ -228,8 +228,8 @@ namespace MWMechanics
|
|||
|
||||
void CreatureStats::setMagicEffects(const MagicEffects &effects)
|
||||
{
|
||||
if (effects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude
|
||||
!= mMagicEffects.get(MWMechanics::EffectKey(ESM::MagicEffect::FortifyMaximumMagicka)).mMagnitude)
|
||||
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude
|
||||
!= mMagicEffects.get(ESM::MagicEffect::FortifyMaximumMagicka).mMagnitude)
|
||||
mRecalcDynamicStats = true;
|
||||
|
||||
mMagicEffects = effects;
|
||||
|
@ -266,8 +266,10 @@ namespace MWMechanics
|
|||
if (mDead)
|
||||
{
|
||||
if (mDynamic[0].getCurrent()<1)
|
||||
mDynamic[0].setCurrent (1);
|
||||
|
||||
{
|
||||
mDynamic[0].setModified(mDynamic[0].getModified(), 1);
|
||||
mDynamic[0].setCurrent(1);
|
||||
}
|
||||
if (mDynamic[0].getCurrent()>=1)
|
||||
mDead = false;
|
||||
}
|
||||
|
@ -343,7 +345,7 @@ namespace MWMechanics
|
|||
float evasion = (getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||
(getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||
evasion *= getFatigueTerm();
|
||||
evasion += mMagicEffects.get(EffectKey(ESM::MagicEffect::Sanctuary)).mMagnitude;
|
||||
evasion += mMagicEffects.get(ESM::MagicEffect::Sanctuary).mMagnitude;
|
||||
|
||||
return evasion;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace MWMechanics
|
|||
///
|
||||
class CreatureStats
|
||||
{
|
||||
Stat<int> mAttributes[8];
|
||||
AttributeValue mAttributes[8];
|
||||
DynamicStat<float> mDynamic[3]; // health, magicka, fatigue
|
||||
int mLevel;
|
||||
Spells mSpells;
|
||||
|
@ -49,7 +49,7 @@ namespace MWMechanics
|
|||
|
||||
protected:
|
||||
bool mIsWerewolf;
|
||||
Stat<int> mWerewolfAttributes[8];
|
||||
AttributeValue mWerewolfAttributes[8];
|
||||
|
||||
public:
|
||||
CreatureStats();
|
||||
|
@ -65,7 +65,7 @@ namespace MWMechanics
|
|||
bool canUsePower (const std::string& power) const;
|
||||
void usePower (const std::string& power);
|
||||
|
||||
const Stat<int> & getAttribute(int index) const;
|
||||
const AttributeValue & getAttribute(int index) const;
|
||||
|
||||
const DynamicStat<float> & getHealth() const;
|
||||
|
||||
|
@ -94,7 +94,7 @@ namespace MWMechanics
|
|||
|
||||
MagicEffects & getMagicEffects();
|
||||
|
||||
void setAttribute(int index, const Stat<int> &value);
|
||||
void setAttribute(int index, const AttributeValue &value);
|
||||
// Shortcut to set only the base
|
||||
void setAttribute(int index, int base);
|
||||
|
||||
|
|
|
@ -56,7 +56,8 @@ namespace MWMechanics
|
|||
struct EffectSourceVisitor
|
||||
{
|
||||
virtual void visit (MWMechanics::EffectKey key,
|
||||
const std::string& sourceName, float magnitude, float remainingTime = -1) = 0;
|
||||
const std::string& sourceName, const std::string& casterHandle,
|
||||
float magnitude, float remainingTime = -1) = 0;
|
||||
};
|
||||
|
||||
/// \brief Effects currently affecting a NPC or creature
|
||||
|
|
|
@ -499,10 +499,10 @@ namespace MWMechanics
|
|||
// otherwise one would get different prices when exiting and re-entering the dialogue window...
|
||||
int clampedDisposition = std::max(0, std::min(getDerivedDisposition(ptr)
|
||||
+ MWBase::Environment::get().getDialogueManager()->getTemporaryDispositionChange(),100));
|
||||
float a = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||
float a = std::min(playerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||
float b = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||
float c = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||
float d = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100.f);
|
||||
float d = std::min(sellerStats.getSkill(ESM::Skill::Mercantile).getModified(), 100);
|
||||
float e = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
|
||||
float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void MWMechanics::NpcStats::setMovementFlag (Flag flag, bool state)
|
|||
mMovementFlags &= ~flag;
|
||||
}
|
||||
|
||||
const MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index) const
|
||||
const MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) const
|
||||
{
|
||||
if (index<0 || index>=ESM::Skill::Length)
|
||||
throw std::runtime_error ("skill index out of range");
|
||||
|
@ -92,7 +92,7 @@ const MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index) cons
|
|||
return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]);
|
||||
}
|
||||
|
||||
MWMechanics::Stat<float>& MWMechanics::NpcStats::getSkill (int index)
|
||||
MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index)
|
||||
{
|
||||
if (index<0 || index>=ESM::Skill::Length)
|
||||
throw std::runtime_error ("skill index out of range");
|
||||
|
@ -197,34 +197,25 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
|
|||
if(mIsWerewolf)
|
||||
return;
|
||||
|
||||
float base = getSkill (skillIndex).getBase();
|
||||
MWMechanics::SkillValue value = getSkill (skillIndex);
|
||||
|
||||
int level = static_cast<int> (base);
|
||||
value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType));
|
||||
|
||||
base += getSkillGain (skillIndex, class_, usageType);
|
||||
|
||||
if (static_cast<int> (base)!=level)
|
||||
if (value.getProgress()>=1)
|
||||
{
|
||||
// skill leveled up
|
||||
increaseSkill(skillIndex, class_, false);
|
||||
}
|
||||
else
|
||||
getSkill (skillIndex).setBase (base);
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress)
|
||||
{
|
||||
float base = getSkill (skillIndex).getBase();
|
||||
int base = getSkill (skillIndex).getBase();
|
||||
|
||||
int level = static_cast<int> (base);
|
||||
|
||||
if (level >= 100)
|
||||
if (base >= 100)
|
||||
return;
|
||||
|
||||
if (preserveProgress)
|
||||
base += 1;
|
||||
else
|
||||
base = level+1;
|
||||
base += 1;
|
||||
|
||||
// if this is a major or minor skill of the class, increase level progress
|
||||
bool levelProgress = false;
|
||||
|
@ -260,6 +251,8 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
|
|||
}
|
||||
|
||||
getSkill (skillIndex).setBase (base);
|
||||
if (!preserveProgress)
|
||||
getSkill(skillIndex).setProgress(0);
|
||||
}
|
||||
|
||||
int MWMechanics::NpcStats::getLevelProgress () const
|
||||
|
@ -387,7 +380,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
|||
// Oh, Bethesda. It's "Intelligence".
|
||||
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
|
||||
ESM::Attribute::sAttributeNames[i]);
|
||||
mWerewolfAttributes[i].setModified(int(gmst.find(name)->getFloat()), 0);
|
||||
mWerewolfAttributes[i].setBase(int(gmst.find(name)->getFloat()));
|
||||
}
|
||||
|
||||
for(size_t i = 0;i < ESM::Skill::Length;i++)
|
||||
|
@ -401,7 +394,7 @@ void MWMechanics::NpcStats::setWerewolf (bool set)
|
|||
// "Mercantile"! >_<
|
||||
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
|
||||
ESM::Skill::sSkillNames[i]);
|
||||
mWerewolfSkill[i].setModified(int(gmst.find(name)->getFloat()), 0);
|
||||
mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat()));
|
||||
}
|
||||
}
|
||||
mIsWerewolf = set;
|
||||
|
|
|
@ -45,8 +45,8 @@ namespace MWMechanics
|
|||
DrawState_ mDrawState;
|
||||
int mDisposition;
|
||||
unsigned int mMovementFlags;
|
||||
Stat<float> mSkill[27];
|
||||
Stat<float> mWerewolfSkill[27];
|
||||
SkillValue mSkill[27];
|
||||
SkillValue mWerewolfSkill[27];
|
||||
int mBounty;
|
||||
std::set<std::string> mExpelled;
|
||||
std::map<std::string, int> mFactionReputation;
|
||||
|
@ -94,8 +94,8 @@ namespace MWMechanics
|
|||
|
||||
void setMovementFlag (Flag flag, bool state);
|
||||
|
||||
const Stat<float>& getSkill (int index) const;
|
||||
Stat<float>& getSkill (int index);
|
||||
const SkillValue& getSkill (int index) const;
|
||||
SkillValue& getSkill (int index);
|
||||
|
||||
const std::map<std::string, int>& getFactionRanks() const;
|
||||
std::map<std::string, int>& getFactionRanks();
|
||||
|
|
|
@ -24,21 +24,13 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
|
|||
MWWorld::LiveCellRef<ESM::Repair> *ref =
|
||||
mTool.get<ESM::Repair>();
|
||||
|
||||
// unstack tool if required
|
||||
player.getClass().getContainerStore(player).unstack(mTool, player);
|
||||
|
||||
// reduce number of uses left
|
||||
int uses = (mTool.getCellRef().mCharge != -1) ? mTool.getCellRef().mCharge : ref->mBase->mData.mUses;
|
||||
mTool.getCellRef().mCharge = uses-1;
|
||||
|
||||
// unstack tool if required
|
||||
if (mTool.getRefData().getCount() > 1 && uses == ref->mBase->mData.mUses)
|
||||
{
|
||||
MWWorld::ContainerStore& store = MWWorld::Class::get(player).getContainerStore(player);
|
||||
MWWorld::ContainerStoreIterator it = store.add(mTool, player);
|
||||
it->getRefData().setCount(mTool.getRefData().getCount()-1);
|
||||
it->getCellRef().mCharge = -1;
|
||||
|
||||
mTool.getRefData().setCount(1);
|
||||
}
|
||||
|
||||
MWMechanics::CreatureStats& stats = MWWorld::Class::get(player).getCreatureStats(player);
|
||||
MWMechanics::NpcStats& npcStats = MWWorld::Class::get(player).getNpcStats(player);
|
||||
|
||||
|
|
|
@ -135,7 +135,8 @@ namespace MWMechanics
|
|||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
||||
magnitude *= magnitudeMult;
|
||||
|
||||
if (target.getClass().isActor() && !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
|
||||
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
||||
if (target.getClass().isActor() && hasDuration)
|
||||
{
|
||||
ActiveSpells::Effect effect;
|
||||
effect.mKey = MWMechanics::EffectKey(*effectIt);
|
||||
|
@ -154,12 +155,23 @@ namespace MWMechanics
|
|||
ActiveSpells::Effect effect_ = effect;
|
||||
effect_.mMagnitude *= -1;
|
||||
effects.push_back(effect_);
|
||||
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true, effects, mSourceName);
|
||||
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
|
||||
effects, mSourceName, caster.getRefData().getHandle());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
applyInstantEffect(target, effectIt->mEffectID, magnitude);
|
||||
applyInstantEffect(target, EffectKey(*effectIt), magnitude);
|
||||
|
||||
// HACK: Damage attribute/skill actually has a duration, even though the actual effect is instant and permanent.
|
||||
// This was probably just done to have the effect visible in the magic menu for a while
|
||||
// to notify the player they've been damaged?
|
||||
if (effectIt->mEffectID == ESM::MagicEffect::DamageAttribute
|
||||
|| effectIt->mEffectID == ESM::MagicEffect::DamageSkill
|
||||
|| effectIt->mEffectID == ESM::MagicEffect::RestoreAttribute
|
||||
|| effectIt->mEffectID == ESM::MagicEffect::RestoreSkill
|
||||
)
|
||||
applyInstantEffect(target, EffectKey(*effectIt), magnitude);
|
||||
|
||||
if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)
|
||||
{
|
||||
|
@ -198,11 +210,13 @@ namespace MWMechanics
|
|||
inflict(caster, target, reflectedEffects, range, true);
|
||||
|
||||
if (appliedLastingEffects.size())
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects, mSourceName);
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().addSpell(mId, mStack, appliedLastingEffects,
|
||||
mSourceName, caster.getRefData().getHandle());
|
||||
}
|
||||
|
||||
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, short effectId, float magnitude)
|
||||
void CastSpell::applyInstantEffect(const MWWorld::Ptr &target, MWMechanics::EffectKey effect, float magnitude)
|
||||
{
|
||||
short effectId = effect.mId;
|
||||
if (!target.getClass().isActor())
|
||||
{
|
||||
if (effectId == ESM::MagicEffect::Lock)
|
||||
|
@ -225,6 +239,28 @@ namespace MWMechanics
|
|||
}
|
||||
else
|
||||
{
|
||||
if (effectId == ESM::MagicEffect::DamageAttribute || effectId == ESM::MagicEffect::RestoreAttribute)
|
||||
{
|
||||
int attribute = effect.mArg;
|
||||
AttributeValue value = target.getClass().getCreatureStats(target).getAttribute(attribute);
|
||||
if (effectId == ESM::MagicEffect::DamageAttribute)
|
||||
value.damage(magnitude);
|
||||
else
|
||||
value.restore(magnitude);
|
||||
target.getClass().getCreatureStats(target).setAttribute(attribute, value);
|
||||
}
|
||||
else if (effectId == ESM::MagicEffect::DamageSkill || effectId == ESM::MagicEffect::RestoreSkill)
|
||||
{
|
||||
if (target.getTypeName() != typeid(ESM::NPC).name())
|
||||
return;
|
||||
int skill = effect.mArg;
|
||||
SkillValue& value = target.getClass().getNpcStats(target).getSkill(skill);
|
||||
if (effectId == ESM::MagicEffect::DamageSkill)
|
||||
value.damage(magnitude);
|
||||
else
|
||||
value.restore(magnitude);
|
||||
}
|
||||
|
||||
if (effectId == ESM::MagicEffect::CurePoison)
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeEffect(ESM::MagicEffect::Poison);
|
||||
else if (effectId == ESM::MagicEffect::CureParalyzation)
|
||||
|
@ -236,7 +272,7 @@ namespace MWMechanics
|
|||
else if (effectId == ESM::MagicEffect::CureCorprusDisease)
|
||||
target.getClass().getCreatureStats(target).getSpells().purgeCorprusDisease();
|
||||
else if (effectId == ESM::MagicEffect::Dispel)
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll();
|
||||
target.getClass().getCreatureStats(target).getActiveSpells().purgeAll(magnitude);
|
||||
else if (effectId == ESM::MagicEffect::RemoveCurse)
|
||||
target.getClass().getCreatureStats(target).getSpells().purgeCurses();
|
||||
|
||||
|
@ -398,7 +434,8 @@ namespace MWMechanics
|
|||
int roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||
if (!fail && roll >= successChance)
|
||||
{
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
||||
if (mCaster.getRefData().getHandle() == "player")
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
|
||||
fail = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ namespace MWMechanics
|
|||
void inflict (const MWWorld::Ptr& target, const MWWorld::Ptr& caster,
|
||||
const ESM::EffectList& effects, ESM::RangeType range, bool reflected=false);
|
||||
|
||||
void applyInstantEffect (const MWWorld::Ptr& target, short effectId, float magnitude);
|
||||
void applyInstantEffect (const MWWorld::Ptr& target, MWMechanics::EffectKey effect, float magnitude);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -34,13 +34,14 @@ namespace MWMechanics
|
|||
random.resize(spell->mEffects.mList.size());
|
||||
for (unsigned int i=0; i<random.size();++i)
|
||||
random[i] = static_cast<float> (std::rand()) / RAND_MAX;
|
||||
mSpells.insert (std::make_pair (spellId, random));
|
||||
mSpells.insert (std::make_pair (Misc::StringUtils::lowerCase(spellId), random));
|
||||
}
|
||||
}
|
||||
|
||||
void Spells::remove (const std::string& spellId)
|
||||
{
|
||||
TContainer::iterator iter = mSpells.find (spellId);
|
||||
std::string lower = Misc::StringUtils::lowerCase(spellId);
|
||||
TContainer::iterator iter = mSpells.find (lower);
|
||||
|
||||
if (iter!=mSpells.end())
|
||||
mSpells.erase (iter);
|
||||
|
@ -192,7 +193,7 @@ namespace MWMechanics
|
|||
effectIt != list.mList.end(); ++effectIt, ++i)
|
||||
{
|
||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * it->second[i];
|
||||
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, magnitude);
|
||||
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -205,6 +205,46 @@ namespace MWMechanics
|
|||
{
|
||||
return !(left==right);
|
||||
}
|
||||
|
||||
class AttributeValue
|
||||
{
|
||||
int mBase;
|
||||
int mModifier;
|
||||
int mDamage;
|
||||
|
||||
public:
|
||||
AttributeValue() : mBase(0), mModifier(0), mDamage(0) {}
|
||||
|
||||
int getModified() const { return std::max(0, mBase - mDamage + mModifier); }
|
||||
int getBase() const { return mBase; }
|
||||
int getModifier() const { return mModifier; }
|
||||
|
||||
void setBase(int base) { mBase = std::max(0, base); }
|
||||
void setModifier(int mod) { mModifier = mod; }
|
||||
|
||||
void damage(int damage) { mDamage += damage; }
|
||||
void restore(int amount) { mDamage -= std::min(mDamage, amount); }
|
||||
int getDamage() const { return mDamage; }
|
||||
};
|
||||
|
||||
class SkillValue : public AttributeValue
|
||||
{
|
||||
float mProgress;
|
||||
public:
|
||||
float getProgress() const { return mProgress; }
|
||||
void setProgress(float progress) { mProgress = progress; }
|
||||
};
|
||||
|
||||
inline bool operator== (const AttributeValue& left, const AttributeValue& right)
|
||||
{
|
||||
return left.getBase() == right.getBase()
|
||||
&& left.getModifier() == right.getModifier()
|
||||
&& left.getDamage() == right.getDamage();
|
||||
}
|
||||
inline bool operator!= (const AttributeValue& left, const AttributeValue& right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -664,11 +664,12 @@ void NpcAnimation::showCarriedLeft(bool show)
|
|||
{
|
||||
Ogre::Vector3 glowColor = getEnchantmentColor(*iter);
|
||||
std::string mesh = MWWorld::Class::get(*iter).getModel(*iter);
|
||||
addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
||||
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor);
|
||||
|
||||
if (iter->getTypeName() == typeid(ESM::Light).name())
|
||||
addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get<ESM::Light>()->mBase);
|
||||
if (addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
||||
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor))
|
||||
{
|
||||
if (iter->getTypeName() == typeid(ESM::Light).name())
|
||||
addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get<ESM::Light>()->mBase);
|
||||
}
|
||||
}
|
||||
else
|
||||
removeIndividualPart(ESM::PRT_Shield);
|
||||
|
|
|
@ -328,7 +328,7 @@ void RenderingManager::update (float duration, bool paused)
|
|||
|
||||
MWWorld::Ptr player = world->getPlayer().getPlayer();
|
||||
|
||||
int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
|
||||
int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).mMagnitude;
|
||||
mRendering.getFader()->setFactor(std::max(0.f, 1.f-(blind / 100.f)));
|
||||
setAmbientMode();
|
||||
|
||||
|
@ -593,7 +593,7 @@ void RenderingManager::setAmbientColour(const Ogre::ColourValue& colour)
|
|||
mAmbientColor = colour;
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||
int nightEye = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::NightEye)).mMagnitude;
|
||||
int nightEye = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::NightEye).mMagnitude;
|
||||
Ogre::ColourValue final = colour;
|
||||
final += Ogre::ColourValue(0.7,0.7,0.7,0) * std::min(1.f, (nightEye/100.f));
|
||||
|
||||
|
|
|
@ -358,5 +358,14 @@ op 0x2000223: GetLineOfSightExplicit
|
|||
op 0x2000224: ToggleAI
|
||||
op 0x2000225: ToggleAIExplicit
|
||||
op 0x2000226: COE
|
||||
|
||||
opcodes 0x2000227-0x3ffffff unused
|
||||
op 0x2000227: Cast
|
||||
op 0x2000228: Cast, explicit
|
||||
op 0x2000229: ExplodeSpell
|
||||
op 0x200022a: ExplodeSpell, explicit
|
||||
op 0x200022b: RemoveSpellEffects
|
||||
op 0x200022c: RemoveSpellEffects, explicit
|
||||
op 0x200022d: RemoveEffects
|
||||
op 0x200022e: RemoveEffects, explicit
|
||||
op 0x200022f: Resurrect
|
||||
op 0x2000230: Resurrect, explicit
|
||||
opcodes 0x200022f-0x3ffffff unused
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
|
@ -700,6 +701,42 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class OpCast : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string spell = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
std::string targetId = ::Misc::StringUtils::lowerCase(runtime.getStringLiteral (runtime[0].mInteger));
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Ptr target = MWBase::Environment::get().getWorld()->getPtr (targetId, false);
|
||||
|
||||
MWMechanics::CastSpell cast(ptr, target);
|
||||
cast.cast(spell);
|
||||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class OpExplodeSpell : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string spell = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWMechanics::CastSpell cast(ptr, ptr);
|
||||
cast.cast(spell);
|
||||
}
|
||||
};
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
|
@ -761,6 +798,10 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Misc::opcodeToggleGodMode, new OpToggleGodMode);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeDisableLevitation, new OpEnableLevitation<false>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeEnableLevitation, new OpEnableLevitation<true>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeCast, new OpCast<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeCastExplicit, new OpCast<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpell, new OpExplodeSpell<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Misc::opcodeExplodeSpellExplicit, new OpExplodeSpell<ExplicitRef>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,8 +124,8 @@ namespace MWScript
|
|||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWMechanics::Stat<int> attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
|
||||
attribute.setModified (value, 0);
|
||||
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
|
||||
attribute.setBase (value - (attribute.getModified() - attribute.getBase()));
|
||||
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
||||
}
|
||||
};
|
||||
|
@ -146,15 +146,11 @@ namespace MWScript
|
|||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWMechanics::Stat<int> attribute = MWWorld::Class::get(ptr)
|
||||
MWMechanics::AttributeValue attribute = MWWorld::Class::get(ptr)
|
||||
.getCreatureStats(ptr)
|
||||
.getAttribute(mIndex);
|
||||
|
||||
value +=
|
||||
attribute.getModified();
|
||||
|
||||
attribute
|
||||
.setModified (value, 0, 100);
|
||||
attribute.setBase (std::min(100, attribute.getBase() + value));
|
||||
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
|
||||
}
|
||||
};
|
||||
|
@ -346,12 +342,10 @@ namespace MWScript
|
|||
const ESM::Class& class_ =
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find (ref->mBase->mClass);
|
||||
|
||||
float level = 0;
|
||||
float progress = std::modf (stats.getSkill (mIndex).getBase(), &level);
|
||||
float level = stats.getSkill(mIndex).getBase();
|
||||
float progress = stats.getSkill(mIndex).getProgress();
|
||||
|
||||
float modifier = stats.getSkill (mIndex).getModifier();
|
||||
|
||||
int newLevel = static_cast<int> (value-modifier);
|
||||
int newLevel = value - (stats.getSkill(mIndex).getModified() - stats.getSkill(mIndex).getBase());
|
||||
|
||||
if (newLevel<0)
|
||||
newLevel = 0;
|
||||
|
@ -362,8 +356,8 @@ namespace MWScript
|
|||
if (progress>=1)
|
||||
progress = 0.999999999;
|
||||
|
||||
stats.getSkill (mIndex).set (newLevel + progress);
|
||||
stats.getSkill (mIndex).setModifier (modifier);
|
||||
stats.getSkill (mIndex).setBase (newLevel);
|
||||
stats.getSkill (mIndex).setProgress(progress);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -383,11 +377,10 @@ namespace MWScript
|
|||
Interpreter::Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
value += MWWorld::Class::get (ptr).getNpcStats (ptr).getSkill (mIndex).
|
||||
getModified();
|
||||
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats(ptr);
|
||||
|
||||
MWWorld::Class::get (ptr).getNpcStats (ptr).getSkill (mIndex).
|
||||
setModified (value, 0, 100);
|
||||
stats.getSkill(mIndex).
|
||||
setBase (std::min(100, stats.getSkill(mIndex).getBase() + value));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -466,6 +459,38 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpRemoveSpellEffects : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string spellid = runtime.getStringLiteral (runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).getActiveSpells().removeEffects(spellid);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpRemoveEffects : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
Interpreter::Type_Integer effectId = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
MWWorld::Class::get (ptr).getCreatureStats (ptr).getActiveSpells().purgeEffect(effectId);
|
||||
}
|
||||
};
|
||||
|
||||
template<class R>
|
||||
class OpGetSpell : public Interpreter::Opcode0
|
||||
{
|
||||
|
@ -1079,6 +1104,18 @@ namespace MWScript
|
|||
}
|
||||
};
|
||||
|
||||
template <class R>
|
||||
class OpResurrect : public Interpreter::Opcode0
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void execute (Interpreter::Runtime& runtime)
|
||||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
ptr.getClass().getCreatureStats(ptr).resurrect();
|
||||
}
|
||||
};
|
||||
|
||||
void installOpcodes (Interpreter::Interpreter& interpreter)
|
||||
{
|
||||
for (int i=0; i<Compiler::Stats::numberOfAttributes; ++i)
|
||||
|
@ -1142,6 +1179,15 @@ namespace MWScript
|
|||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpell, new OpRemoveSpell<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellExplicit,
|
||||
new OpRemoveSpell<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellEffects, new OpRemoveSpellEffects<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellEffectsExplicit,
|
||||
new OpRemoveSpellEffects<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeResurrect, new OpResurrect<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeResurrectExplicit,
|
||||
new OpResurrect<ExplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveEffects, new OpRemoveEffects<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveEffectsExplicit,
|
||||
new OpRemoveEffects<ExplicitRef>);
|
||||
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpell, new OpGetSpell<ImplicitRef>);
|
||||
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
|
||||
|
|
|
@ -607,7 +607,7 @@ void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisito
|
|||
const EffectParams& params = mPermanentMagicEffectMagnitudes[(**iter).getCellRef().mRefID][i];
|
||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * params.mRandom;
|
||||
magnitude *= params.mMultiplier;
|
||||
visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), magnitude);
|
||||
visitor.visit(MWMechanics::EffectKey(*effectIt), (**iter).getClass().getName(**iter), "", magnitude);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
|
|
@ -1606,7 +1606,8 @@ namespace MWWorld
|
|||
return false;
|
||||
|
||||
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
||||
if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Levitate)).mMagnitude > 0)
|
||||
if(stats.getMagicEffects().get(ESM::MagicEffect::Levitate).mMagnitude > 0
|
||||
&& isLevitationEnabled())
|
||||
return true;
|
||||
|
||||
// TODO: Check if flying creature
|
||||
|
@ -1625,7 +1626,7 @@ namespace MWWorld
|
|||
return false;
|
||||
|
||||
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
||||
if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::SlowFall)).mMagnitude > 0)
|
||||
if(stats.getMagicEffects().get(ESM::MagicEffect::SlowFall).mMagnitude > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -1999,7 +2000,7 @@ namespace MWWorld
|
|||
const Store<ESM::GameSetting> &gmst = getStore().get<ESM::GameSetting>();
|
||||
MWMechanics::NpcStats &stats = Class::get(actor).getNpcStats(actor);
|
||||
|
||||
stats.getSkill(ESM::Skill::Acrobatics).setModified(gmst.find("fWerewolfAcrobatics")->getFloat(), 0);
|
||||
stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->getFloat());
|
||||
}
|
||||
|
||||
bool World::getGodModeState()
|
||||
|
@ -2389,11 +2390,11 @@ namespace MWWorld
|
|||
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
|
||||
float dist=0;
|
||||
if (type == World::Detect_Creature)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectAnimal)).mMagnitude;
|
||||
dist = effects.get(ESM::MagicEffect::DetectAnimal).mMagnitude;
|
||||
else if (type == World::Detect_Key)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectKey)).mMagnitude;
|
||||
dist = effects.get(ESM::MagicEffect::DetectKey).mMagnitude;
|
||||
else if (type == World::Detect_Enchantment)
|
||||
dist = effects.get(MWMechanics::EffectKey(ESM::MagicEffect::DetectEnchantment)).mMagnitude;
|
||||
dist = effects.get(ESM::MagicEffect::DetectEnchantment).mMagnitude;
|
||||
|
||||
if (!dist)
|
||||
return;
|
||||
|
|
|
@ -222,6 +222,8 @@ namespace Compiler
|
|||
extensions.registerInstruction ("activate", "", opcodeActivate);
|
||||
extensions.registerInstruction ("lock", "/l", opcodeLock, opcodeLockExplicit);
|
||||
extensions.registerInstruction ("unlock", "", opcodeUnlock, opcodeUnlockExplicit);
|
||||
extensions.registerInstruction ("cast", "SS", opcodeCast, opcodeCastExplicit);
|
||||
extensions.registerInstruction ("explodespell", "S", opcodeExplodeSpell, opcodeExplodeSpellExplicit);
|
||||
extensions.registerInstruction ("togglecollisionboxes", "", opcodeToggleCollisionBoxes);
|
||||
extensions.registerInstruction ("togglecollisiongrid", "", opcodeToggleCollisionDebug);
|
||||
extensions.registerInstruction ("tcb", "", opcodeToggleCollisionBoxes);
|
||||
|
@ -389,6 +391,12 @@ namespace Compiler
|
|||
extensions.registerInstruction ("addspell", "c", opcodeAddSpell, opcodeAddSpellExplicit);
|
||||
extensions.registerInstruction ("removespell", "c", opcodeRemoveSpell,
|
||||
opcodeRemoveSpellExplicit);
|
||||
extensions.registerInstruction ("removespelleffects", "c", opcodeRemoveSpellEffects,
|
||||
opcodeRemoveSpellEffectsExplicit);
|
||||
extensions.registerInstruction ("removeeffects", "l", opcodeRemoveEffects,
|
||||
opcodeRemoveEffectsExplicit);
|
||||
extensions.registerInstruction ("resurrect", "", opcodeResurrect,
|
||||
opcodeResurrectExplicit);
|
||||
extensions.registerFunction ("getspell", 'l', "c", opcodeGetSpell, opcodeGetSpellExplicit);
|
||||
|
||||
extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank);
|
||||
|
|
|
@ -228,6 +228,10 @@ namespace Compiler
|
|||
const int opcodeToggleGodMode = 0x200021f;
|
||||
const int opcodeDisableLevitation = 0x2000220;
|
||||
const int opcodeEnableLevitation = 0x2000221;
|
||||
const int opcodeCast = 0x2000227;
|
||||
const int opcodeCastExplicit = 0x2000228;
|
||||
const int opcodeExplodeSpell = 0x2000229;
|
||||
const int opcodeExplodeSpellExplicit = 0x200022a;
|
||||
}
|
||||
|
||||
namespace Sky
|
||||
|
@ -365,6 +369,13 @@ namespace Compiler
|
|||
const int opcodeIsWerewolfExplicit = 0x20001fe;
|
||||
|
||||
const int opcodeGetWerewolfKills = 0x20001e2;
|
||||
|
||||
const int opcodeRemoveSpellEffects = 0x200022b;
|
||||
const int opcodeRemoveSpellEffectsExplicit = 0x200022c;
|
||||
const int opcodeRemoveEffects = 0x200022d;
|
||||
const int opcodeRemoveEffectsExplicit = 0x200022e;
|
||||
const int opcodeResurrect = 0x200022f;
|
||||
const int opcodeResurrectExplicit = 0x2000230;
|
||||
}
|
||||
|
||||
namespace Transformation
|
||||
|
|
|
@ -854,7 +854,7 @@ class NIFObjectLoader
|
|||
{
|
||||
const Nif::NiParticleSystemController *partctrl = static_cast<const Nif::NiParticleSystemController*>(ctrl.getPtr());
|
||||
|
||||
partsys->setDefaultDimensions(partctrl->size, partctrl->size);
|
||||
partsys->setDefaultDimensions(partctrl->size*2, partctrl->size*2);
|
||||
|
||||
if(!partctrl->emitter.empty())
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue