Merge remote-tracking branch 'scrawl/master'

actorid
Marc Zinnschlag 11 years ago
commit ee621245bb

@ -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 modifier = stats.getSkill (mIndex).getModifier();
float level = stats.getSkill(mIndex).getBase();
float progress = stats.getSkill(mIndex).getProgress();
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…
Cancel
Save