Add OpenMW commits up to 1 Sep 2018

# Conflicts:
#	apps/openmw/mwbase/world.hpp
#	apps/openmw/mwclass/creature.cpp
#	apps/openmw/mwclass/npc.cpp
#	apps/openmw/mwgui/jailscreen.cpp
#	apps/openmw/mwmechanics/actors.cpp
#	apps/openmw/mwmechanics/difficultyscaling.cpp
#	apps/openmw/mwscript/transformationextensions.cpp
#	apps/openmw/mwworld/worldimp.hpp
pull/541/head
David Cernat 5 years ago
commit 889bcec7f8

@ -153,6 +153,7 @@ Programmers
Siimacore
sir_herrbatka
smbas
Sophie Kirschner (pineapplemachine)
spycrab
Stefan Galowicz (bogglez)
Stanislav Bobrov (Jiub)

@ -4,6 +4,8 @@
Bug #1990: Sunrise/sunset not set correct
Bug #2131: Lustidrike's spell misses the player every time
Bug #2222: Fatigue's effect on selling price is backwards
Bug #2256: Landing sound not playing when jumping immediately after landing
Bug #2274: Thin platform clips through player character instead of lifting
Bug #2326: After a bound item expires the last equipped item of that type is not automatically re-equipped
Bug #2455: Creatures attacks degrade armor
Bug #2562: Forcing AI to activate a teleport door sometimes causes a crash
@ -15,6 +17,7 @@
Bug #2872: Tab completion in console doesn't work with explicit reference
Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y
Bug #3049: Drain and Fortify effects are not properly applied on health, magicka and fatigue
Bug #3059: Unable to hit with marksman weapons when too close to an enemy
Bug #3072: Fatal error on AddItem <item> that has a script containing Equip <item>
Bug #3249: Fixed revert function not updating views properly
Bug #3374: Touch spells not hitting kwama foragers
@ -22,10 +25,13 @@
Bug #3533: GetSpellEffects should detect effects with zero duration
Bug #3591: Angled hit distance too low
Bug #3629: DB assassin attack never triggers creature spawning
Bug #3681: OpenMW-CS: Clicking Scripts in Preferences spawns many color pickers
Bug #3788: GetPCInJail and GetPCTraveling do not work as in vanilla
Bug #3836: Script fails to compile when command argument contains "\n"
Bug #3876: Landscape texture painting is misaligned
Bug #3897: Have Goodbye give all choices the effects of Goodbye
Bug #3911: [macOS] Typing in the "Content List name" dialog box produces double characters
Bug #3920: RemoveSpellEffects doesn't remove constant effects
Bug #3948: AiCombat moving target aiming uses incorrect speed for magic projectiles
Bug #3950: FLATTEN_STATIC_TRANSFORMS optimization breaks animated collision shapes
Bug #3993: Terrain texture blending map is not upscaled
@ -91,6 +97,7 @@
Bug #4553: Forcegreeting on non-actor opens a dialogue window which cannot be closed
Bug #4557: Topics with reserved names are handled differently from vanilla
Bug #4558: Mesh optimizer: check for reserved node name is case-sensitive
Bug #4560: OpenMW does not update pinned windows properly
Bug #4563: Fast travel price logic checks destination cell instead of service actor cell
Bug #4565: Underwater view distance should be limited
Bug #4573: Player uses headtracking in the 1st-person mode
@ -98,6 +105,14 @@
Bug #4575: Weird result of attack animation blending with movement animations
Bug #4576: Reset of idle animations when attack can not be started
Bug #4591: Attack strength should be 0 if player did not hold the attack button
Bug #4597: <> operator causes a compile error
Bug #4604: Picking up gold from the ground only makes 1 grabbed
Bug #4607: Scaling for animated collision shapes is applied twice
Bug #4608: Falling damage is applied twice
Bug #4615: Flicker effects for light sources are handled incorrectly
Bug #4617: First person sneaking offset is not applied while the character is in air
Bug #4618: Sneaking is possible while the character is flying
Bug #4622: Recharging enchanted items with Soul Gems does not award experience if it fails
Feature #1645: Casting effects from objects
Feature #2606: Editor: Implemented (optional) case sensitive global search
Feature #3083: Play animation when NPC is casting spell via script
@ -123,6 +138,10 @@
Feature #4581: Use proper logging system
Task #2490: Don't open command prompt window on Release-mode builds automatically
Task #4545: Enable is_pod string test
Task #4605: Optimize skinning
Task #4606: Support Rapture3D's OpenAL driver
Task #4613: Incomplete type errors when compiling with g++ on OSX 10.9
Task #4621: Optimize combat AI
0.44.0
------

@ -1,11 +1,9 @@
#include "coloreditor.hpp"
#include <QApplication>
#include <QColor>
#include <QColorDialog>
#include <QDesktopWidget>
#include <QPainter>
#include <QRect>
#include <QShowEvent>
#include "colorpickerpopup.hpp"
@ -27,9 +25,7 @@ CSVWidget::ColorEditor::ColorEditor(QWidget *parent, const bool popupOnStart)
mColorPicker(new ColorPickerPopup(this)),
mPopupOnStart(popupOnStart)
{
setCheckable(true);
connect(this, SIGNAL(clicked()), this, SLOT(showPicker()));
connect(mColorPicker, SIGNAL(hid()), this, SLOT(pickerHid()));
connect(mColorPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(pickerColorChanged(const QColor &)));
}
@ -85,20 +81,7 @@ void CSVWidget::ColorEditor::setColor(const int colorInt)
void CSVWidget::ColorEditor::showPicker()
{
if (isChecked())
{
mColorPicker->showPicker(calculatePopupPosition(), mColor);
}
else
{
mColorPicker->hide();
}
}
void CSVWidget::ColorEditor::pickerHid()
{
setChecked(false);
emit pickingFinished();
mColorPicker->showPicker(calculatePopupPosition(), mColor);
}
void CSVWidget::ColorEditor::pickerColorChanged(const QColor &color)

@ -45,7 +45,6 @@ namespace CSVWidget
private slots:
void showPicker();
void pickerHid();
void pickerColorChanged(const QColor &color);
signals:

@ -4,7 +4,6 @@
#include <QPushButton>
#include <QEvent>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QLayout>
#include <QStyleOption>
@ -19,7 +18,6 @@ CSVWidget::ColorPickerPopup::ColorPickerPopup(QWidget *parent)
mColorPicker->setWindowFlags(Qt::Widget);
mColorPicker->setOptions(QColorDialog::NoButtons | QColorDialog::DontUseNativeDialog);
mColorPicker->installEventFilter(this);
mColorPicker->open();
connect(mColorPicker,
SIGNAL(currentColorChanged(const QColor &)),
this,
@ -39,8 +37,9 @@ void CSVWidget::ColorPickerPopup::showPicker(const QPoint &position, const QColo
geometry.moveTo(position);
setGeometry(geometry);
mColorPicker->setCurrentColor(initialColor);
show();
// Calling getColor() creates a blocking dialog that will continue execution once the user chooses OK or Cancel
QColor color = mColorPicker->getColor(initialColor);
mColorPicker->setCurrentColor(color);
}
void CSVWidget::ColorPickerPopup::mousePressEvent(QMouseEvent *event)
@ -63,12 +62,6 @@ void CSVWidget::ColorPickerPopup::mousePressEvent(QMouseEvent *event)
QFrame::mousePressEvent(event);
}
void CSVWidget::ColorPickerPopup::hideEvent(QHideEvent *event)
{
QFrame::hideEvent(event);
emit hid();
}
bool CSVWidget::ColorPickerPopup::eventFilter(QObject *object, QEvent *event)
{
if (object == mColorPicker && event->type() == QEvent::KeyPress)

@ -20,11 +20,9 @@ namespace CSVWidget
protected:
virtual void mousePressEvent(QMouseEvent *event);
virtual void hideEvent(QHideEvent *event);
virtual bool eventFilter(QObject *object, QEvent *event);
signals:
void hid();
void colorChanged(const QColor &color);
};
}

@ -584,6 +584,7 @@ namespace MWBase
End of tes3mp addition
*/
virtual void getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors) = 0; ///< get a list of actors standing on \a object
virtual bool getPlayerStandingOn (const MWWorld::ConstPtr& object) = 0; ///< @return true if the player is standing on \a object
virtual bool getActorStandingOn (const MWWorld::ConstPtr& object) = 0; ///< @return true if any actor is standing on \a object
virtual bool getPlayerCollidingWith(const MWWorld::ConstPtr& object) = 0; ///< @return true if the player is colliding with \a object
@ -662,8 +663,8 @@ namespace MWBase
virtual void castSpell (const MWWorld::Ptr& actor, bool manualSpell=false) = 0;
virtual void launchMagicBolt (const std::string& spellId, const MWWorld::Ptr& caster, const osg::Vec3f& fallbackDirection) = 0;
virtual void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) = 0;
virtual void launchProjectile (MWWorld::Ptr& actor, MWWorld::Ptr& projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr& bow, float speed, float attackStrength) = 0;
virtual void applyLoopingParticles(const MWWorld::Ptr& ptr) = 0;

@ -176,14 +176,14 @@ namespace MWClass
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
float iWeight = floor(gmst.find(typeGmst)->getFloat());
float iWeight = floor(gmst.find(typeGmst)->mValue.getFloat());
float epsilon = 0.0005f;
if (ref->mBase->mData.mWeight <= iWeight * gmst.find ("fLightMaxMod")->getFloat() + epsilon)
if (ref->mBase->mData.mWeight <= iWeight * gmst.find ("fLightMaxMod")->mValue.getFloat() + epsilon)
return ESM::Skill::LightArmor;
if (ref->mBase->mData.mWeight <= iWeight * gmst.find ("fMedMaxMod")->getFloat() + epsilon)
if (ref->mBase->mData.mWeight <= iWeight * gmst.find ("fMedMaxMod")->mValue.getFloat() + epsilon)
return ESM::Skill::MediumArmor;
else
@ -331,7 +331,7 @@ namespace MWClass
int armorSkill = actor.getClass().getSkill(actor, armorSkillType);
const MWBase::World *world = MWBase::Environment::get().getWorld();
int iBaseArmorSkill = world->getStore().get<ESM::GameSetting>().find("iBaseArmorSkill")->getInt();
int iBaseArmorSkill = world->getStore().get<ESM::GameSetting>().find("iBaseArmorSkill")->mValue.getInteger();
if(ref->mBase->mData.mWeight == 0)
return ref->mBase->mData.mArmor;

@ -275,13 +275,13 @@ namespace MWClass
MWMechanics::applyFatigueLoss(ptr, weapon, attackStrength);
float dist = gmst.find("fCombatDistance")->getFloat();
float dist = gmst.find("fCombatDistance")->mValue.getFloat();
if (!weapon.isEmpty())
dist *= weapon.get<ESM::Weapon>()->mBase->mData.mReach;
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit result.
std::vector<MWWorld::Ptr> targetActors;
if (!ptr.isEmpty() && ptr.getClass().isActor() && ptr != MWMechanics::getPlayer())
if (!ptr.isEmpty() && ptr.getClass().isActor())
ptr.getClass().getCreatureStats(ptr).getAiSequence().getCombatTargets(targetActors);
std::pair<MWWorld::Ptr, osg::Vec3f> result = MWBase::Environment::get().getWorld()->getHitContact(ptr, dist, targetActors);
@ -401,9 +401,6 @@ namespace MWClass
if (MWMechanics::blockMeleeAttack(ptr, victim, weapon, damage, attackStrength))
damage = 0;
if (victim == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState())
damage = 0;
MWMechanics::diseaseContact(victim, ptr);
victim.getClass().onHit(victim, damage, healthdmg, weapon, ptr, hitPosition, true);
@ -466,11 +463,6 @@ namespace MWClass
ptr.getRefData().getLocals().setVarByInt(script, "onpchitme", 1);
}
bool godmode = object == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
if (godmode)
damage = 0;
if (!successful)
{
// Missed
@ -492,9 +484,9 @@ namespace MWClass
if (!attacker.isEmpty())
{
// Check for knockdown
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->getFloat();
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * getGmst().fKnockDownMult->mValue.getFloat();
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
* getGmst().iKnockDownOddsMult->getInt() * 0.01f + getGmst().iKnockDownOddsBase->getInt();
* getGmst().iKnockDownOddsMult->mValue.getInteger() * 0.01f + getGmst().iKnockDownOddsBase->mValue.getInteger();
/*
Start of tes3mp change (major)
@ -513,6 +505,9 @@ namespace MWClass
if (dedicatedAttack->knockdown)
stats.setKnockedDown(true);
}
if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99())
stats.setKnockedDown(true);
else
{
if (ishealth && agilityTerm <= damage && knockdownTerm <= Misc::Rng::roll0to99())
@ -530,7 +525,7 @@ namespace MWClass
if(ishealth)
{
if (!attacker.isEmpty() && !godmode)
if (!attacker.isEmpty())
{
damage = scaleDamage(damage, attacker, ptr);
MWBase::Environment::get().getWorld()->spawnBloodEffect(ptr, hitPosition);
@ -671,8 +666,8 @@ namespace MWClass
const GMST& gmst = getGmst();
float walkSpeed = gmst.fMinWalkSpeedCreature->getFloat() + 0.01f * stats.getAttribute(ESM::Attribute::Speed).getModified()
* (gmst.fMaxWalkSpeedCreature->getFloat() - gmst.fMinWalkSpeedCreature->getFloat());
float walkSpeed = gmst.fMinWalkSpeedCreature->mValue.getFloat() + 0.01f * stats.getAttribute(ESM::Attribute::Speed).getModified()
* (gmst.fMaxWalkSpeedCreature->mValue.getFloat() - gmst.fMinWalkSpeedCreature->mValue.getFloat());
const MWBase::World *world = MWBase::Environment::get().getWorld();
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
@ -691,9 +686,9 @@ namespace MWClass
{
float flySpeed = 0.01f*(stats.getAttribute(ESM::Attribute::Speed).getModified() +
mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
flySpeed = gmst.fMinFlySpeed->mValue.getFloat() + flySpeed*(gmst.fMaxFlySpeed->mValue.getFloat() - gmst.fMinFlySpeed->mValue.getFloat());
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat() * normalizedEncumbrance;
flySpeed = std::max(0.0f, flySpeed);
moveSpeed = flySpeed;
}
@ -703,8 +698,8 @@ namespace MWClass
if(running)
swimSpeed = runSpeed;
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
gmst.fSwimRunAthleticsMult->getFloat();
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat() + 0.01f*getSkill(ptr, ESM::Skill::Athletics) *
gmst.fSwimRunAthleticsMult->mValue.getFloat();
moveSpeed = swimSpeed;
}
else if(running)
@ -969,8 +964,8 @@ namespace MWClass
return;
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->mValue.getFloat();
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->mValue.getFloat();
float delay = ptr.getRefData().getCount() == 0 ? fCorpseClearDelay : std::min(fCorpseRespawnDelay, fCorpseClearDelay);

@ -56,8 +56,8 @@ namespace MWClass
else if (creatureStats.isDead())
{
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->mValue.getFloat();
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->mValue.getFloat();
float delay = std::min(fCorpseRespawnDelay, fCorpseClearDelay);
if (creatureStats.getTimeOfDeath() + delay <= MWBase::Environment::get().getWorld()->getTimeStamp())

@ -171,7 +171,7 @@ namespace MWClass
int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase();
static const float fWortChanceValue =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->getFloat();
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->mValue.getFloat();
MWGui::Widgets::SpellEffectList list;
for (int i=0; i<4; ++i)

@ -387,9 +387,9 @@ namespace MWClass
if (!ref->mBase->mFaction.empty())
{
static const int iAutoRepFacMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iAutoRepFacMod")->getInt();
.find("iAutoRepFacMod")->mValue.getInteger();
static const int iAutoRepLevMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iAutoRepLevMod")->getInt();
.find("iAutoRepLevMod")->mValue.getInteger();
int rank = ref->mBase->getFactionRank();
data->mNpcStats.setReputation(iAutoRepFacMod * (rank+1) + iAutoRepLevMod * (data->mNpcStats.getLevel()-1));
@ -543,7 +543,7 @@ namespace MWClass
const MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
return store.find("sWerewolfPopup")->getString();
return store.find("sWerewolfPopup")->mValue.getString();
}
const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
@ -593,10 +593,10 @@ namespace MWClass
MWMechanics::applyFatigueLoss(ptr, weapon, attackStrength);
const float fCombatDistance = store.find("fCombatDistance")->getFloat();
const float fCombatDistance = store.find("fCombatDistance")->mValue.getFloat();
float dist = fCombatDistance * (!weapon.isEmpty() ?
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
store.find("fHandToHandReach")->getFloat());
store.find("fHandToHandReach")->mValue.getFloat());
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit result.
std::vector<MWWorld::Ptr> targetActors;
@ -701,14 +701,14 @@ namespace MWClass
&& !MWBase::Environment::get().getMechanicsManager()->awarenessCheck(ptr, victim);
if(unaware)
{
damage *= store.find("fCombatCriticalStrikeMult")->getFloat();
damage *= store.find("fCombatCriticalStrikeMult")->mValue.getFloat();
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
}
}
if (othercls.getCreatureStats(victim).getKnockedDown())
damage *= store.find("fCombatKODamageMult")->getFloat();
damage *= store.find("fCombatKODamageMult")->mValue.getFloat();
// Apply "On hit" enchanted weapons
@ -827,14 +827,14 @@ namespace MWClass
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
const GMST& gmst = getGmst();
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->getInt();
int chance = store.get<ESM::GameSetting>().find("iVoiceHitOdds")->mValue.getInteger();
if (Misc::Rng::roll0to99() < chance)
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
// Check for knockdown
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->getFloat();
float agilityTerm = stats.getAttribute(ESM::Attribute::Agility).getModified() * gmst.fKnockDownMult->mValue.getFloat();
float knockdownTerm = stats.getAttribute(ESM::Attribute::Agility).getModified()
* gmst.iKnockDownOddsMult->getInt() * 0.01f + gmst.iKnockDownOddsBase->getInt();
* gmst.iKnockDownOddsMult->mValue.getInteger() * 0.01f + gmst.iKnockDownOddsBase->mValue.getInteger();
/*
Start of tes3mp change (major)
@ -887,7 +887,7 @@ namespace MWClass
float unmitigatedDamage = damage;
float x = damage / (damage + getArmorRating(ptr));
damage *= std::max(gmst.fCombatArmorMinMult->getFloat(), x);
damage *= std::max(gmst.fCombatArmorMinMult->mValue.getFloat(), x);
int damageDiff = static_cast<int>(unmitigatedDamage - damage);
damage = std::max(1.f, damage);
damageDiff = std::max(1, damageDiff);
@ -1126,15 +1126,15 @@ namespace MWClass
bool sneaking = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak);
bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run);
float walkSpeed = gmst.fMinWalkSpeed->getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
(gmst.fMaxWalkSpeed->getFloat() - gmst.fMinWalkSpeed->getFloat());
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat()*normalizedEncumbrance;
float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
(gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat());
walkSpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat()*normalizedEncumbrance;
walkSpeed = std::max(0.0f, walkSpeed);
if(sneaking)
walkSpeed *= gmst.fSneakSpeedMultiplier->getFloat();
walkSpeed *= gmst.fSneakSpeedMultiplier->mValue.getFloat();
float runSpeed = walkSpeed*(0.01f * npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified() *
gmst.fAthleticsRunBonus->getFloat() + gmst.fBaseRunMultiplier->getFloat());
gmst.fAthleticsRunBonus->mValue.getFloat() + gmst.fBaseRunMultiplier->mValue.getFloat());
float moveSpeed;
if(getEncumbrance(ptr) > getCapacity(ptr))
@ -1144,8 +1144,8 @@ namespace MWClass
{
float flySpeed = 0.01f*(npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified() +
mageffects.get(ESM::MagicEffect::Levitate).getMagnitude());
flySpeed = gmst.fMinFlySpeed->getFloat() + flySpeed*(gmst.fMaxFlySpeed->getFloat() - gmst.fMinFlySpeed->getFloat());
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->getFloat() * normalizedEncumbrance;
flySpeed = gmst.fMinFlySpeed->mValue.getFloat() + flySpeed*(gmst.fMaxFlySpeed->mValue.getFloat() - gmst.fMinFlySpeed->mValue.getFloat());
flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat() * normalizedEncumbrance;
flySpeed = std::max(0.0f, flySpeed);
moveSpeed = flySpeed;
}
@ -1155,8 +1155,8 @@ namespace MWClass
if(running)
swimSpeed = runSpeed;
swimSpeed *= 1.0f + 0.01f * mageffects.get(ESM::MagicEffect::SwiftSwim).getMagnitude();
swimSpeed *= gmst.fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
gmst.fSwimRunAthleticsMult->getFloat();
swimSpeed *= gmst.fSwimRunBase->mValue.getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()*
gmst.fSwimRunAthleticsMult->mValue.getFloat();
moveSpeed = swimSpeed;
}
else if(running && !sneaking)
@ -1167,7 +1167,7 @@ namespace MWClass
moveSpeed *= 0.75f;
if(npcdata->mNpcStats.isWerewolf() && running && npcdata->mNpcStats.getDrawState() == MWMechanics::DrawState_Nothing)
moveSpeed *= gmst.fWereWolfRunMult->getFloat();
moveSpeed *= gmst.fWereWolfRunMult->mValue.getFloat();
return moveSpeed;
}
@ -1177,11 +1177,15 @@ namespace MWClass
if(getEncumbrance(ptr) > getCapacity(ptr))
return 0.f;
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
if (stats.isParalyzed() || stats.getKnockedDown() || stats.isDead())
return 0.f;
const NpcCustomData *npcdata = static_cast<const NpcCustomData*>(ptr.getRefData().getCustomData());
const GMST& gmst = getGmst();
const MWMechanics::MagicEffects &mageffects = npcdata->mNpcStats.getMagicEffects();
const float encumbranceTerm = gmst.fJumpEncumbranceBase->getFloat() +
gmst.fJumpEncumbranceMultiplier->getFloat() *
const float encumbranceTerm = gmst.fJumpEncumbranceBase->mValue.getFloat() +
gmst.fJumpEncumbranceMultiplier->mValue.getFloat() *
(1.0f - Npc::getNormalizedEncumbrance(ptr));
float a = static_cast<float>(npcdata->mNpcStats.getSkill(ESM::Skill::Acrobatics).getModified());
@ -1192,14 +1196,14 @@ namespace MWClass
a = 50.0f;
}
float x = gmst.fJumpAcrobaticsBase->getFloat() +
std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->getFloat());
x += 3.0f * b * gmst.fJumpAcroMultiplier->getFloat();
float x = gmst.fJumpAcrobaticsBase->mValue.getFloat() +
std::pow(a / 15.0f, gmst.fJumpAcroMultiplier->mValue.getFloat());
x += 3.0f * b * gmst.fJumpAcroMultiplier->mValue.getFloat();
x += mageffects.get(ESM::MagicEffect::Jump).getMagnitude() * 64;
x *= encumbranceTerm;
if(ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run))
x *= gmst.fJumpRunMultiplier->getFloat();
if(stats.getStance(MWMechanics::CreatureStats::Stance_Run))
x *= gmst.fJumpRunMultiplier->mValue.getFloat();
x *= npcdata->mNpcStats.getFatigueTerm();
x -= -627.2f;/*gravity constant*/
x /= 3.0f;
@ -1264,7 +1268,7 @@ namespace MWClass
float Npc::getCapacity (const MWWorld::Ptr& ptr) const
{
const MWMechanics::CreatureStats& stats = getCreatureStats (ptr);
static const float fEncumbranceStrMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fEncumbranceStrMult")->getFloat();
static const float fEncumbranceStrMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fEncumbranceStrMult")->mValue.getFloat();
return stats.getAttribute(ESM::Attribute::Strength).getModified()*fEncumbranceStrMult;
}
@ -1307,8 +1311,8 @@ namespace MWClass
MWMechanics::NpcStats &stats = getNpcStats(ptr);
const MWWorld::InventoryStore &invStore = getInventoryStore(ptr);
float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat();
float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat();
float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat();
float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat();
int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified();
float ratings[MWWorld::InventoryStore::Slots];
@ -1426,11 +1430,10 @@ namespace MWClass
{
MWBase::World *world = MWBase::Environment::get().getWorld();
osg::Vec3f pos(ptr.getRefData().getPosition().asVec3());
if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
if (world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr))
return "DefaultLandWater";
if(world->isOnGround(ptr))
return "DefaultLand";
return "";
return "DefaultLand";
}
if(name == "swimleft")
return "Swim Left";
@ -1549,8 +1552,8 @@ namespace MWClass
return;
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->getFloat();
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->getFloat();
static const float fCorpseRespawnDelay = gmst.find("fCorpseRespawnDelay")->mValue.getFloat();
static const float fCorpseClearDelay = gmst.find("fCorpseClearDelay")->mValue.getFloat();
float delay = ptr.getRefData().getCount() == 0 ? fCorpseClearDelay : std::min(fCorpseRespawnDelay, fCorpseClearDelay);

@ -321,8 +321,8 @@ namespace MWClass
std::string type = mapping[ref->mBase->mData.mType].first;
std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second;
text += store.get<ESM::GameSetting>().find(type)->getString() +
((oneOrTwoHanded != "") ? ", " + store.get<ESM::GameSetting>().find(oneOrTwoHanded)->getString() : "");
text += store.get<ESM::GameSetting>().find(type)->mValue.getString() +
((oneOrTwoHanded != "") ? ", " + store.get<ESM::GameSetting>().find(oneOrTwoHanded)->mValue.getString() : "");
// weapon damage
if (ref->mBase->mData.mType >= 9)
@ -360,7 +360,7 @@ namespace MWClass
if (ref->mBase->mData.mType < 9 && Settings::Manager::getBool("show melee info", "Game"))
{
// 64 game units = 1 yard = 3 ft, display value in feet
const float combatDistance = store.get<ESM::GameSetting>().find("fCombatDistance")->getFloat() * ref->mBase->mData.mReach;
const float combatDistance = store.get<ESM::GameSetting>().find("fCombatDistance")->mValue.getFloat() * ref->mBase->mData.mReach;
text += MWGui::ToolTips::getWeightString(combatDistance*3/64, "#{sRange}");
text += " #{sFeet}";

@ -311,7 +311,7 @@ namespace MWDialogue
const MWWorld::Store<ESM::GameSetting>& gmsts =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
title = gmsts.find (modifiedTopic)->getString();
title = gmsts.find (modifiedTopic)->mValue.getString();
}
else
title = topic;
@ -587,7 +587,7 @@ namespace MWDialogue
MWScript::InterpreterContext interpreterContext(&mActor.getRefData().getLocals(),mActor);
callback->addResponse(gmsts.find ("sServiceRefusal")->getString(), Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
callback->addResponse(gmsts.find ("sServiceRefusal")->mValue.getString(), Interpreter::fixDefinesDialog(info->mResponse, interpreterContext));
executeScript (info->mResultScript, mActor);
return true;

@ -365,15 +365,15 @@ namespace MWGui
const MWWorld::Store<ESM::GameSetting> &gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
const std::string sPersuasion = gmst.find("sPersuasion")->getString();
const std::string sCompanionShare = gmst.find("sCompanionShare")->getString();
const std::string sBarter = gmst.find("sBarter")->getString();
const std::string sSpells = gmst.find("sSpells")->getString();
const std::string sTravel = gmst.find("sTravel")->getString();
const std::string sSpellMakingMenuTitle = gmst.find("sSpellMakingMenuTitle")->getString();
const std::string sEnchanting = gmst.find("sEnchanting")->getString();
const std::string sServiceTrainingTitle = gmst.find("sServiceTrainingTitle")->getString();
const std::string sRepair = gmst.find("sRepair")->getString();
const std::string sPersuasion = gmst.find("sPersuasion")->mValue.getString();
const std::string sCompanionShare = gmst.find("sCompanionShare")->mValue.getString();
const std::string sBarter = gmst.find("sBarter")->mValue.getString();
const std::string sSpells = gmst.find("sSpells")->mValue.getString();
const std::string sTravel = gmst.find("sTravel")->mValue.getString();
const std::string sSpellMakingMenuTitle = gmst.find("sSpellMakingMenuTitle")->mValue.getString();
const std::string sEnchanting = gmst.find("sEnchanting")->mValue.getString();
const std::string sServiceTrainingTitle = gmst.find("sServiceTrainingTitle")->mValue.getString();
const std::string sRepair = gmst.find("sRepair")->mValue.getString();
if (topic != sPersuasion && topic != sCompanionShare && topic != sBarter
&& topic != sSpells && topic != sTravel && topic != sSpellMakingMenuTitle
@ -458,7 +458,7 @@ namespace MWGui
void DialogueWindow::restock()
{
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
float delay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getFloat();
float delay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->mValue.getFloat();
// Gold is restocked every 24h
if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getLastRestockTime() + delay)
@ -503,31 +503,31 @@ namespace MWGui
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
if (mPtr.getTypeName() == typeid(ESM::NPC).name())
mTopicsList->addItem(gmst.find("sPersuasion")->getString());
mTopicsList->addItem(gmst.find("sPersuasion")->mValue.getString());
if (services & ESM::NPC::AllItems)
mTopicsList->addItem(gmst.find("sBarter")->getString());
mTopicsList->addItem(gmst.find("sBarter")->mValue.getString());
if (services & ESM::NPC::Spells)
mTopicsList->addItem(gmst.find("sSpells")->getString());
mTopicsList->addItem(gmst.find("sSpells")->mValue.getString());
if (travel)
mTopicsList->addItem(gmst.find("sTravel")->getString());
mTopicsList->addItem(gmst.find("sTravel")->mValue.getString());
if (services & ESM::NPC::Spellmaking)
mTopicsList->addItem(gmst.find("sSpellmakingMenuTitle")->getString());
mTopicsList->addItem(gmst.find("sSpellmakingMenuTitle")->mValue.getString());
if (services & ESM::NPC::Enchanting)
mTopicsList->addItem(gmst.find("sEnchanting")->getString());
mTopicsList->addItem(gmst.find("sEnchanting")->mValue.getString());
if (services & ESM::NPC::Training)
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->getString());
mTopicsList->addItem(gmst.find("sServiceTrainingTitle")->mValue.getString());
if (services & ESM::NPC::Repair)
mTopicsList->addItem(gmst.find("sRepair")->getString());
mTopicsList->addItem(gmst.find("sRepair")->mValue.getString());
if (isCompanion())
mTopicsList->addItem(gmst.find("sCompanionShare")->getString());
mTopicsList->addItem(gmst.find("sCompanionShare")->mValue.getString());
if (mTopicsList->getItemCount() > 0)
mTopicsList->addSeparator();
@ -592,7 +592,7 @@ namespace MWGui
Goodbye* link = new Goodbye();
link->eventActivated += MyGUI::newDelegate(this, &DialogueWindow::onGoodbyeActivated);
mLinks.push_back(link);
std::string goodbye = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGoodbye")->getString();
std::string goodbye = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sGoodbye")->mValue.getString();
BookTypesetter::Style* questionStyle = typesetter->createHotStyle(body, textColours.answer, textColours.answerOver,
textColours.answerPressed,
TypesetBook::InteractiveId(link));

@ -341,7 +341,7 @@ namespace MWGui
MWWorld::Ptr item = (i == 0) ? mEnchanting.getOldItem() : mEnchanting.getGem();
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(item.getCellRef().getRefId(), mPtr))
{
std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->getString();
std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->mValue.getString();
if (msg.find("%s") != std::string::npos)
msg.replace(msg.find("%s"), 2, item.getClass().getName(item));
MWBase::Environment::get().getWindowManager()->messageBox(msg);

@ -670,7 +670,7 @@ namespace MWGui
// Therefore any value < 1 should show as an empty health bar. We do the same in statswindow :)
mEnemyHealth->setProgressPosition(static_cast<size_t>(stats.getHealth().getCurrent() / stats.getHealth().getModified() * 100));
static const float fNPCHealthBarFade = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarFade")->getFloat();
static const float fNPCHealthBarFade = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarFade")->mValue.getFloat();
if (fNPCHealthBarFade > 0.f)
mEnemyHealth->setAlpha(std::max(0.f, std::min(1.f, mEnemyHealthTimer/fNPCHealthBarFade)));
@ -679,7 +679,7 @@ namespace MWGui
void HUD::setEnemy(const MWWorld::Ptr &enemy)
{
mEnemyActorId = enemy.getClass().getCreatureStats(enemy).getActorId();
mEnemyHealthTimer = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarTime")->getFloat();
mEnemyHealthTimer = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCHealthBarTime")->mValue.getFloat();
if (!mEnemyHealth->getVisible())
mWeaponSpellBox->setPosition(mWeaponSpellBox->getPosition() - MyGUI::IntPoint(0,20));
mEnemyHealth->setVisible(true);

@ -82,6 +82,7 @@ namespace MWGui
, mPreview(new MWRender::InventoryPreview(parent, resourceSystem, MWMechanics::getPlayer()))
, mTrading(false)
, mScaleFactor(1.0f)
, mUpdateTimer(0.f)
{
float uiScale = Settings::Manager::getFloat("scaling factor", "GUI");
if (uiScale > 1.0)
@ -655,6 +656,22 @@ namespace MWGui
void InventoryWindow::onFrame(float dt)
{
updateEncumbranceBar();
if (mPinned)
{
mUpdateTimer += dt;
if (0.1f < mUpdateTimer)
{
mUpdateTimer = 0;
// Update pinned inventory in-game
if (!MWBase::Environment::get().getWindowManager()->isGuiMode())
{
mItemView->update();
notifyContentChanged();
}
}
}
}
void InventoryWindow::setTrading(bool trading)
@ -705,6 +722,8 @@ namespace MWGui
return;
int count = object.getRefData().getCount();
if (object.getClass().isGold(object))
count *= object.getClass().getValue(object);
MWWorld::Ptr player = MWMechanics::getPlayer();
MWBase::Environment::get().getWorld()->breakInvisibility(player);

@ -102,6 +102,7 @@ namespace MWGui
bool mTrading;
float mScaleFactor;
float mUpdateTimer;
void onItemSelected(int index);
void onItemSelectedFromSourceModel(int index);

@ -163,9 +163,9 @@ namespace MWGui
std::string message;
if (mDays == 1)
message = gmst.find("sNotifyMessage42")->getString();
message = gmst.find("sNotifyMessage42")->mValue.getString();
else
message = gmst.find("sNotifyMessage43")->getString();
message = gmst.find("sNotifyMessage43")->mValue.getString();
/*
Start of tes3mp addition
@ -185,10 +185,10 @@ namespace MWGui
for (std::set<int>::iterator it = skills.begin(); it != skills.end(); ++it)
{
std::string skillName = gmst.find(ESM::Skill::sSkillNameIds[*it])->getString();
std::string skillName = gmst.find(ESM::Skill::sSkillNameIds[*it])->mValue.getString();
std::stringstream skillValue;
skillValue << player.getClass().getNpcStats(player).getSkill(*it).getBase();
std::string skillMsg = gmst.find("sNotifyMessage44")->getString();
std::string skillMsg = gmst.find("sNotifyMessage44")->mValue.getString();
/*
Start of tes3mp change (minor)
@ -200,7 +200,7 @@ namespace MWGui
/*
End of tes3mp change (minor)
*/
skillMsg = gmst.find("sNotifyMessage39")->getString();
skillMsg = gmst.find("sNotifyMessage39")->mValue.getString();
if (skillMsg.find("%s") != std::string::npos)
skillMsg.replace(skillMsg.find("%s"), 2, skillName);

@ -57,7 +57,7 @@ void MerchantRepair::setPtr(const MWWorld::Ptr &actor)
int basePrice = iter->getClass().getValue(*iter);
float fRepairMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fRepairMult")->getFloat();
.find("fRepairMult")->mValue.getFloat();
float p = static_cast<float>(std::max(1, basePrice));
float r = static_cast<float>(std::max(1, static_cast<int>(maxDurability / p)));
@ -71,7 +71,7 @@ void MerchantRepair::setPtr(const MWWorld::Ptr &actor)
std::string name = iter->getClass().getName(*iter)
+ " - " + MyGUI::utility::toString(price)
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sgp")->getString();
.find("sgp")->mValue.getString();
MyGUI::Button* button =

@ -199,19 +199,18 @@ void Recharge::onItemClicked(MyGUI::Widget *sender, const MWWorld::Ptr& item)
MWBase::Environment::get().getWindowManager()->playSound("Enchant Success");
player.getClass().getContainerStore(player).restack(item);
player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0);
}
else
{
MWBase::Environment::get().getWindowManager()->playSound("Enchant Fail");
}
player.getClass().skillUsageSucceeded (player, ESM::Skill::Enchant, 0);
gem.getContainerStore()->remove(gem, 1, player);
if (gem.getRefData().getCount() == 0)
{
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage51")->getString();
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage51")->mValue.getString();
message = boost::str(boost::format(message) % gem.getClass().getName(gem));
MWBase::Environment::get().getWindowManager()->messageBox(message);

@ -55,7 +55,7 @@ namespace MWGui
const MWWorld::ESMStore &store =
MWBase::Environment::get().getWorld()->getStore();
int price = static_cast<int>(spell.mData.mCost*store.get<ESM::GameSetting>().find("fSpellValueMult")->getFloat());
int price = static_cast<int>(spell.mData.mCost*store.get<ESM::GameSetting>().find("fSpellValueMult")->mValue.getFloat());
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
MWWorld::Ptr player = MWMechanics::getPlayer();

@ -44,8 +44,8 @@ namespace
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
return gmst.find(ESM::MagicEffect::effectIdToString (id1))->getString()
< gmst.find(ESM::MagicEffect::effectIdToString (id2))->getString();
return gmst.find(ESM::MagicEffect::effectIdToString (id1))->mValue.getString()
< gmst.find(ESM::MagicEffect::effectIdToString (id2))->mValue.getString();
}
void init(ESM::ENAMstruct& effect)
@ -495,7 +495,7 @@ namespace MWGui
mMagickaCost->setCaption(MyGUI::utility::toString(int(y)));
float fSpellMakingValueMult =
store.get<ESM::GameSetting>().find("fSpellMakingValueMult")->getFloat();
store.get<ESM::GameSetting>().find("fSpellMakingValueMult")->mValue.getFloat();
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, static_cast<int>(y * fSpellMakingValueMult),true);
@ -573,7 +573,7 @@ namespace MWGui
for (std::vector<short>::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it)
{
mAvailableEffectsList->addItem(MWBase::Environment::get().getWorld ()->getStore ().get<ESM::GameSetting>().find(
ESM::MagicEffect::effectIdToString (*it))->getString());
ESM::MagicEffect::effectIdToString (*it))->mValue.getString());
mButtonMapping[i] = *it;
++i;
}
@ -583,7 +583,7 @@ namespace MWGui
for (std::vector<short>::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it)
{
std::string name = MWBase::Environment::get().getWorld ()->getStore ().get<ESM::GameSetting>().find(
ESM::MagicEffect::effectIdToString (*it))->getString();
ESM::MagicEffect::effectIdToString (*it))->mValue.getString();
MyGUI::Widget* w = mAvailableEffectsList->getItemWidget(name);
ToolTips::createMagicEffectToolTip (w, *it);

@ -75,7 +75,7 @@ namespace MWGui
std::string sourcesDescription;
static const float fadeTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fMagicStartIconBlink")->getFloat();
static const float fadeTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fMagicStartIconBlink")->mValue.getFloat();
for (std::vector<MagicEffectInfo>::const_iterator effectIt = it->second.begin();
effectIt != it->second.end(); ++effectIt)

@ -97,6 +97,10 @@ namespace MWGui
mUpdateTimer = 0;
mSpellView->incrementalUpdate();
}
// Update effects in-game too if the window is pinned
if (mPinned && !MWBase::Environment::get().getWindowManager()->isGuiMode())
mSpellIcons->updateWidgets(mEffectBox, false);
}
void SpellWindow::updateSpells()

@ -61,7 +61,7 @@ namespace MWGui
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
for (int i=0; names[i][0]; ++i)
{
setText (names[i][0], store.get<ESM::GameSetting>().find (names[i][1])->getString());
setText (names[i][0], store.get<ESM::GameSetting>().find (names[i][1])->mValue.getString());
}
getWidget(mSkillView, "SkillView");
@ -306,7 +306,7 @@ namespace MWGui
MyGUI::Widget* levelWidget;
for (int i=0; i<2; ++i)
{
int max = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iLevelUpTotal")->getInt();
int max = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iLevelUpTotal")->mValue.getInteger();
getWidget(levelWidget, i==0 ? "Level_str" : "LevelText");
levelWidget->setUserString("RangePosition_LevelProgress", MyGUI::utility::toString(PCstats.getLevelProgress()));
levelWidget->setUserString("Range_LevelProgress", MyGUI::utility::toString(max));

@ -313,7 +313,7 @@ namespace MWGui
{
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(it->mBase.getCellRef().getRefId(), mPtr))
{
std::string msg = gmst.find("sNotifyMessage49")->getString();
std::string msg = gmst.find("sNotifyMessage49")->mValue.getString();
if (msg.find("%s") != std::string::npos)
msg.replace(msg.find("%s"), 2, it->mBase.getClass().getName(it->mBase));
MWBase::Environment::get().getWindowManager()->messageBox(msg);
@ -331,8 +331,8 @@ namespace MWGui
// apply disposition change if merchant is NPC
if ( mPtr.getClass().isNpc() ) {
int dispositionDelta = offerAccepted
? gmst.find("iBarterSuccessDisposition")->getInt()
: gmst.find("iBarterFailDisposition")->getInt();
? gmst.find("iBarterSuccessDisposition")->mValue.getInteger()
: gmst.find("iBarterFailDisposition")->mValue.getInteger();
MWBase::Environment::get().getDialogueManager()->applyBarterDispositionChange(dispositionDelta);
}

@ -98,7 +98,7 @@ namespace MWGui
for (int i=0; i<3; ++i)
{
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer
(mPtr,pcStats.getSkill (skills[i].first).getBase() * gmst.find("iTrainingMod")->getInt (),true);
(mPtr,pcStats.getSkill (skills[i].first).getBase() * gmst.find("iTrainingMod")->mValue.getInteger(),true);
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>(price <= playerGold ? "SandTextButton" : "SandTextButtonDisabled", // can't use setEnabled since that removes tooltip
MyGUI::IntCoord(5, 5+i*18, mTrainingOptions->getWidth()-10, 18), MyGUI::Align::Default);
@ -136,7 +136,7 @@ namespace MWGui
const MWWorld::ESMStore &store =
MWBase::Environment::get().getWorld()->getStore();
int price = pcStats.getSkill (skillId).getBase() * store.get<ESM::GameSetting>().find("iTrainingMod")->getInt ();
int price = pcStats.getSkill (skillId).getBase() * store.get<ESM::GameSetting>().find("iTrainingMod")->mValue.getInteger();
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr,price,true);
if (price > player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId))

@ -58,13 +58,13 @@ namespace MWGui
if (!mPtr.getCell()->isExterior())
{
price = gmst.find("fMagesGuildTravel")->getInt();
price = gmst.find("fMagesGuildTravel")->mValue.getInteger();
}
else
{
ESM::Position PlayerPos = player.getRefData().getPosition();
float d = sqrt(pow(pos.pos[0] - PlayerPos.pos[0], 2) + pow(pos.pos[1] - PlayerPos.pos[1], 2) + pow(pos.pos[2] - PlayerPos.pos[2], 2));
price = static_cast<int>(d / gmst.find("fTravelMult")->getFloat());
price = static_cast<int>(d / gmst.find("fTravelMult")->mValue.getFloat());
}
price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, price, true);
@ -176,7 +176,7 @@ namespace MWGui
{
ESM::Position playerPos = player.getRefData().getPosition();
float d = (osg::Vec3f(pos.pos[0], pos.pos[1], 0) - osg::Vec3f(playerPos.pos[0], playerPos.pos[1], 0)).length();
int hours = static_cast<int>(d /MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTravelTimeMult")->getFloat());
int hours = static_cast<int>(d /MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTravelTimeMult")->mValue.getFloat());
for(int i = 0;i < hours;i++)
{
MWBase::Environment::get().getMechanicsManager ()->rest (true);

@ -22,6 +22,8 @@ VideoWidget::VideoWidget()
setNeedKeyFocus(true);
}
VideoWidget::~VideoWidget() = default;
void VideoWidget::setVFS(const VFS::Manager *vfs)
{
mVFS = vfs;

@ -25,6 +25,8 @@ namespace MWGui
MYGUI_RTTI_DERIVED(VideoWidget)
VideoWidget();
~VideoWidget();
/// Set the VFS (virtual file system) to find the videos on.
void setVFS(const VFS::Manager* vfs);

@ -193,10 +193,10 @@ namespace MWGui
{
// figure out if player will be woken while sleeping
int x = Misc::Rng::rollDice(hoursToWait);
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->getFloat();
float fSleepRandMod = world->getStore().get<ESM::GameSetting>().find("fSleepRandMod")->mValue.getFloat();
if (x < fSleepRandMod * hoursToWait)
{
float fSleepRestMod = world->getStore().get<ESM::GameSetting>().find("fSleepRestMod")->getFloat();
float fSleepRestMod = world->getStore().get<ESM::GameSetting>().find("fSleepRestMod")->mValue.getFloat();
int interruptAtHoursRemaining = int(fSleepRestMod * hoursToWait);
if (interruptAtHoursRemaining != 0)
{
@ -271,7 +271,7 @@ namespace MWGui
// trigger levelup if possible
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
if (mSleeping && pcstats.getLevelProgress () >= gmst.find("iLevelUpTotal")->getInt())
if (mSleeping && pcstats.getLevelProgress () >= gmst.find("iLevelUpTotal")->mValue.getInteger())
{
MWBase::Environment::get().getWindowManager()->pushGuiMode (GM_Levelup);
}

@ -370,7 +370,7 @@ namespace MWGui
mGuiModeStates[GM_Journal].mCloseSound = "book close";
mGuiModeStates[GM_Journal].mOpenSound = "book open";
mMessageBoxManager = new MessageBoxManager(mStore->get<ESM::GameSetting>().find("fMessageTimePerChar")->getFloat());
mMessageBoxManager = new MessageBoxManager(mStore->get<ESM::GameSetting>().find("fMessageTimePerChar")->mValue.getFloat());
SpellBuyingWindow* spellBuyingWindow = new SpellBuyingWindow();
mWindows.push_back(spellBuyingWindow);

@ -1284,7 +1284,7 @@ namespace MWInput
void InputManager::updateIdleTime(float dt)
{
static const float vanityDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fVanityDelay")->getFloat();
.find("fVanityDelay")->mValue.getFloat();
if (mTimeIdle >= 0.f)
mTimeIdle += dt;
if (mTimeIdle > vanityDelay) {

@ -197,8 +197,14 @@ namespace MWMechanics
void ActiveSpells::removeEffects(const std::string &id)
{
mSpells.erase(Misc::StringUtils::lowerCase(id));
mSpellsChanged = true;
for (TContainer::iterator spell = mSpells.begin(); spell != mSpells.end(); ++spell)
{
if (spell->first == id)
{
spell->second.mEffects.clear();
mSpellsChanged = true;
}
}
}
void ActiveSpells::visitEffectSources(EffectSourceVisitor &visitor) const

@ -71,22 +71,22 @@ int getBoundItemSlot (const std::string& itemId)
static std::map<std::string, int> boundItemsMap;
if (boundItemsMap.empty())
{
std::string boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundBootsID")->getString();
std::string boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundBootsID")->mValue.getString();
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Boots;
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundCuirassID")->getString();
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundCuirassID")->mValue.getString();
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Cuirass;
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundLeftGauntletID")->getString();
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundLeftGauntletID")->mValue.getString();
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_LeftGauntlet;
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundRightGauntletID")->getString();
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundRightGauntletID")->mValue.getString();
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_RightGauntlet;
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundHelmID")->getString();
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundHelmID")->mValue.getString();
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_Helmet;
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundShieldID")->getString();
boundId = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sMagicBoundShieldID")->mValue.getString();
boundItemsMap[boundId] = MWWorld::InventoryStore::Slot_CarriedLeft;
}
@ -155,7 +155,7 @@ void getRestorationPerHourOfSleep (const MWWorld::Ptr& ptr, float& health, float
magicka = 0;
if (!stunted)
{
float fRestMagicMult = settings.find("fRestMagicMult")->getFloat ();
float fRestMagicMult = settings.find("fRestMagicMult")->mValue.getFloat ();
magicka = fRestMagicMult * stats.getAttribute(ESM::Attribute::Intelligence).getModified();
}
}
@ -206,7 +206,7 @@ namespace MWMechanics
if (caster.isEmpty() || !caster.getClass().isActor())
return;
static const float fSoulgemMult = world->getStore().get<ESM::GameSetting>().find("fSoulgemMult")->getFloat();
static const float fSoulgemMult = world->getStore().get<ESM::GameSetting>().find("fSoulgemMult")->mValue.getFloat();
int creatureSoulValue = mCreature.get<ESM::Creature>()->mBase->mData.mSoul;
if (creatureSoulValue == 0)
@ -354,9 +354,9 @@ namespace MWMechanics
MWWorld::Ptr& headTrackTarget, float& sqrHeadTrackDistance)
{
static const float fMaxHeadTrackDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fMaxHeadTrackDistance")->getFloat();
.find("fMaxHeadTrackDistance")->mValue.getFloat();
static const float fInteriorHeadTrackMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fInteriorHeadTrackMult")->getFloat();
.find("fInteriorHeadTrackMult")->mValue.getFloat();
float maxDistance = fMaxHeadTrackDistance;
const ESM::Cell* currentCell = actor.getCell()->getCell();
if (!currentCell->isExterior() && !(currentCell->mData.mFlags & ESM::Cell::QuasiEx))
@ -523,7 +523,7 @@ namespace MWMechanics
if (actor1.getClass().isClass(actor1, "Guard") && !actor2.getClass().isNpc())
{
// Check if the creature is too far
static const float fAlarmRadius = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->getFloat();
static const float fAlarmRadius = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->mValue.getFloat();
if (sqrDist > fAlarmRadius * fAlarmRadius)
return;
@ -587,9 +587,9 @@ namespace MWMechanics
float base = 1.f;
if (ptr == getPlayer())
base = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPCbaseMagickaMult")->getFloat();
base = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPCbaseMagickaMult")->mValue.getFloat();
else
base = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCbaseMagickaMult")->getFloat();
base = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fNPCbaseMagickaMult")->mValue.getFloat();
double magickaFactor = base +
creatureStats.getMagicEffects().get (EffectKey (ESM::MagicEffect::FortifyMaximumMagicka)).getMagnitude() * 0.1;
@ -637,9 +637,9 @@ namespace MWMechanics
return;
// Restore fatigue
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
float fEndFatigueMult = settings.find("fEndFatigueMult")->getFloat ();
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->mValue.getFloat ();
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat ();
float fEndFatigueMult = settings.find("fEndFatigueMult")->mValue.getFloat ();
float x = fFatigueReturnBase + fFatigueReturnMult * (1 - normalizedEncumbrance);
x *= fEndFatigueMult * endurance;
@ -664,8 +664,8 @@ namespace MWMechanics
// Restore fatigue
int endurance = stats.getAttribute(ESM::Attribute::Endurance).getModified();
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->mValue.getFloat ();
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->mValue.getFloat ();
float x = fFatigueReturnBase + fFatigueReturnMult * endurance;
@ -925,14 +925,14 @@ namespace MWMechanics
std::string itemGmst = it->second;
std::string item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
itemGmst)->getString();
itemGmst)->mValue.getString();
magnitude > 0 ? addBoundItem(item, ptr) : removeBoundItem(item, ptr);
if (it->first == ESM::MagicEffect::BoundGloves)
{
item = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"sMagicBoundRightGauntletID")->getString();
"sMagicBoundRightGauntletID")->mValue.getString();
magnitude > 0 ? addBoundItem(item, ptr) : removeBoundItem(item, ptr);
}
}
@ -1008,7 +1008,7 @@ namespace MWMechanics
NpcStats &stats = ptr.getClass().getNpcStats(ptr);
// When npc stats are just initialized, mTimeToStartDrowning == -1 and we should get value from GMST
static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->getFloat();
static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->mValue.getFloat();
if (stats.getTimeToStartDrowning() == -1.f)
stats.setTimeToStartDrowning(fHoldBreathTime);
@ -1042,7 +1042,7 @@ namespace MWMechanics
if(timeLeft == 0.0f && !godmode)
{
// If drowning, apply 3 points of damage per second
static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->getFloat();
static const float fSuffocationDamage = world->getStore().get<ESM::GameSetting>().find("fSuffocationDamage")->mValue.getFloat();
DynamicStat<float> health = stats.getHealth();
health.setCurrent(health.getCurrent() - fSuffocationDamage*duration);
stats.setHealth(health);
@ -1179,7 +1179,7 @@ namespace MWMechanics
&& creatureStats.getMagicEffects().get(ESM::MagicEffect::CalmHumanoid).getMagnitude() == 0)
{
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
static const int cutoff = esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->getInt();
static const int cutoff = esmStore.get<ESM::GameSetting>().find("iCrimeThreshold")->mValue.getInteger();
// Force dialogue on sight if bounty is greater than the cutoff
// In vanilla morrowind, the greeting dialogue is scripted to either arrest the player (< 5000 bounty) or attack (>= 5000 bounty)
if ( player.getClass().getNpcStats(player).getBounty() >= cutoff
@ -1187,7 +1187,7 @@ namespace MWMechanics
&& MWBase::Environment::get().getWorld()->getLOS(ptr, player)
&& MWBase::Environment::get().getMechanicsManager()->awarenessCheck(player, ptr))
{
static const int iCrimeThresholdMultiplier = esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->getInt();
static const int iCrimeThresholdMultiplier = esmStore.get<ESM::GameSetting>().find("iCrimeThresholdMultiplier")->mValue.getInteger();
/*
Start of tes3mp change (major)
@ -1675,9 +1675,9 @@ namespace MWMechanics
static float sneakSkillTimer = 0.f; // times sneak skill progress from "avoid notice"
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
const int radius = esmStore.get<ESM::GameSetting>().find("fSneakUseDist")->getInt();
const int radius = esmStore.get<ESM::GameSetting>().find("fSneakUseDist")->mValue.getInteger();
static float fSneakUseDelay = esmStore.get<ESM::GameSetting>().find("fSneakUseDelay")->getFloat();
static float fSneakUseDelay = esmStore.get<ESM::GameSetting>().find("fSneakUseDelay")->mValue.getFloat();
if (sneakTimer >= fSneakUseDelay)
sneakTimer = 0.f;
@ -1921,7 +1921,7 @@ namespace MWMechanics
MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(iter->first);
if (animation)
animation->updateEffects(duration);
animation->updateEffects();
}
@ -2037,6 +2037,8 @@ namespace MWMechanics
if (iteratedActor == getPlayer())
continue;
const bool sameActor = (iteratedActor == actor);
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
if (stats.isDead())
continue;
@ -2045,14 +2047,13 @@ namespace MWMechanics
// Actors that are targeted by this actor's Follow or Escort packages also side with them
for (auto package = stats.getAiSequence().begin(); package != stats.getAiSequence().end(); ++package)
{
const MWWorld::Ptr &target = (*package)->getTarget();
if ((*package)->sideWithTarget() && !target.isEmpty())
if ((*package)->sideWithTarget() && !(*package)->getTarget().isEmpty())
{
if (iteratedActor == actor)
if (sameActor)
{
list.push_back(target);
list.push_back((*package)->getTarget());
}
else if (target == actor)
else if ((*package)->getTarget() == actor)
{
list.push_back(iteratedActor);
}
@ -2071,7 +2072,7 @@ namespace MWMechanics
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{
const MWWorld::Ptr &iteratedActor = iter->first;
if (iteratedActor == getPlayer())
if (iteratedActor == getPlayer() || iteratedActor == actor)
continue;
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
@ -2134,7 +2135,7 @@ namespace MWMechanics
for(PtrActorMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{
const MWWorld::Ptr &iteratedActor = iter->first;
if (iteratedActor == getPlayer())
if (iteratedActor == getPlayer() || iteratedActor == actor)
continue;
const CreatureStats &stats = iteratedActor.getClass().getCreatureStats(iteratedActor);
@ -2164,8 +2165,11 @@ namespace MWMechanics
getObjectsInRange(position, aiProcessingDistance, neighbors);
for(auto neighbor = neighbors.begin(); neighbor != neighbors.end(); ++neighbor)
{
if (*neighbor == actor)
continue;
const CreatureStats &stats = neighbor->getClass().getCreatureStats(*neighbor);
if (stats.isDead() || *neighbor == actor)
if (stats.isDead())
continue;
if (stats.getAiSequence().isInCombat(actor))

@ -19,7 +19,7 @@ MWMechanics::AiBreathe::AiBreathe()
bool MWMechanics::AiBreathe::execute (const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
{
static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->getFloat();
static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHoldBreathTime")->mValue.getFloat();
const MWWorld::Class& actorClass = actor.getClass();
if (actorClass.isNpc())

@ -417,7 +417,7 @@ namespace MWMechanics
case AiCombatStorage::FleeState_RunToDestination:
{
static const float fFleeDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFleeDistance")->getFloat();
static const float fFleeDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFleeDistance")->mValue.getFloat();
float dist = (actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length();
if ((dist > fFleeDistance && !storage.mLOS)
@ -604,13 +604,13 @@ namespace MWMechanics
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
float baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayCreature")->getFloat();
float baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayCreature")->mValue.getFloat();
if (actor.getClass().isNpc())
{
baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayNPC")->getFloat();
baseDelay = store.get<ESM::GameSetting>().find("fCombatDelayNPC")->mValue.getFloat();
//say a provoking combat phrase
int chance = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->getInt();
int chance = store.get<ESM::GameSetting>().find("iVoiceAttackOdds")->mValue.getInteger();
if (Misc::Rng::roll0to99() < chance)
{
MWBase::Environment::get().getDialogueManager()->say(actor, "attack");
@ -700,21 +700,21 @@ osg::Vec3f AimDirToMovingTarget(const MWWorld::Ptr& actor, const MWWorld::Ptr& t
// get projectile speed (depending on weapon type)
if (weapType == ESM::Weapon::MarksmanThrown)
{
static float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->getFloat();
static float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->getFloat();
static float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->mValue.getFloat();
static float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->mValue.getFloat();
projSpeed = fThrownWeaponMinSpeed + (fThrownWeaponMaxSpeed - fThrownWeaponMinSpeed) * strength;
}
else if (weapType != 0)
{
static float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->getFloat();
static float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->getFloat();
static float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->mValue.getFloat();
static float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->mValue.getFloat();
projSpeed = fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * strength;
}
else // weapType is 0 ==> it's a target spell projectile
{
projSpeed = gmst.find("fTargetSpellMaxSpeed")->getFloat();
projSpeed = gmst.find("fTargetSpellMaxSpeed")->mValue.getFloat();
}
// idea: perpendicular to dir to target speed components of target move vector and projectile vector should be the same

@ -23,8 +23,8 @@ namespace MWMechanics
{
float suggestCombatRange(int rangeTypes)
{
static const float fCombatDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCombatDistance")->getFloat();
static float fHandToHandReach = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHandToHandReach")->getFloat();
static const float fCombatDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCombatDistance")->mValue.getFloat();
static float fHandToHandReach = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHandToHandReach")->mValue.getFloat();
// This distance is a possible distance of melee attack
static float distance = fCombatDistance * std::max(2.f, fHandToHandReach);
@ -114,13 +114,13 @@ namespace MWMechanics
{
isRanged = false;
static const float fCombatDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCombatDistance")->getFloat();
static const float fProjectileMaxSpeed = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fProjectileMaxSpeed")->getFloat();
static const float fCombatDistance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCombatDistance")->mValue.getFloat();
static const float fProjectileMaxSpeed = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fProjectileMaxSpeed")->mValue.getFloat();
if (mWeapon.isEmpty())
{
static float fHandToHandReach =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHandToHandReach")->getFloat();
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fHandToHandReach")->mValue.getFloat();
return fHandToHandReach * fCombatDistance;
}
@ -190,11 +190,6 @@ namespace MWMechanics
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
std::vector<int> equipmentSlots = it->getClass().getEquipmentSlots(*it).first;
if (std::find(equipmentSlots.begin(), equipmentSlots.end(), (int)MWWorld::InventoryStore::Slot_CarriedRight)
== equipmentSlots.end())
continue;
float rating = rateWeapon(*it, actor, enemy, -1, bestArrowRating, bestBoltRating);
if (rating > bestActionRating)
{
@ -215,14 +210,12 @@ namespace MWMechanics
for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
{
const ESM::Spell* spell = it->first;
float rating = rateSpell(spell, actor, enemy);
float rating = rateSpell(it->first, actor, enemy);
if (rating > bestActionRating)
{
bestActionRating = rating;
bestAction.reset(new ActionSpell(spell->mId));
antiFleeRating = vanillaRateSpell(spell, actor, enemy);
bestAction.reset(new ActionSpell(it->first->mId));
antiFleeRating = vanillaRateSpell(it->first, actor, enemy);
}
}
@ -265,11 +258,6 @@ namespace MWMechanics
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
{
std::vector<int> equipmentSlots = it->getClass().getEquipmentSlots(*it).first;
if (std::find(equipmentSlots.begin(), equipmentSlots.end(), (int)MWWorld::InventoryStore::Slot_CarriedRight)
== equipmentSlots.end())
continue;
float rating = rateWeapon(*it, actor, enemy, -1, bestArrowRating, bestBoltRating);
if (rating > bestActionRating)
{
@ -280,9 +268,7 @@ namespace MWMechanics
for (Spells::TIterator it = spells.begin(); it != spells.end(); ++it)
{
const ESM::Spell* spell = it->first;
float rating = rateSpell(spell, actor, enemy);
float rating = rateSpell(it->first, actor, enemy);
if (rating > bestActionRating)
{
bestActionRating = rating;
@ -336,7 +322,7 @@ namespace MWMechanics
float dist = 1.0f;
if (activeWeapon.isEmpty() && !selectedSpellId.empty() && !selectedEnchItem.isEmpty())
{
static const float fHandToHandReach = gmst.find("fHandToHandReach")->getFloat();
static const float fHandToHandReach = gmst.find("fHandToHandReach")->mValue.getFloat();
dist = fHandToHandReach;
}
else if (stats.getDrawState() == MWMechanics::DrawState_Spell)
@ -375,7 +361,7 @@ namespace MWMechanics
}
}
static const float fTargetSpellMaxSpeed = gmst.find("fTargetSpellMaxSpeed")->getFloat();
static const float fTargetSpellMaxSpeed = gmst.find("fTargetSpellMaxSpeed")->mValue.getFloat();
dist *= std::max(1000.0f, fTargetSpellMaxSpeed);
}
else if (!activeWeapon.isEmpty())
@ -383,7 +369,7 @@ namespace MWMechanics
const ESM::Weapon* esmWeap = activeWeapon.get<ESM::Weapon>()->mBase;
if (esmWeap->mData.mType >= ESM::Weapon::MarksmanBow)
{
static const float fTargetSpellMaxSpeed = gmst.find("fProjectileMaxSpeed")->getFloat();
static const float fTargetSpellMaxSpeed = gmst.find("fProjectileMaxSpeed")->mValue.getFloat();
dist = fTargetSpellMaxSpeed;
if (!activeAmmo.isEmpty())
{
@ -399,8 +385,8 @@ namespace MWMechanics
dist = (dist > 0.f) ? dist : 1.0f;
static const float fCombatDistance = gmst.find("fCombatDistance")->getFloat();
static const float fCombatDistanceWerewolfMod = gmst.find("fCombatDistanceWerewolfMod")->getFloat();
static const float fCombatDistance = gmst.find("fCombatDistance")->mValue.getFloat();
static const float fCombatDistanceWerewolfMod = gmst.find("fCombatDistanceWerewolfMod")->mValue.getFloat();
float combatDistance = fCombatDistance;
if (actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
@ -485,20 +471,20 @@ namespace MWMechanics
if (flee >= 100)
return flee;
static const float fAIFleeHealthMult = gmst.find("fAIFleeHealthMult")->getFloat();
static const float fAIFleeFleeMult = gmst.find("fAIFleeFleeMult")->getFloat();
static const float fAIFleeHealthMult = gmst.find("fAIFleeHealthMult")->mValue.getFloat();
static const float fAIFleeFleeMult = gmst.find("fAIFleeFleeMult")->mValue.getFloat();
float healthPercentage = (stats.getHealth().getModified() == 0.0f)
? 1.0f : stats.getHealth().getCurrent() / stats.getHealth().getModified();
float rating = (1.0f - healthPercentage) * fAIFleeHealthMult + flee * fAIFleeFleeMult;
static const int iWereWolfLevelToAttack = gmst.find("iWereWolfLevelToAttack")->getInt();
static const int iWereWolfLevelToAttack = gmst.find("iWereWolfLevelToAttack")->mValue.getInteger();
if (actor.getClass().isNpc() && enemy.getClass().isNpc())
{
if (enemy.getClass().getNpcStats(enemy).isWerewolf() && stats.getLevel() < iWereWolfLevelToAttack)
{
static const int iWereWolfFleeMod = gmst.find("iWereWolfFleeMod")->getInt();
static const int iWereWolfFleeMod = gmst.find("iWereWolfFleeMod")->mValue.getInteger();
rating = iWereWolfFleeMod;
}
}

@ -228,7 +228,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
{
if ((*it)->getTypeId() != AiPackage::TypeIdCombat) break;
MWWorld::Ptr target = static_cast<const AiCombat *>(*it)->getTarget();
MWWorld::Ptr target = (*it)->getTarget();
// target disappeared (e.g. summoned creatures)
if (target.isEmpty())
@ -242,11 +242,11 @@ void AiSequence::execute (const MWWorld::Ptr& actor, CharacterController& charac
const ESM::Position &targetPos = target.getRefData().getPosition();
float distTo = (targetPos.asVec3() - vActorPos).length();
float distTo = (targetPos.asVec3() - vActorPos).length2();
// Small threshold for changing target
if (it == mPackages.begin())
distTo = std::max(0.f, distTo - 50.f);
distTo = std::max(0.f, distTo - 2500.f);
// if a target has higher priority than current target or has same priority but closer
if (rating > bestRating || ((distTo < nearestDist) && rating == bestRating))

@ -495,7 +495,7 @@ namespace MWMechanics
MWWorld::Ptr player = getPlayer();
static float fVoiceIdleOdds = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->getFloat();
.get<ESM::GameSetting>().find("fVoiceIdleOdds")->mValue.getFloat();
float roll = Misc::Rng::rollProbability() * 10000.0f;
@ -522,7 +522,7 @@ namespace MWMechanics
int hello = actor.getClass().getCreatureStats(actor).getAiSetting(CreatureStats::AI_Hello).getModified();
float helloDistance = static_cast<float>(hello);
static int iGreetDistanceMultiplier = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("iGreetDistanceMultiplier")->getInt();
.get<ESM::GameSetting>().find("iGreetDistanceMultiplier")->mValue.getInteger();
helloDistance *= iGreetDistanceMultiplier;
@ -700,7 +700,7 @@ namespace MWMechanics
for(unsigned int counter = 0; counter < mIdle.size(); counter++)
{
static float fIdleChanceMultiplier = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fIdleChanceMultiplier")->getFloat();
.get<ESM::GameSetting>().find("fIdleChanceMultiplier")->mValue.getFloat();
unsigned short idleChance = static_cast<unsigned short>(fIdleChanceMultiplier * mIdle[counter]);
unsigned short randSelect = (int)(Misc::Rng::rollProbability() * int(100 / fIdleChanceMultiplier));

@ -153,11 +153,11 @@ void MWMechanics::Alchemy::updateEffects()
float x = getAlchemyFactor();
x *= mTools[ESM::Apparatus::MortarPestle].get<ESM::Apparatus>()->mBase->mData.mQuality;
x *= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fPotionStrengthMult")->getFloat();
x *= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fPotionStrengthMult")->mValue.getFloat();
// value
mValue = static_cast<int> (
x * MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("iAlchemyMod")->getFloat());
x * MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("iAlchemyMod")->mValue.getFloat());
// build quantified effect list
for (std::set<EffectKey>::const_iterator iter (effects.begin()); iter!=effects.end(); ++iter)
@ -173,13 +173,13 @@ void MWMechanics::Alchemy::updateEffects()
}
float fPotionT1MagMul =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fPotionT1MagMult")->getFloat();
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fPotionT1MagMult")->mValue.getFloat();
if (fPotionT1MagMul<=0)
throw std::runtime_error ("invalid gmst: fPotionT1MagMul");
float fPotionT1DurMult =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fPotionT1DurMult")->getFloat();
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fPotionT1DurMult")->mValue.getFloat();
if (fPotionT1DurMult<=0)
throw std::runtime_error ("invalid gmst: fPotionT1DurMult");
@ -478,7 +478,7 @@ bool MWMechanics::Alchemy::knownEffect(unsigned int potionEffectIndex, const MWW
MWMechanics::NpcStats& npcStats = npc.getClass().getNpcStats(npc);
int alchemySkill = npcStats.getSkill (ESM::Skill::Alchemy).getBase();
static const float fWortChanceValue =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->getFloat();
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWortChanceValue")->mValue.getFloat();
return (potionEffectIndex <= 1 && alchemySkill >= fWortChanceValue)
|| (potionEffectIndex <= 3 && alchemySkill >= fWortChanceValue*2)
|| (potionEffectIndex <= 5 && alchemySkill >= fWortChanceValue*3)
@ -532,5 +532,5 @@ std::string MWMechanics::Alchemy::suggestPotionName()
int effectId = effects.begin()->mId;
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
ESM::MagicEffect::effectIdToString(effectId))->getString();
ESM::MagicEffect::effectIdToString(effectId))->mValue.getString();
}

@ -25,7 +25,7 @@ namespace MWMechanics
std::vector<std::string> autoCalcNpcSpells(const int *actorSkills, const int *actorAttributes, const ESM::Race* race)
{
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fNPCbaseMagickaMult = gmst.find("fNPCbaseMagickaMult")->getFloat();
static const float fNPCbaseMagickaMult = gmst.find("fNPCbaseMagickaMult")->mValue.getFloat();
float baseMagicka = fNPCbaseMagickaMult * actorAttributes[ESM::Attribute::Intelligence];
static const std::string schools[] = {
@ -38,7 +38,7 @@ namespace MWMechanics
for (int i=0; i<6; ++i)
{
const std::string& gmstName = "iAutoSpell" + schools[i] + "Max";
iAutoSpellSchoolMax[i] = gmst.find(gmstName)->getInt();
iAutoSpellSchoolMax[i] = gmst.find(gmstName)->mValue.getInteger();
}
init = true;
}
@ -70,7 +70,7 @@ namespace MWMechanics
continue;
if (!(spell->mData.mFlags & ESM::Spell::F_Autocalc))
continue;
static const int iAutoSpellTimesCanCast = gmst.find("iAutoSpellTimesCanCast")->getInt();
static const int iAutoSpellTimesCanCast = gmst.find("iAutoSpellTimesCanCast")->mValue.getInteger();
if (baseMagicka < iAutoSpellTimesCanCast * spell->mData.mCost)
continue;
@ -89,7 +89,7 @@ namespace MWMechanics
if (cap.mReachedLimit && spell->mData.mCost <= cap.mMinCost)
continue;
static const float fAutoSpellChance = gmst.find("fAutoSpellChance")->getFloat();
static const float fAutoSpellChance = gmst.find("fAutoSpellChance")->mValue.getFloat();
if (calcAutoCastChance(spell, actorSkills, actorAttributes, school) < fAutoSpellChance)
continue;
@ -146,7 +146,7 @@ namespace MWMechanics
{
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
static const float fPCbaseMagickaMult = esmStore.get<ESM::GameSetting>().find("fPCbaseMagickaMult")->getFloat();
static const float fPCbaseMagickaMult = esmStore.get<ESM::GameSetting>().find("fPCbaseMagickaMult")->mValue.getFloat();
float baseMagicka = fPCbaseMagickaMult * actorAttributes[ESM::Attribute::Intelligence];
bool reachedLimit = false;
@ -173,7 +173,7 @@ namespace MWMechanics
if (baseMagicka < spell->mData.mCost)
continue;
static const float fAutoPCSpellChance = esmStore.get<ESM::GameSetting>().find("fAutoPCSpellChance")->getFloat();
static const float fAutoPCSpellChance = esmStore.get<ESM::GameSetting>().find("fAutoPCSpellChance")->mValue.getFloat();
if (calcAutoCastChance(spell, actorSkills, actorAttributes, -1) < fAutoPCSpellChance)
continue;
@ -206,7 +206,7 @@ namespace MWMechanics
weakestSpell = spell;
minCost = weakestSpell->mData.mCost;
}
static const unsigned int iAutoPCSpellMax = esmStore.get<ESM::GameSetting>().find("iAutoPCSpellMax")->getInt();
static const unsigned int iAutoPCSpellMax = esmStore.get<ESM::GameSetting>().find("iAutoPCSpellMax")->mValue.getInteger();
if (selectedSpells.size() == iAutoPCSpellMax)
reachedLimit = true;
}
@ -221,7 +221,7 @@ namespace MWMechanics
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = effects.begin(); effectIt != effects.end(); ++effectIt)
{
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effectIt->mEffectID);
static const int iAutoSpellAttSkillMin = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iAutoSpellAttSkillMin")->getInt();
static const int iAutoSpellAttSkillMin = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iAutoSpellAttSkillMin")->mValue.getInteger();
if ((magicEffect->mData.mFlags & ESM::MagicEffect::TargetSkill))
{
@ -278,7 +278,7 @@ namespace MWMechanics
duration = effect.mDuration;
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
float x = 0.5 * (std::max(1, minMagn) + std::max(1, maxMagn));
x *= 0.1 * magicEffect->mData.mBaseCost;

@ -139,16 +139,16 @@ float getFallDamage(const MWWorld::Ptr& ptr, float fallHeight)
MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
const float fallDistanceMin = store.find("fFallDamageDistanceMin")->getFloat();
const float fallDistanceMin = store.find("fFallDamageDistanceMin")->mValue.getFloat();
if (fallHeight >= fallDistanceMin)
{
const float acrobaticsSkill = static_cast<float>(ptr.getClass().getSkill(ptr, ESM::Skill::Acrobatics));
const float jumpSpellBonus = ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Jump).getMagnitude();
const float fallAcroBase = store.find("fFallAcroBase")->getFloat();
const float fallAcroMult = store.find("fFallAcroMult")->getFloat();
const float fallDistanceBase = store.find("fFallDistanceBase")->getFloat();
const float fallDistanceMult = store.find("fFallDistanceMult")->getFloat();
const float fallAcroBase = store.find("fFallAcroBase")->mValue.getFloat();
const float fallAcroMult = store.find("fFallAcroMult")->mValue.getFloat();
const float fallDistanceBase = store.find("fFallDistanceBase")->mValue.getFloat();
const float fallDistanceMult = store.find("fFallDistanceMult")->mValue.getFloat();
float x = fallHeight - fallDistanceMin;
x -= (1.5f * acrobaticsSkill) + jumpSpellBonus;
@ -968,11 +968,14 @@ void CharacterController::handleTextKey(const std::string &groupname, const std:
}
}
if (soundgen == "land") // Morrowind ignores land soundgen for some reason
return;
std::string sound = mPtr.getClass().getSoundIdFromSndGen(mPtr, soundgen);
if(!sound.empty())
{
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(evt.compare(10, evt.size()-10, "left") == 0 || evt.compare(10, evt.size()-10, "right") == 0 || evt.compare(10, evt.size()-10, "land") == 0)
if(soundgen == "left" || soundgen == "right")
{
// Don't make foot sounds local for the player, it makes sense to keep them
// positioned on the ground.
@ -1910,10 +1913,11 @@ void CharacterController::update(float duration)
else if(!cls.getCreatureStats(mPtr).isDead())
{
bool onground = world->isOnGround(mPtr);
bool incapacitated = (cls.getCreatureStats(mPtr).isParalyzed() || cls.getCreatureStats(mPtr).getKnockedDown());
bool inwater = world->isSwimming(mPtr);
bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak);
bool flying = world->isFlying(mPtr);
// Can't run while flying (see speed formula in Npc/Creature::getSpeed)
// Can't run and sneak while flying (see speed formula in Npc/Creature::getSpeed)
bool sneak = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak) && !flying;
bool isrunning = cls.getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) && !flying;
CreatureStats &stats = cls.getCreatureStats(mPtr);
@ -2025,14 +2029,14 @@ void CharacterController::update(float duration)
// reduce fatigue
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
float fatigueLoss = 0;
static const float fFatigueRunBase = gmst.find("fFatigueRunBase")->getFloat();
static const float fFatigueRunMult = gmst.find("fFatigueRunMult")->getFloat();
static const float fFatigueSwimWalkBase = gmst.find("fFatigueSwimWalkBase")->getFloat();
static const float fFatigueSwimRunBase = gmst.find("fFatigueSwimRunBase")->getFloat();
static const float fFatigueSwimWalkMult = gmst.find("fFatigueSwimWalkMult")->getFloat();
static const float fFatigueSwimRunMult = gmst.find("fFatigueSwimRunMult")->getFloat();
static const float fFatigueSneakBase = gmst.find("fFatigueSneakBase")->getFloat();
static const float fFatigueSneakMult = gmst.find("fFatigueSneakMult")->getFloat();
static const float fFatigueRunBase = gmst.find("fFatigueRunBase")->mValue.getFloat();
static const float fFatigueRunMult = gmst.find("fFatigueRunMult")->mValue.getFloat();
static const float fFatigueSwimWalkBase = gmst.find("fFatigueSwimWalkBase")->mValue.getFloat();
static const float fFatigueSwimRunBase = gmst.find("fFatigueSwimRunBase")->mValue.getFloat();
static const float fFatigueSwimWalkMult = gmst.find("fFatigueSwimWalkMult")->mValue.getFloat();
static const float fFatigueSwimRunMult = gmst.find("fFatigueSwimRunMult")->mValue.getFloat();
static const float fFatigueSneakBase = gmst.find("fFatigueSneakBase")->mValue.getFloat();
static const float fFatigueSneakMult = gmst.find("fFatigueSneakMult")->mValue.getFloat();
if (cls.getEncumbrance(mPtr) <= cls.getCapacity(mPtr))
{
@ -2061,7 +2065,7 @@ void CharacterController::update(float duration)
cls.getCreatureStats(mPtr).setFatigue(fatigue);
}
if(sneak || inwater || flying)
if(sneak || inwater || flying || incapacitated)
vec.z() = 0.0f;
bool inJump = true;
@ -2072,8 +2076,8 @@ void CharacterController::update(float duration)
forcestateupdate = (mJumpState != JumpState_InAir);
jumpstate = JumpState_InAir;
static const float fJumpMoveBase = gmst.find("fJumpMoveBase")->getFloat();
static const float fJumpMoveMult = gmst.find("fJumpMoveMult")->getFloat();
static const float fJumpMoveBase = gmst.find("fJumpMoveBase")->mValue.getFloat();
static const float fJumpMoveMult = gmst.find("fJumpMoveMult")->mValue.getFloat();
float factor = fJumpMoveBase + fJumpMoveMult * mPtr.getClass().getSkill(mPtr, ESM::Skill::Acrobatics)/100.f;
factor = std::min(1.f, factor);
vec.x() *= factor;
@ -2100,8 +2104,8 @@ void CharacterController::update(float duration)
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0);
// decrease fatigue
const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat();
const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat();
const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->mValue.getFloat();
const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->mValue.getFloat();
float normalizedEncumbrance = mPtr.getClass().getNormalizedEncumbrance(mPtr);
if (normalizedEncumbrance > 1)
normalizedEncumbrance = 1;
@ -2130,17 +2134,15 @@ void CharacterController::update(float duration)
// inflict fall damages
if (!godmode)
{
DynamicStat<float> health = cls.getCreatureStats(mPtr).getHealth();
float realHealthLost = static_cast<float>(healthLost * (1.0f - 0.25f * fatigueTerm));
health.setCurrent(health.getCurrent() - realHealthLost);
cls.getCreatureStats(mPtr).setHealth(health);
cls.onHit(mPtr, realHealthLost, true, MWWorld::Ptr(), MWWorld::Ptr(), osg::Vec3f(), true);
}
const int acrobaticsSkill = cls.getSkill(mPtr, ESM::Skill::Acrobatics);
if (healthLost > (acrobaticsSkill * fatigueTerm))
{
cls.getCreatureStats(mPtr).setKnockedDown(true);
if (!godmode)
cls.getCreatureStats(mPtr).setKnockedDown(true);
}
else
{
@ -2149,6 +2151,12 @@ void CharacterController::update(float duration)
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1);
}
}
// Play landing sound
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
std::string sound = cls.getSoundIdFromSndGen(mPtr, "land");
if (!sound.empty())
sndMgr->playSound3D(mPtr, sound, 1.f, 1.f, MWSound::Type::Foot, MWSound::PlayMode::NoPlayerLocal);
}
else
{
@ -2158,6 +2166,12 @@ void CharacterController::update(float duration)
inJump = false;
// Do not play turning animation for player if rotation speed is very slow.
// Actual threshold should take framerate in account.
float rotationThreshold = 0;
if (mPtr == getPlayer())
rotationThreshold = 0.015 * 60 * duration;
if(std::abs(vec.x()/2.0f) > std::abs(vec.y()))
{
if(vec.x() > 0.0f)
@ -2182,9 +2196,9 @@ void CharacterController::update(float duration)
}
else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson()))
{
if(rot.z() > 0.0f)
if(rot.z() > rotationThreshold)
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
else if(rot.z() < 0.0f)
else if(rot.z() < -rotationThreshold)
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
}
}
@ -2335,9 +2349,6 @@ void CharacterController::update(float duration)
moved *= (l / newLength);
}
if (mSkipAnim)
mAnimation->updateEffects(duration);
if (mFloatToSurface && cls.isActor() && cls.getCreatureStats(mPtr).isDead() && cls.canSwim(mPtr))
moved.z() = 1.0;

@ -97,9 +97,9 @@ namespace MWMechanics
osg::Vec3f(0,0,1)));
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
if (angleDegrees < gmst.find("fCombatBlockLeftAngle")->getFloat())
if (angleDegrees < gmst.find("fCombatBlockLeftAngle")->mValue.getFloat())
return false;
if (angleDegrees > gmst.find("fCombatBlockRightAngle")->getFloat())
if (angleDegrees > gmst.find("fCombatBlockRightAngle")->mValue.getFloat())
return false;
MWMechanics::CreatureStats& attackerStats = attacker.getClass().getCreatureStats(attacker);
@ -107,11 +107,11 @@ namespace MWMechanics
float blockTerm = blocker.getClass().getSkill(blocker, ESM::Skill::Block) + 0.2f * blockerStats.getAttribute(ESM::Attribute::Agility).getModified()
+ 0.1f * blockerStats.getAttribute(ESM::Attribute::Luck).getModified();
float enemySwing = attackStrength;
float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->getFloat() + gmst.find("fSwingBlockBase")->getFloat();
float swingTerm = enemySwing * gmst.find("fSwingBlockMult")->mValue.getFloat() + gmst.find("fSwingBlockBase")->mValue.getFloat();
float blockerTerm = blockTerm * swingTerm;
if (blocker.getClass().getMovementSettings(blocker).mPosition[1] <= 0)
blockerTerm *= gmst.find("fBlockStillBonus")->getFloat();
blockerTerm *= gmst.find("fBlockStillBonus")->mValue.getFloat();
blockerTerm *= blockerStats.getFatigueTerm();
int attackerSkill = 0;
@ -124,8 +124,8 @@ namespace MWMechanics
attackerTerm *= attackerStats.getFatigueTerm();
int x = int(blockerTerm - attackerTerm);
int iBlockMaxChance = gmst.find("iBlockMaxChance")->getInt();
int iBlockMinChance = gmst.find("iBlockMinChance")->getInt();
int iBlockMaxChance = gmst.find("iBlockMaxChance")->mValue.getInteger();
int iBlockMinChance = gmst.find("iBlockMinChance")->mValue.getInteger();
x = std::min(iBlockMaxChance, std::max(iBlockMinChance, x));
/*
@ -165,9 +165,9 @@ namespace MWMechanics
inv.unequipItem(*shield, blocker);
}
// Reduce blocker fatigue
const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->getFloat();
const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->getFloat();
const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->getFloat();
const float fFatigueBlockBase = gmst.find("fFatigueBlockBase")->mValue.getFloat();
const float fFatigueBlockMult = gmst.find("fFatigueBlockMult")->mValue.getFloat();
const float fWeaponFatigueBlockMult = gmst.find("fWeaponFatigueBlockMult")->mValue.getFloat();
MWMechanics::DynamicStat<float> fatigue = blockerStats.getFatigue();
float normalizedEncumbrance = blocker.getClass().getNormalizedEncumbrance(blocker);
normalizedEncumbrance = std::min(1.f, normalizedEncumbrance);
@ -205,7 +205,7 @@ namespace MWMechanics
if ((weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Silver)
&& actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())
damage *= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWereWolfSilverWeaponDamageMult")->getFloat();
damage *= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWereWolfSilverWeaponDamageMult")->mValue.getFloat();
if (damage == 0 && attacker == getPlayer())
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResistsWeapons}");
@ -302,14 +302,14 @@ namespace MWMechanics
if (unaware)
{
damage *= gmst.find("fCombatCriticalStrikeMult")->getFloat();
damage *= gmst.find("fCombatCriticalStrikeMult")->mValue.getFloat();
MWBase::Environment::get().getWindowManager()->messageBox("#{sTargetCriticalStrike}");
MWBase::Environment::get().getSoundManager()->playSound3D(victim, "critical damage", 1.0f, 1.0f);
}
}
if (victim.getClass().getCreatureStats(victim).getKnockedDown())
damage *= gmst.find("fCombatKODamageMult")->getFloat();
damage *= gmst.find("fCombatKODamageMult")->mValue.getFloat();
}
reduceWeaponCondition(damage, validVictim, weapon, attacker);
@ -343,7 +343,7 @@ namespace MWMechanics
// Non-enchanted arrows shot at enemies have a chance to turn up in their inventory
if (victim != getPlayer() && !appliedEnchantment)
{
float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->getFloat();
float fProjectileThrownStoreChance = gmst.find("fProjectileThrownStoreChance")->mValue.getFloat();
if (Misc::Rng::rollProbability() < fProjectileThrownStoreChance / 100.f)
victim.getClass().getContainerStore(victim).add(projectile, 1, victim);
}
@ -388,10 +388,10 @@ namespace MWMechanics
defenseTerm = victimStats.getEvasion();
}
defenseTerm += std::min(100.f,
gmst.find("fCombatInvisoMult")->getFloat() *
gmst.find("fCombatInvisoMult")->mValue.getFloat() *
victimStats.getMagicEffects().get(ESM::MagicEffect::Chameleon).getMagnitude());
defenseTerm += std::min(100.f,
gmst.find("fCombatInvisoMult")->getFloat() *
gmst.find("fCombatInvisoMult")->mValue.getFloat() *
victimStats.getMagicEffects().get(ESM::MagicEffect::Invisibility).getMagnitude());
}
float attackTerm = skillValue +
@ -437,7 +437,7 @@ namespace MWMechanics
x = std::min(100.f, x + elementResistance);
static const float fElementalShieldMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fElementalShieldMult")->getFloat();
static const float fElementalShieldMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fElementalShieldMult")->mValue.getFloat();
x = fElementalShieldMult * magnitude * (1.f - 0.01f * x);
// Note swapped victim and attacker, since the attacker takes the damage here.
@ -467,7 +467,7 @@ namespace MWMechanics
// weapon condition does not degrade when godmode is on
if (!godmode)
{
const float fWeaponDamageMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWeaponDamageMult")->getFloat();
const float fWeaponDamageMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fWeaponDamageMult")->mValue.getFloat();
float x = std::max(1.f, fWeaponDamageMult * damage);
weaphealth -= std::min(int(x), weaphealth);
@ -494,9 +494,9 @@ namespace MWMechanics
}
static const float fDamageStrengthBase = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fDamageStrengthBase")->getFloat();
.find("fDamageStrengthBase")->mValue.getFloat();
static const float fDamageStrengthMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fDamageStrengthMult")->getFloat();
.find("fDamageStrengthMult")->mValue.getFloat();
damage *= fDamageStrengthBase +
(attacker.getClass().getCreatureStats(attacker).getAttribute(ESM::Attribute::Strength).getModified() * fDamageStrengthMult * 0.1f);
}
@ -504,8 +504,8 @@ namespace MWMechanics
void getHandToHandDamage(const MWWorld::Ptr &attacker, const MWWorld::Ptr &victim, float &damage, bool &healthdmg, float attackStrength)
{
const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore();
float minstrike = store.get<ESM::GameSetting>().find("fMinHandToHandMult")->getFloat();
float maxstrike = store.get<ESM::GameSetting>().find("fMaxHandToHandMult")->getFloat();
float minstrike = store.get<ESM::GameSetting>().find("fMinHandToHandMult")->mValue.getFloat();
float maxstrike = store.get<ESM::GameSetting>().find("fMaxHandToHandMult")->mValue.getFloat();
damage = static_cast<float>(attacker.getClass().getSkill(attacker, ESM::Skill::HandToHand));
damage *= minstrike + ((maxstrike-minstrike)*attackStrength);
@ -530,7 +530,7 @@ namespace MWMechanics
damage *= MWBase::Environment::get().getWorld()->getGlobalFloat("werewolfclawmult");
}
if(healthdmg)
damage *= store.get<ESM::GameSetting>().find("fHandtoHandHealthPer")->getFloat();
damage *= store.get<ESM::GameSetting>().find("fHandtoHandHealthPer")->mValue.getFloat();
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
if(isWerewolf)
@ -547,9 +547,9 @@ namespace MWMechanics
{
// somewhat of a guess, but using the weapon weight makes sense
const MWWorld::Store<ESM::GameSetting>& store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
const float fFatigueAttackBase = store.find("fFatigueAttackBase")->getFloat();
const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat();
const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat();
const float fFatigueAttackBase = store.find("fFatigueAttackBase")->mValue.getFloat();
const float fFatigueAttackMult = store.find("fFatigueAttackMult")->mValue.getFloat();
const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->mValue.getFloat();
CreatureStats& stats = attacker.getClass().getCreatureStats(attacker);
MWMechanics::DynamicStat<float> fatigue = stats.getFatigue();
const float normalizedEncumbrance = attacker.getClass().getNormalizedEncumbrance(attacker);
@ -574,9 +574,9 @@ namespace MWMechanics
float d = (pos1 - pos2).length();
static const int iFightDistanceBase = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"iFightDistanceBase")->getInt();
"iFightDistanceBase")->mValue.getInteger();
static const float fFightDistanceMultiplier = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fFightDistanceMultiplier")->getFloat();
"fFightDistanceMultiplier")->mValue.getFloat();
return (iFightDistanceBase - fFightDistanceMultiplier * d);
}

@ -59,8 +59,8 @@ namespace MWMechanics
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fFatigueBase = gmst.find("fFatigueBase")->getFloat();
static const float fFatigueMult = gmst.find("fFatigueMult")->getFloat();
static const float fFatigueBase = gmst.find("fFatigueBase")->mValue.getFloat();
static const float fFatigueMult = gmst.find("fFatigueMult")->mValue.getFloat();
return fFatigueBase - fFatigueMult * (1-normalised);
}

@ -38,7 +38,7 @@ float scaleDamage(float damage, const MWWorld::Ptr& attacker, const MWWorld::Ptr
End of tes3mp change (major)
*/
static const float fDifficultyMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDifficultyMult")->getFloat();
static const float fDifficultyMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDifficultyMult")->mValue.getFloat();
float difficultyTerm = 0.01f * difficultySetting;

@ -28,7 +28,7 @@ namespace MWMechanics
float fDiseaseXferChance =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fDiseaseXferChance")->getFloat();
"fDiseaseXferChance")->mValue.getFloat();
MagicEffects& actorEffects = actor.getClass().getCreatureStats(actor).getMagicEffects();
@ -59,7 +59,7 @@ namespace MWMechanics
actor.getClass().getCreatureStats(actor).getSpells().add(it->first);
std::string msg = "sMagicContractDisease";
msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->getString();
msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->mValue.getString();
if (msg.find("%s") != std::string::npos)
msg.replace(msg.find("%s"), 2, spell->mName);
MWBase::Environment::get().getWindowManager()->messageBox(msg);

@ -136,7 +136,7 @@ namespace MWMechanics
}
const bool powerfulSoul = getGemCharge() >= \
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("iSoulAmountForConstantEffect")->getInt();
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("iSoulAmountForConstantEffect")->mValue.getInteger();
if ((mObjectType == typeid(ESM::Armor).name()) || (mObjectType == typeid(ESM::Clothing).name()))
{ // Armor or Clothing
switch(mCastStyle)
@ -213,7 +213,7 @@ namespace MWMechanics
float magnitudeCost = (magMin + magMax) * baseCost * 0.05f;
if (mCastStyle == ESM::Enchantment::ConstantEffect)
{
magnitudeCost *= store.get<ESM::GameSetting>().find("fEnchantmentConstantDurationMult")->getFloat();
magnitudeCost *= store.get<ESM::GameSetting>().find("fEnchantmentConstantDurationMult")->mValue.getFloat();
}
else
{
@ -222,7 +222,7 @@ namespace MWMechanics
float areaCost = area * 0.05f * baseCost;
const float fEffectCostMult = store.get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
const float fEffectCostMult = store.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
cost += (magnitudeCost + areaCost) * fEffectCostMult;
@ -259,7 +259,7 @@ namespace MWMechanics
if(mEnchanter.isEmpty())
return 0;
float priceMultipler = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fEnchantmentValueMult")->getFloat();
float priceMultipler = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find ("fEnchantmentValueMult")->mValue.getFloat();
int price = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mEnchanter, static_cast<int>(getEnchantPoints() * priceMultipler), true);
return price;
}
@ -285,7 +285,7 @@ namespace MWMechanics
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
return static_cast<int>(mOldItemPtr.getClass().getEnchantmentPoints(mOldItemPtr) * store.get<ESM::GameSetting>().find("fEnchantmentMult")->getFloat());
return static_cast<int>(mOldItemPtr.getClass().getEnchantmentPoints(mOldItemPtr) * store.get<ESM::GameSetting>().find("fEnchantmentMult")->mValue.getFloat());
}
bool Enchanting::soulEmpty() const
{
@ -317,8 +317,8 @@ namespace MWMechanics
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
float chance2 = 7.5f / (gmst.find("fEnchantmentChanceMult")->getFloat() * ((mCastStyle == ESM::Enchantment::ConstantEffect) ?
gmst.find("fEnchantmentConstantChanceMult")->getFloat() : 1.0f ))
float chance2 = 7.5f / (gmst.find("fEnchantmentChanceMult")->mValue.getFloat() * ((mCastStyle == ESM::Enchantment::ConstantEffect) ?
gmst.find("fEnchantmentConstantChanceMult")->mValue.getFloat() : 1.0f ))
* getEnchantPoints();
return (chance1-chance2);

@ -49,7 +49,7 @@ namespace
float getFightDispositionBias(float disposition)
{
static const float fFightDispMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fFightDispMult")->getFloat();
"fFightDispMult")->mValue.getFloat();
return ((50.f - disposition) * fFightDispMult);
}
@ -58,11 +58,11 @@ namespace
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
float persTerm = stats.getAttribute(ESM::Attribute::Personality).getModified() / gmst.find("fPersonalityMod")->getFloat();
float luckTerm = stats.getAttribute(ESM::Attribute::Luck).getModified() / gmst.find("fLuckMod")->getFloat();
float repTerm = stats.getReputation() * gmst.find("fReputationMod")->getFloat();
float persTerm = stats.getAttribute(ESM::Attribute::Personality).getModified() / gmst.find("fPersonalityMod")->mValue.getFloat();
float luckTerm = stats.getAttribute(ESM::Attribute::Luck).getModified() / gmst.find("fLuckMod")->mValue.getFloat();
float repTerm = stats.getReputation() * gmst.find("fReputationMod")->mValue.getFloat();
float fatigueTerm = stats.getFatigueTerm();
float levelTerm = stats.getLevel() * gmst.find("fLevelMod")->getFloat();
float levelTerm = stats.getLevel() * gmst.find("fLevelMod")->mValue.getFloat();
rating1 = (repTerm + luckTerm + persTerm + stats.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm;
@ -355,7 +355,7 @@ namespace MWMechanics
if(timeToDrown != mWatchedTimeToStartDrowning)
{
static const float fHoldBreathTime = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fHoldBreathTime")->getFloat();
.find("fHoldBreathTime")->mValue.getFloat();
mWatchedTimeToStartDrowning = timeToDrown;
@ -556,12 +556,12 @@ namespace MWMechanics
const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr);
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fDispRaceMod = gmst.find("fDispRaceMod")->getFloat();
static const float fDispRaceMod = gmst.find("fDispRaceMod")->mValue.getFloat();
if (Misc::StringUtils::ciEqual(npc->mBase->mRace, player->mBase->mRace))
x += fDispRaceMod;
static const float fDispPersonalityMult = gmst.find("fDispPersonalityMult")->getFloat();
static const float fDispPersonalityBase = gmst.find("fDispPersonalityBase")->getFloat();
static const float fDispPersonalityMult = gmst.find("fDispPersonalityMult")->mValue.getFloat();
static const float fDispPersonalityBase = gmst.find("fDispPersonalityBase")->mValue.getFloat();
x += fDispPersonalityMult * (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - fDispPersonalityBase);
float reaction = 0;
@ -605,20 +605,20 @@ namespace MWMechanics
rank = 0;
}
static const float fDispFactionRankMult = gmst.find("fDispFactionRankMult")->getFloat();
static const float fDispFactionRankBase = gmst.find("fDispFactionRankBase")->getFloat();
static const float fDispFactionMod = gmst.find("fDispFactionMod")->getFloat();
static const float fDispFactionRankMult = gmst.find("fDispFactionRankMult")->mValue.getFloat();
static const float fDispFactionRankBase = gmst.find("fDispFactionRankBase")->mValue.getFloat();
static const float fDispFactionMod = gmst.find("fDispFactionMod")->mValue.getFloat();
x += (fDispFactionRankMult * rank
+ fDispFactionRankBase)
* fDispFactionMod * reaction;
static const float fDispCrimeMod = gmst.find("fDispCrimeMod")->getFloat();
static const float fDispDiseaseMod = gmst.find("fDispDiseaseMod")->getFloat();
static const float fDispCrimeMod = gmst.find("fDispCrimeMod")->mValue.getFloat();
static const float fDispDiseaseMod = gmst.find("fDispDiseaseMod")->mValue.getFloat();
x -= fDispCrimeMod * playerStats.getBounty();
if (playerStats.hasCommonDisease() || playerStats.hasBlightDisease())
x += fDispDiseaseMod;
static const float fDispWeaponDrawn = gmst.find("fDispWeaponDrawn")->getFloat();
static const float fDispWeaponDrawn = gmst.find("fDispWeaponDrawn")->mValue.getFloat();
if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon)
x += fDispWeaponDrawn;
@ -699,16 +699,16 @@ namespace MWMechanics
float target2 = d * (playerRating2 - npcRating2 + 50);
float bribeMod;
if (type == PT_Bribe10) bribeMod = gmst.find("fBribe10Mod")->getFloat();
else if (type == PT_Bribe100) bribeMod = gmst.find("fBribe100Mod")->getFloat();
else bribeMod = gmst.find("fBribe1000Mod")->getFloat();
if (type == PT_Bribe10) bribeMod = gmst.find("fBribe10Mod")->mValue.getFloat();
else if (type == PT_Bribe100) bribeMod = gmst.find("fBribe100Mod")->mValue.getFloat();
else bribeMod = gmst.find("fBribe1000Mod")->mValue.getFloat();
float target3 = d * (playerRating3 - npcRating3 + 50) + bribeMod;
float iPerMinChance = floor(gmst.find("iPerMinChance")->getFloat());
float iPerMinChange = floor(gmst.find("iPerMinChange")->getFloat());
float fPerDieRollMult = gmst.find("fPerDieRollMult")->getFloat();
float fPerTempMult = gmst.find("fPerTempMult")->getFloat();
float iPerMinChance = floor(gmst.find("iPerMinChance")->mValue.getFloat());
float iPerMinChange = floor(gmst.find("iPerMinChange")->mValue.getFloat());
float fPerDieRollMult = gmst.find("fPerDieRollMult")->mValue.getFloat();
float fPerTempMult = gmst.find("fPerTempMult")->mValue.getFloat();
float x = 0;
float y = 0;
@ -911,7 +911,7 @@ namespace MWMechanics
continue;
// All sMagicBound* GMST's should be of type string
std::string currentGMSTValue = currentSetting.getString();
std::string currentGMSTValue = currentSetting.mValue.getString();
Misc::StringUtils::lowerCaseInPlace(currentGMSTValue);
boundItemIDCache.insert(currentGMSTValue);
@ -1225,7 +1225,7 @@ namespace MWMechanics
osg::Vec3f from (player.getRefData().getPosition().asVec3());
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getFloat();
float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->mValue.getFloat();
mActors.getObjectsInRange(from, radius, neighbors);
@ -1334,29 +1334,29 @@ namespace MWMechanics
float disp = 0.f, dispVictim = 0.f;
if (type == OT_Trespassing || type == OT_SleepingInOwnedBed)
{
arg = store.find("iCrimeTresspass")->getInt();
disp = dispVictim = store.find("iDispTresspass")->getFloat();
arg = store.find("iCrimeTresspass")->mValue.getInteger();
disp = dispVictim = store.find("iDispTresspass")->mValue.getFloat();
}
else if (type == OT_Pickpocket)
{
arg = store.find("iCrimePickPocket")->getInt();
disp = dispVictim = store.find("fDispPickPocketMod")->getFloat();
arg = store.find("iCrimePickPocket")->mValue.getInteger();
disp = dispVictim = store.find("fDispPickPocketMod")->mValue.getFloat();
}
else if (type == OT_Assault)
{
arg = store.find("iCrimeAttack")->getInt();
disp = store.find("iDispAttackMod")->getFloat();
dispVictim = store.find("fDispAttacking")->getFloat();
arg = store.find("iCrimeAttack")->mValue.getInteger();
disp = store.find("iDispAttackMod")->mValue.getFloat();
dispVictim = store.find("fDispAttacking")->mValue.getFloat();
}
else if (type == OT_Murder)
{
arg = store.find("iCrimeKilling")->getInt();
disp = dispVictim = store.find("iDispKilling")->getFloat();
arg = store.find("iCrimeKilling")->mValue.getInteger();
disp = dispVictim = store.find("iDispKilling")->mValue.getFloat();
}
else if (type == OT_Theft)
{
disp = dispVictim = store.find("fDispStealing")->getFloat() * arg;
arg = static_cast<int>(arg * store.find("fCrimeStealing")->getFloat());
disp = dispVictim = store.find("fDispStealing")->mValue.getFloat() * arg;
arg = static_cast<int>(arg * store.find("fCrimeStealing")->mValue.getFloat());
arg = std::max(1, arg); // Minimum bounty of 1, in case items with zero value are stolen
}
@ -1366,7 +1366,7 @@ namespace MWMechanics
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
osg::Vec3f from (player.getRefData().getPosition().asVec3());
float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->getFloat();
float radius = esmStore.get<ESM::GameSetting>().find("fAlarmRadius")->mValue.getFloat();
mActors.getObjectsInRange(from, radius, neighbors);
@ -1380,21 +1380,21 @@ namespace MWMechanics
// Controls whether witnesses will engage combat with the criminal.
int fight = 0, fightVictim = 0;
if (type == OT_Trespassing || type == OT_SleepingInOwnedBed)
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("iFightTrespass")->getInt();
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("iFightTrespass")->mValue.getInteger();
else if (type == OT_Pickpocket)
{
fight = esmStore.get<ESM::GameSetting>().find("iFightPickpocket")->getInt();
fightVictim = esmStore.get<ESM::GameSetting>().find("iFightPickpocket")->getInt() * 4; // *4 according to research wiki
fight = esmStore.get<ESM::GameSetting>().find("iFightPickpocket")->mValue.getInteger();
fightVictim = esmStore.get<ESM::GameSetting>().find("iFightPickpocket")->mValue.getInteger() * 4; // *4 according to research wiki
}
else if (type == OT_Assault)
{
fight = esmStore.get<ESM::GameSetting>().find("iFightAttacking")->getInt();
fightVictim = esmStore.get<ESM::GameSetting>().find("iFightAttack")->getInt();
fight = esmStore.get<ESM::GameSetting>().find("iFightAttacking")->mValue.getInteger();
fightVictim = esmStore.get<ESM::GameSetting>().find("iFightAttack")->mValue.getInteger();
}
else if (type == OT_Murder)
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("iFightKilling")->getInt();
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("iFightKilling")->mValue.getInteger();
else if (type == OT_Theft)
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("fFightStealing")->getInt();
fight = fightVictim = esmStore.get<ESM::GameSetting>().find("fFightStealing")->mValue.getInteger();
bool reported = false;
@ -1645,8 +1645,8 @@ namespace MWMechanics
&& !MWBase::Environment::get().getWorld()->isSwimming(ptr)
&& MWBase::Environment::get().getWorld()->isOnGround(ptr))
{
static float fSneakSkillMult = store.find("fSneakSkillMult")->getFloat();
static float fSneakBootMult = store.find("fSneakBootMult")->getFloat();
static float fSneakSkillMult = store.find("fSneakSkillMult")->mValue.getFloat();
static float fSneakBootMult = store.find("fSneakBootMult")->mValue.getFloat();
float sneak = static_cast<float>(ptr.getClass().getSkill(ptr, ESM::Skill::Sneak));
int agility = stats.getAttribute(ESM::Attribute::Agility).getModified();
int luck = stats.getAttribute(ESM::Attribute::Luck).getModified();
@ -1661,8 +1661,8 @@ namespace MWMechanics
sneakTerm = fSneakSkillMult * sneak + 0.2f * agility + 0.1f * luck + bootWeight * fSneakBootMult;
}
static float fSneakDistBase = store.find("fSneakDistanceBase")->getFloat();
static float fSneakDistMult = store.find("fSneakDistanceMultiplier")->getFloat();
static float fSneakDistBase = store.find("fSneakDistanceBase")->mValue.getFloat();
static float fSneakDistMult = store.find("fSneakDistanceMultiplier")->mValue.getFloat();
osg::Vec3f pos1 (ptr.getRefData().getPosition().asVec3());
osg::Vec3f pos2 (observer.getRefData().getPosition().asVec3());
@ -1680,8 +1680,8 @@ namespace MWMechanics
float obsTerm = obsSneak + 0.2f * obsAgility + 0.1f * obsLuck - obsBlind;
// is ptr behind the observer?
static float fSneakNoViewMult = store.find("fSneakNoViewMult")->getFloat();
static float fSneakViewMult = store.find("fSneakViewMult")->getFloat();
static float fSneakNoViewMult = store.find("fSneakNoViewMult")->mValue.getFloat();
static float fSneakViewMult = store.find("fSneakViewMult")->mValue.getFloat();
float y = 0;
osg::Vec3f vec = pos1 - pos2;
if (observer.getRefData().getBaseNode())
@ -1841,7 +1841,7 @@ namespace MWMechanics
MWBase::Environment::get().getWorld()->getGlobalInt("pcknownwerewolf")))
{
const ESM::GameSetting * iWerewolfFightMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iWerewolfFightMod");
fight += iWerewolfFightMod->getInt();
fight += iWerewolfFightMod->mValue.getInteger();
}
}
@ -1934,7 +1934,7 @@ namespace MWMechanics
// Witnesses of the player's transformation will make them a globally known werewolf
std::vector<MWWorld::Ptr> closeActors;
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
getActorsInRange(actor.getRefData().getPosition().asVec3(), gmst.find("fAlarmRadius")->getFloat(), closeActors);
getActorsInRange(actor.getRefData().getPosition().asVec3(), gmst.find("fAlarmRadius")->mValue.getFloat(), closeActors);
bool detected = false, reported = false;
for (std::vector<MWWorld::Ptr>::const_iterator it = closeActors.begin(); it != closeActors.end(); ++it)
@ -1959,7 +1959,7 @@ namespace MWMechanics
if (reported)
{
npcStats.setBounty(npcStats.getBounty()+
gmst.find("iWereWolfBounty")->getInt());
gmst.find("iWereWolfBounty")->mValue.getInteger());
windowManager->messageBox("#{sCrimeMessage}");
}
}
@ -1971,7 +1971,7 @@ namespace MWMechanics
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWMechanics::NpcStats &stats = actor.getClass().getNpcStats(actor);
stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->getInt());
stats.getSkill(ESM::Skill::Acrobatics).setBase(gmst.find("fWerewolfAcrobatics")->mValue.getInteger());
}
void MechanicsManager::cleanupSummonedCreature(const MWWorld::Ptr &caster, int creatureActorId)

@ -149,12 +149,12 @@ float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
float typeFactor = gmst.find ("fMiscSkillBonus")->getFloat();
float typeFactor = gmst.find ("fMiscSkillBonus")->mValue.getFloat();
for (int i=0; i<5; ++i)
if (class_.mData.mSkills[i][0]==skillIndex)
{
typeFactor = gmst.find ("fMinorSkillBonus")->getFloat();
typeFactor = gmst.find ("fMinorSkillBonus")->mValue.getFloat();
break;
}
@ -162,7 +162,7 @@ float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const
for (int i=0; i<5; ++i)
if (class_.mData.mSkills[i][1]==skillIndex)
{
typeFactor = gmst.find ("fMajorSkillBonus")->getFloat();
typeFactor = gmst.find ("fMajorSkillBonus")->mValue.getFloat();
break;
}
@ -178,7 +178,7 @@ float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const
MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find (skillIndex);
if (skill->mData.mSpecialization==class_.mData.mSpecialization)
{
specialisationFactor = gmst.find ("fSpecialSkillBonus")->getFloat();
specialisationFactor = gmst.find ("fSpecialSkillBonus")->mValue.getFloat();
if (specialisationFactor<=0)
throw std::runtime_error ("invalid skill specialisation factor");
@ -227,21 +227,21 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
// is this a minor or major skill?
int increase = gmst.find("iLevelupMiscMultAttriubte")->getInt(); // Note: GMST has a typo
int increase = gmst.find("iLevelupMiscMultAttriubte")->mValue.getInteger(); // Note: GMST has a typo
for (int k=0; k<5; ++k)
{
if (class_.mData.mSkills[k][0] == skillIndex)
{
mLevelProgress += gmst.find("iLevelUpMinorMult")->getInt();
increase = gmst.find("iLevelUpMajorMultAttribute")->getInt();
mLevelProgress += gmst.find("iLevelUpMinorMult")->mValue.getInteger();
increase = gmst.find("iLevelUpMajorMultAttribute")->mValue.getInteger();
}
}
for (int k=0; k<5; ++k)
{
if (class_.mData.mSkills[k][1] == skillIndex)
{
mLevelProgress += gmst.find("iLevelUpMajorMult")->getInt();
increase = gmst.find("iLevelUpMinorMultAttribute")->getInt();
mLevelProgress += gmst.find("iLevelUpMajorMult")->mValue.getInteger();
increase = gmst.find("iLevelUpMinorMultAttribute")->mValue.getInteger();
}
}
@ -249,7 +249,7 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
MWBase::Environment::get().getWorld ()->getStore ().get<ESM::Skill>().find(skillIndex);
mSkillIncreases[skill->mData.mAttribute] += increase;
mSpecIncreases[skill->mData.mSpecialization] += gmst.find("iLevelupSpecialization")->getInt();
mSpecIncreases[skill->mData.mSpecialization] += gmst.find("iLevelupSpecialization")->mValue.getInteger();
// Play sound & skill progress notification
/// \todo check if character is the player, if levelling is ever implemented for NPCs
@ -266,7 +266,7 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never);
if (mLevelProgress >= gmst.find("iLevelUpTotal")->getInt())
if (mLevelProgress >= gmst.find("iLevelUpTotal")->mValue.getInteger())
{
// levelup is possible now
MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}", MWGui::ShowInDialogueMode_Never);
@ -348,7 +348,7 @@ void MWMechanics::NpcStats::levelUp()
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
mLevelProgress -= gmst.find("iLevelUpTotal")->getInt();
mLevelProgress -= gmst.find("iLevelUpTotal")->mValue.getInteger();
mLevelProgress = std::max(0, mLevelProgress); // might be necessary when levelup was invoked via console
for (int i=0; i<ESM::Attribute::Length; ++i)
@ -359,7 +359,7 @@ void MWMechanics::NpcStats::levelUp()
// "When you gain a level, in addition to increasing three primary attributes, your Health
// will automatically increase by 10% of your Endurance attribute. If you increased Endurance this level,
// the Health increase is calculated from the increased Endurance"
setHealth(getHealth().getBase() + endurance * gmst.find("fLevelUpHealthEndMult")->getFloat());
setHealth(getHealth().getBase() + endurance * gmst.find("fLevelUpHealthEndMult")->mValue.getFloat());
setLevel(getLevel()+1);
}
@ -385,7 +385,7 @@ int MWMechanics::NpcStats::getLevelupAttributeMultiplier(int attribute) const
std::stringstream gmst;
gmst << "iLevelUp" << std::setfill('0') << std::setw(2) << num << "Mult";
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(gmst.str())->getInt();
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(gmst.str())->mValue.getInteger();
}
int MWMechanics::NpcStats::getSkillIncreasesForSpecialization(int spec) const

@ -37,9 +37,9 @@ namespace MWMechanics
float pcSneak = static_cast<float>(mThief.getClass().getSkill(mThief, ESM::Skill::Sneak));
int iPickMinChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iPickMinChance")->getInt();
.find("iPickMinChance")->mValue.getInteger();
int iPickMaxChance = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("iPickMaxChance")->getInt();
.find("iPickMaxChance")->mValue.getInteger();
int roll = Misc::Rng::roll0to99();
if (t < pcSneak / iPickMinChance)
@ -57,7 +57,7 @@ namespace MWMechanics
{
float stackValue = static_cast<float>(item.getClass().getValue(item) * count);
float fPickPocketMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fPickPocketMod")->getFloat();
.find("fPickPocketMod")->mValue.getFloat();
float valueTerm = 10 * fPickPocketMod * stackValue;
return getDetected(valueTerm);

@ -55,7 +55,7 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
int armorerSkill = npcStats.getSkill(ESM::Skill::Armorer).getModified();
float fRepairAmountMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fRepairAmountMult")->getFloat();
.find("fRepairAmountMult")->mValue.getFloat();
float toolQuality = ref->mBase->mData.mQuality;
@ -117,7 +117,7 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
store.remove(mTool, 1, player);
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sNotifyMessage51")->getString();
.find("sNotifyMessage51")->mValue.getString();
MWBase::Environment::get().getWindowManager()->messageBox((boost::format(message) % mTool.getClass().getName(mTool)).str());

@ -54,7 +54,7 @@ namespace MWMechanics
float pickQuality = lockpick.get<ESM::Lockpick>()->mBase->mData.mQuality;
float fPickLockMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPickLockMult")->getFloat();
float fPickLockMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fPickLockMult")->mValue.getFloat();
float x = 0.2f * mAgility + 0.1f * mLuck + mSecuritySkill;
x *= pickQuality * mFatigueTerm;
@ -119,7 +119,7 @@ namespace MWMechanics
const ESM::Spell* trapSpell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(trap.getCellRef().getTrap());
int trapSpellPoints = trapSpell->mData.mCost;
float fTrapCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTrapCostMult")->getFloat();
float fTrapCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fTrapCostMult")->mValue.getFloat();
float x = 0.2f * mAgility + 0.1f * mLuck + mSecuritySkill;
x += fTrapCostMult * trapSpellPoints;

@ -51,13 +51,17 @@ namespace MWMechanics
{
ESM::Skill::SkillEnum spellSchoolToSkill(int school)
{
std::map<int, ESM::Skill::SkillEnum> schoolSkillMap; // maps spell school to skill id
schoolSkillMap[0] = ESM::Skill::Alteration;
schoolSkillMap[1] = ESM::Skill::Conjuration;
schoolSkillMap[3] = ESM::Skill::Illusion;
schoolSkillMap[2] = ESM::Skill::Destruction;
schoolSkillMap[4] = ESM::Skill::Mysticism;
schoolSkillMap[5] = ESM::Skill::Restoration;
static std::map<int, ESM::Skill::SkillEnum> schoolSkillMap; // maps spell school to skill id
if (schoolSkillMap.empty())
{
schoolSkillMap[0] = ESM::Skill::Alteration;
schoolSkillMap[1] = ESM::Skill::Conjuration;
schoolSkillMap[3] = ESM::Skill::Illusion;
schoolSkillMap[2] = ESM::Skill::Destruction;
schoolSkillMap[4] = ESM::Skill::Mysticism;
schoolSkillMap[5] = ESM::Skill::Restoration;
}
assert(schoolSkillMap.find(school) != schoolSkillMap.end());
return schoolSkillMap[school];
}
@ -65,7 +69,11 @@ namespace MWMechanics
float calcEffectCost(const ESM::ENAMstruct& effect)
{
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
return calcEffectCost(effect, magicEffect);
}
float calcEffectCost(const ESM::ENAMstruct& effect, const ESM::MagicEffect* magicEffect)
{
int minMagn = 1;
int maxMagn = 1;
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoMagnitude))
@ -79,7 +87,7 @@ namespace MWMechanics
duration = effect.mDuration;
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore()
.get<ESM::GameSetting>().find("fEffectCostMult")->getFloat();
.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
float x = 0.5 * (std::max(1, minMagn) + std::max(1, maxMagn));
x *= 0.1 * magicEffect->mData.mBaseCost;
@ -110,7 +118,7 @@ namespace MWMechanics
if (it->mRange == ESM::RT_Target)
x *= 1.5f;
static const float fEffectCostMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fEffectCostMult")->getFloat();
"fEffectCostMult")->mValue.getFloat();
x *= fEffectCostMult;
float s = 2.0f * actor.getClass().getSkill(actor, spellSchoolToSkill(magicEffect->mData.mSchool));
@ -996,8 +1004,8 @@ namespace MWMechanics
if (!godmode)
{
// Reduce fatigue (note that in the vanilla game, both GMSTs are 0, and there's no fatigue loss)
static const float fFatigueSpellBase = store.get<ESM::GameSetting>().find("fFatigueSpellBase")->getFloat();
static const float fFatigueSpellMult = store.get<ESM::GameSetting>().find("fFatigueSpellMult")->getFloat();
static const float fFatigueSpellBase = store.get<ESM::GameSetting>().find("fFatigueSpellBase")->mValue.getFloat();
static const float fFatigueSpellMult = store.get<ESM::GameSetting>().find("fFatigueSpellMult")->mValue.getFloat();
DynamicStat<float> fatigue = stats.getFatigue();
const float normalizedEncumbrance = mCaster.getClass().getNormalizedEncumbrance(mCaster);
@ -1098,7 +1106,7 @@ namespace MWMechanics
if (roll > x)
{
// "X has no effect on you"
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage50")->getString();
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage50")->mValue.getString();
message = boost::str(boost::format(message) % ingredient->mName);
MWBase::Environment::get().getWindowManager()->messageBox(message);
return false;
@ -1381,7 +1389,7 @@ namespace MWMechanics
float damageScale = 1.f - timeDiff / 7.f;
// When cloudy, the sun damage effect is halved
static float fMagicSunBlockedMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fMagicSunBlockedMult")->getFloat();
"fMagicSunBlockedMult")->mValue.getFloat();
int weather = MWBase::Environment::get().getWorld()->getCurrentWeather();
if (weather > 1)
@ -1494,7 +1502,7 @@ namespace MWMechanics
if (it == summonMap.end())
return std::string();
else
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->getString();
return MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(it->second)->mValue.getString();
}
void ApplyLoopingParticlesVisitor::visit (MWMechanics::EffectKey key,

@ -3,6 +3,7 @@
#include <components/esm/effectlist.hpp>
#include <components/esm/loadskil.hpp>
#include <components/esm/loadmgef.hpp>
#include "../mwworld/ptr.hpp"
@ -25,6 +26,7 @@ namespace MWMechanics
ESM::Skill::SkillEnum spellSchoolToSkill(int school);
float calcEffectCost(const ESM::ENAMstruct& effect);
float calcEffectCost(const ESM::ENAMstruct& effect, const ESM::MagicEffect* magicEffect);
bool isSummoningEffect(int effectId);

@ -515,8 +515,6 @@ namespace MWMechanics
return 0.f;
}
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
// Underwater casting not possible
if (effect.mRange == ESM::RT_Target)
{
@ -530,6 +528,7 @@ namespace MWMechanics
return 0.f;
}
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(effect.mEffectID);
if (magicEffect->mData.mFlags & ESM::MagicEffect::Harmful)
{
rating *= -1.f;
@ -565,7 +564,7 @@ namespace MWMechanics
}
}
rating *= calcEffectCost(effect);
rating *= calcEffectCost(effect, magicEffect);
// Currently treating all "on target" or "on touch" effects to target the enemy actor.
// Combat AI is egoistic, so doesn't consider applying positive effects to friendly actors.
@ -593,8 +592,8 @@ namespace MWMechanics
{
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fAIMagicSpellMult = gmst.find("fAIMagicSpellMult")->getFloat();
static const float fAIRangeMagicSpellMult = gmst.find("fAIRangeMagicSpellMult")->getFloat();
static const float fAIMagicSpellMult = gmst.find("fAIMagicSpellMult")->mValue.getFloat();
static const float fAIRangeMagicSpellMult = gmst.find("fAIRangeMagicSpellMult")->mValue.getFloat();
float mult = fAIMagicSpellMult;

@ -279,6 +279,25 @@ namespace MWMechanics
}
}
void Spells::removeEffects(const std::string &id)
{
if (isSpellActive(id))
{
for (TContainer::iterator spell = mSpells.begin(); spell != mSpells.end(); ++spell)
{
if (spell->first == getSpell(id))
{
for (long unsigned int i = 0; i != spell->first->mEffects.mList.size(); i++)
{
spell->second.mPurgedEffects.insert(i);
}
}
}
mSpellsChanged = true;
}
}
void Spells::visitEffectSources(EffectSourceVisitor &visitor) const
{
if (mSpellsChanged) {

@ -124,6 +124,8 @@ namespace MWMechanics
bool hasBlightDisease() const;
void removeEffects(const std::string& id);
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor) const;
void readState (const ESM::SpellState& state);

@ -50,11 +50,11 @@ namespace MWMechanics
float e1 = 0.1f * merchantStats.getAttribute(ESM::Attribute::Luck).getModified();
float f1 = 0.2f * merchantStats.getAttribute(ESM::Attribute::Personality).getModified();
float dispositionTerm = gmst.find("fDispositionMod")->getFloat() * (clampedDisposition - 50);
float dispositionTerm = gmst.find("fDispositionMod")->mValue.getFloat() * (clampedDisposition - 50);
float pcTerm = (dispositionTerm + a1 + b1 + c1) * playerStats.getFatigueTerm();
float npcTerm = (d1 + e1 + f1) * merchantStats.getFatigueTerm();
float x = gmst.find("fBargainOfferMulti")->getFloat() * d
+ gmst.find("fBargainOfferBase")->getFloat()
float x = gmst.find("fBargainOfferMulti")->mValue.getFloat() * d
+ gmst.find("fBargainOfferBase")->mValue.getFloat()
+ int(pcTerm - npcTerm);
int roll = Misc::Rng::rollDice(100) + 1;

@ -29,6 +29,9 @@ namespace MWMechanics
if (type != -1 && weapon->mData.mType != type)
return 0.f;
if (type == -1 && (weapon->mData.mType == ESM::Weapon::Arrow || weapon->mData.mType == ESM::Weapon::Bolt))
return 0.f;
float rating=0.f;
float rangedMult=1.f;
@ -108,11 +111,19 @@ namespace MWMechanics
}
}
int skill = item.getClass().getEquipmentSkill(item);
if (skill != -1)
if (actor.getClass().isNpc())
{
int skill = item.getClass().getEquipmentSkill(item);
if (skill != -1)
{
int value = actor.getClass().getSkill(actor, skill);
rating *= MWMechanics::getHitChance(actor, enemy, value) / 100.f;
}
}
else
{
int value = actor.getClass().getSkill(actor, skill);
rating *= MWMechanics::getHitChance(actor, enemy, value) / 100.f;
MWWorld::LiveCellRef<ESM::Creature> *ref = actor.get<ESM::Creature>();
rating *= MWMechanics::getHitChance(actor, enemy, ref->mBase->mData.mCombat) / 100.f;
}
return rating * rangedMult;
@ -149,9 +160,9 @@ namespace MWMechanics
{
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fAIMeleeWeaponMult = gmst.find("fAIMeleeWeaponMult")->getFloat();
static const float fAIMeleeArmorMult = gmst.find("fAIMeleeArmorMult")->getFloat();
static const float fAIRangeMeleeWeaponMult = gmst.find("fAIRangeMeleeWeaponMult")->getFloat();
static const float fAIMeleeWeaponMult = gmst.find("fAIMeleeWeaponMult")->mValue.getFloat();
static const float fAIMeleeArmorMult = gmst.find("fAIMeleeArmorMult")->mValue.getFloat();
static const float fAIRangeMeleeWeaponMult = gmst.find("fAIRangeMeleeWeaponMult")->mValue.getFloat();
if (weapon.isEmpty())
return 0.f;

@ -303,7 +303,7 @@ namespace MWPhysics
position.z() += halfExtents.z();
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fSwimHeightScale")->getFloat();
.find("fSwimHeightScale")->mValue.getFloat();
float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
ActorTracer tracer;
@ -339,7 +339,7 @@ namespace MWPhysics
osg::Vec3f stormDirection = MWBase::Environment::get().getWorld()->getStormDirection();
float angleDegrees = osg::RadiansToDegrees(std::acos(stormDirection * velocity / (stormDirection.length() * velocity.length())));
static const float fStromWalkMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fStromWalkMult")->getFloat();
.find("fStromWalkMult")->mValue.getFloat();
velocity *= 1.f-(fStromWalkMult * (angleDegrees/180.f));
}
@ -650,7 +650,6 @@ namespace MWPhysics
osg::NodePath& nodePath = nodePathFound->second;
osg::Matrixf matrix = osg::computeLocalToWorld(nodePath);
osg::Vec3f scale = matrix.getScale();
matrix.orthoNormalize(matrix);
btTransform transform;
@ -659,8 +658,8 @@ namespace MWPhysics
for (int j=0; j<3; ++j)
transform.getBasis()[i][j] = matrix(j,i); // NB column/row major difference
if (compound->getLocalScaling() * toBullet(scale) != compound->getChildShape(shapeIndex)->getLocalScaling())
compound->getChildShape(shapeIndex)->setLocalScaling(compound->getLocalScaling() * toBullet(scale));
// Note: we can not apply scaling here for now since we treat scaled shapes
// as new shapes (btScaledBvhTriangleMeshShape) with 1.0 scale for now
if (!(transform == compound->getChildTransform(shapeIndex)))
compound->updateChildTransform(shapeIndex, transform);
}
@ -883,8 +882,8 @@ namespace MWPhysics
// Use cone shape as fallback
const MWWorld::Store<ESM::GameSetting> &store = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
btConeShape shape (osg::DegreesToRadians(store.find("fCombatAngleXY")->getFloat()/2.0f), queryDistance);
shape.setLocalScaling(btVector3(1, 1, osg::DegreesToRadians(store.find("fCombatAngleZ")->getFloat()/2.0f) /
btConeShape shape (osg::DegreesToRadians(store.find("fCombatAngleXY")->mValue.getFloat()/2.0f), queryDistance);
shape.setLocalScaling(btVector3(1, 1, osg::DegreesToRadians(store.find("fCombatAngleZ")->mValue.getFloat()/2.0f) /
shape.getRadius()));
// The shape origin is its center, so we have to move it forward by half the length. The

@ -208,8 +208,11 @@ namespace
class RemoveFinishedCallbackVisitor : public RemoveVisitor
{
public:
bool mHasMagicEffects;
RemoveFinishedCallbackVisitor()
: RemoveVisitor()
, mHasMagicEffects(false)
, mEffectId(-1)
{
}
@ -234,11 +237,14 @@ namespace
{
// We should remove empty transformation nodes and finished callbacks here
MWRender::UpdateVfxCallback* vfxCallback = dynamic_cast<MWRender::UpdateVfxCallback*>(callback);
bool finished = vfxCallback && vfxCallback->mFinished;
bool toRemove = vfxCallback && mEffectId >= 0 && vfxCallback->mParams.mEffectId == mEffectId;
if (finished || toRemove)
if (vfxCallback)
{
mToRemove.push_back(std::make_pair(group.asNode(), group.getParent(0)));
bool finished = vfxCallback->mFinished;
bool toRemove = mEffectId >= 0 && vfxCallback->mParams.mEffectId == mEffectId;
if (finished || toRemove)
mToRemove.push_back(std::make_pair(group.asNode(), group.getParent(0)));
else
mHasMagicEffects = true;
}
}
}
@ -610,6 +616,7 @@ namespace MWRender
, mTextKeyListener(NULL)
, mHeadYawRadians(0.f)
, mHeadPitchRadians(0.f)
, mHasMagicEffects(false)
, mAlpha(1.f)
{
for(size_t i = 0;i < sNumBlendMasks;i++)
@ -1321,7 +1328,7 @@ namespace MWRender
++stateiter;
}
updateEffects(duration);
updateEffects();
if (mHeadController)
{
@ -1633,6 +1640,9 @@ namespace MWRender
SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
node->accept(assignVisitor);
// Notify that this animation has attached magic effects
mHasMagicEffects = true;
overrideFirstRootTexture(texture, mResourceSystem, node);
}
@ -1641,10 +1651,14 @@ namespace MWRender
RemoveFinishedCallbackVisitor visitor(effectId);
mInsert->accept(visitor);
visitor.remove();
mHasMagicEffects = visitor.mHasMagicEffects;
}
void Animation::getLoopingEffects(std::vector<int> &out) const
{
if (!mHasMagicEffects)
return;
FindVfxCallbacksVisitor visitor;
mInsert->accept(visitor);
@ -1657,13 +1671,19 @@ namespace MWRender
}
}
void Animation::updateEffects(float duration)
void Animation::updateEffects()
{
// We do not need to visit scene every frame.
// We can use a bool flag to check in spellcasting effect found.
if (!mHasMagicEffects)
return;
// TODO: objects without animation still will have
// transformation nodes with finished callbacks
RemoveFinishedCallbackVisitor visitor;
mInsert->accept(visitor);
visitor.remove();
mHasMagicEffects = visitor.mHasMagicEffects;
}
bool Animation::upperBodyReady() const

@ -263,6 +263,7 @@ protected:
osg::ref_ptr<RotateController> mHeadController;
float mHeadYawRadians;
float mHeadPitchRadians;
bool mHasMagicEffects;
osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
osg::ref_ptr<GlowUpdater> mGlowUpdater;
@ -450,7 +451,7 @@ public:
void setLoopingEnabled(const std::string &groupname, bool enabled);
/// This is typically called as part of runAnimation, but may be called manually if needed.
void updateEffects(float duration);
void updateEffects();
/// Return a node with the specified name, or NULL if not existing.
/// @note The matching is case-insensitive.

@ -171,11 +171,12 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor, float attackStrength)
return;
osg::Vec3f launchPos = osg::computeLocalToWorld(nodepaths[0]).getTrans();
float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->getFloat();
float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->getFloat();
float fThrownWeaponMinSpeed = gmst.find("fThrownWeaponMinSpeed")->mValue.getFloat();
float fThrownWeaponMaxSpeed = gmst.find("fThrownWeaponMaxSpeed")->mValue.getFloat();
float speed = fThrownWeaponMinSpeed + (fThrownWeaponMaxSpeed - fThrownWeaponMinSpeed) * attackStrength;
MWBase::Environment::get().getWorld()->launchProjectile(actor, *weapon, launchPos, orient, *weapon, speed, attackStrength);
MWWorld::Ptr weaponPtr = *weapon;
MWBase::Environment::get().getWorld()->launchProjectile(actor, weaponPtr, launchPos, orient, weaponPtr, speed, attackStrength);
showWeapon(false);
@ -208,13 +209,15 @@ void WeaponAnimation::releaseArrow(MWWorld::Ptr actor, float attackStrength)
return;
osg::Vec3f launchPos = osg::computeLocalToWorld(nodepaths[0]).getTrans();
float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->getFloat();
float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->getFloat();
float fProjectileMinSpeed = gmst.find("fProjectileMinSpeed")->mValue.getFloat();
float fProjectileMaxSpeed = gmst.find("fProjectileMaxSpeed")->mValue.getFloat();
float speed = fProjectileMinSpeed + (fProjectileMaxSpeed - fProjectileMinSpeed) * attackStrength;
MWBase::Environment::get().getWorld()->launchProjectile(actor, *ammo, launchPos, orient, *weapon, speed, attackStrength);
MWWorld::Ptr weaponPtr = *weapon;
MWWorld::Ptr ammoPtr = *ammo;
MWBase::Environment::get().getWorld()->launchProjectile(actor, ammoPtr, launchPos, orient, weaponPtr, speed, attackStrength);
inv.remove(*ammo, 1, actor);
inv.remove(ammoPtr, 1, actor);
mAmmunition.reset();
}
}

@ -548,6 +548,7 @@ namespace MWScript
runtime.pop();
ptr.getClass().getCreatureStats (ptr).getActiveSpells().removeEffects(spellid);
ptr.getClass().getCreatureStats (ptr).getSpells().removeEffects(spellid);
}
};

@ -46,6 +46,18 @@ namespace MWScript
{
namespace Transformation
{
void moveStandingActors(const MWWorld::Ptr &ptr, const osg::Vec3f& diff)
{
std::vector<MWWorld::Ptr> actors;
MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors);
for (auto& actor : actors)
{
osg::Vec3f actorPos(actor.getRefData().getPosition().asVec3());
actorPos += diff;
MWBase::Environment::get().getWorld()->moveObject(actor, actorPos.x(), actorPos.y(), actorPos.z());
}
}
template<class R>
class OpSetScale : public Interpreter::Opcode0
{
@ -839,6 +851,9 @@ namespace MWScript
osg::Vec3f worldPos(ptr.getRefData().getPosition().asVec3());
worldPos += diff;
// We should move actors, standing on moving object, too.
// This approach can be used to create elevators.
moveStandingActors(ptr, diff);
MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x(), worldPos.y(), worldPos.z());
}
};
@ -861,22 +876,21 @@ namespace MWScript
runtime.pop();
const float *objPos = ptr.getRefData().getPosition().pos;
osg::Vec3f diff;
MWWorld::Ptr updated;
if (axis == "x")
{
updated = MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+movement, objPos[1], objPos[2]);
}
diff.x() += movement;
else if (axis == "y")
{
updated = MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0], objPos[1]+movement, objPos[2]);
}
diff.y() += movement;
else if (axis == "z")
{
updated = MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0], objPos[1], objPos[2]+movement);
}
diff.z() += movement;
else
throw std::runtime_error ("invalid movement axis: " + axis);
// We should move actors, standing on moving object, too.
// This approach can be used to create elevators.
moveStandingActors(ptr, diff);
MWBase::Environment::get().getWorld()->moveObject(ptr, objPos[0]+diff.x(), objPos[1]+diff.y(), objPos[2]+diff.z());
}
};

@ -1145,14 +1145,24 @@ bool OpenAL_Output::playSound(Sound *sound, Sound_Handle data, float offset)
initCommon2D(source, sound->getPosition(), sound->getRealVolume(), sound->getPitch(),
sound->getIsLooping(), sound->getUseEnv());
alSourcei(source, AL_BUFFER, GET_PTRID(data));
alSourcef(source, AL_SEC_OFFSET, offset);
if(getALError() != AL_NO_ERROR)
{
alSourceRewind(source);
alSourcei(source, AL_BUFFER, 0);
alGetError();
return false;
}
alSourcei(source, AL_BUFFER, GET_PTRID(data));
alSourcePlay(source);
if(getALError() != AL_NO_ERROR)
{
alSourceRewind(source);
alSourcei(source, AL_BUFFER, 0);
alGetError();
return false;
}
mFreeSources.pop_front();
sound->mHandle = MAKE_PTRID(source);
@ -1175,14 +1185,24 @@ bool OpenAL_Output::playSound3D(Sound *sound, Sound_Handle data, float offset)
initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
sound->getRealVolume(), sound->getPitch(), sound->getIsLooping(),
sound->getUseEnv());
alSourcei(source, AL_BUFFER, GET_PTRID(data));
alSourcef(source, AL_SEC_OFFSET, offset);
if(getALError() != AL_NO_ERROR)
{
alSourceRewind(source);
alSourcei(source, AL_BUFFER, 0);
alGetError();
return false;
}
alSourcei(source, AL_BUFFER, GET_PTRID(data));
alSourcePlay(source);
if(getALError() != AL_NO_ERROR)
{
alSourceRewind(source);
alSourcei(source, AL_BUFFER, 0);
alGetError();
return false;
}
mFreeSources.pop_front();
sound->mHandle = MAKE_PTRID(source);
@ -1197,9 +1217,8 @@ void OpenAL_Output::finishSound(Sound *sound)
ALuint source = GET_PTRID(sound->mHandle);
sound->mHandle = 0;
// Rewind the stream instead of stopping it, this puts the source into an AL_INITIAL state,
// which works around a bug in the MacOS OpenAL implementation which would otherwise think
// the initial queue already played when it hasn't.
// Rewind the stream to put the source back into an AL_INITIAL state, for
// the next time it's used.
alSourceRewind(source);
alSourcei(source, AL_BUFFER, 0);
getALError();
@ -1302,9 +1321,8 @@ void OpenAL_Output::finishStream(Stream *sound)
sound->mHandle = 0;
mStreamThread->remove(stream);
// Rewind the stream instead of stopping it, this puts the source into an AL_INITIAL state,
// which works around a bug in the MacOS OpenAL implementation which would otherwise think
// the initial queue already played when it hasn't.
// Rewind the stream to put the source back into an AL_INITIAL state, for
// the next time it's used.
alSourceRewind(source);
alSourcei(source, AL_BUFFER, 0);
getALError();

@ -139,10 +139,10 @@ namespace MWSound
Sound_Buffer *SoundManager::insertSound(const std::string &soundId, const ESM::Sound *sound)
{
MWBase::World* world = MWBase::Environment::get().getWorld();
static const float fAudioDefaultMinDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMinDistance")->getFloat();
static const float fAudioDefaultMaxDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMaxDistance")->getFloat();
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->getFloat();
static const float fAudioMaxDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMaxDistanceMult")->getFloat();
static const float fAudioDefaultMinDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMinDistance")->mValue.getFloat();
static const float fAudioDefaultMaxDistance = world->getStore().get<ESM::GameSetting>().find("fAudioDefaultMaxDistance")->mValue.getFloat();
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->mValue.getFloat();
static const float fAudioMaxDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMaxDistanceMult")->mValue.getFloat();
float volume, min, max;
volume = static_cast<float>(pow(10.0, (sound->mData.mVolume / 255.0*3348.0 - 3348.0) / 2000.0));
@ -296,10 +296,10 @@ namespace MWSound
Stream *SoundManager::playVoice(DecoderPtr decoder, const osg::Vec3f &pos, bool playlocal)
{
MWBase::World* world = MWBase::Environment::get().getWorld();
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->getFloat();
static const float fAudioMaxDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMaxDistanceMult")->getFloat();
static const float fAudioVoiceDefaultMinDistance = world->getStore().get<ESM::GameSetting>().find("fAudioVoiceDefaultMinDistance")->getFloat();
static const float fAudioVoiceDefaultMaxDistance = world->getStore().get<ESM::GameSetting>().find("fAudioVoiceDefaultMaxDistance")->getFloat();
static const float fAudioMinDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMinDistanceMult")->mValue.getFloat();
static const float fAudioMaxDistanceMult = world->getStore().get<ESM::GameSetting>().find("fAudioMaxDistanceMult")->mValue.getFloat();
static const float fAudioVoiceDefaultMinDistance = world->getStore().get<ESM::GameSetting>().find("fAudioVoiceDefaultMinDistance")->mValue.getFloat();
static const float fAudioVoiceDefaultMaxDistance = world->getStore().get<ESM::GameSetting>().find("fAudioVoiceDefaultMaxDistance")->mValue.getFloat();
static float minDistance = std::max(fAudioVoiceDefaultMinDistance * fAudioMinDistanceMult, 1.0f);
static float maxDistance = std::max(fAudioVoiceDefaultMaxDistance * fAudioMaxDistanceMult, minDistance);

@ -1130,7 +1130,7 @@ namespace MWWorld
void clearCorpse(const MWWorld::Ptr& ptr)
{
const MWMechanics::CreatureStats& creatureStats = ptr.getClass().getCreatureStats(ptr);
static const float fCorpseClearDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCorpseClearDelay")->getFloat();
static const float fCorpseClearDelay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fCorpseClearDelay")->mValue.getFloat();
if (creatureStats.isDead() &&
creatureStats.isDeathAnimationFinished() &&
!ptr.getClass().isPersistent(ptr) &&
@ -1144,7 +1144,7 @@ namespace MWWorld
{
if (mState == State_Loaded)
{
static const int iMonthsToRespawn = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iMonthsToRespawn")->getInt();
static const int iMonthsToRespawn = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("iMonthsToRespawn")->mValue.getInteger();
if (MWBase::Environment::get().getWorld()->getTimeStamp() - mLastRespawn > 24*30*iMonthsToRespawn)
{
mLastRespawn = MWBase::Environment::get().getWorld()->getTimeStamp();

@ -289,8 +289,8 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
const MWWorld::Store<ESM::GameSetting> &store = world->getStore().get<ESM::GameSetting>();
MWMechanics::NpcStats& stats = actor.getClass().getNpcStats(actor);
static float fUnarmoredBase1 = store.find("fUnarmoredBase1")->getFloat();
static float fUnarmoredBase2 = store.find("fUnarmoredBase2")->getFloat();
static float fUnarmoredBase1 = store.find("fUnarmoredBase1")->mValue.getFloat();
static float fUnarmoredBase2 = store.find("fUnarmoredBase2")->mValue.getFloat();
int unarmoredSkill = stats.getSkill(ESM::Skill::Unarmored).getModified();
float unarmoredRating = (fUnarmoredBase1 * unarmoredSkill) * (fUnarmoredBase2 * unarmoredSkill);
@ -958,7 +958,7 @@ void MWWorld::InventoryStore::rechargeItems(float duration)
continue;
static float fMagicItemRechargePerSecond = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(
"fMagicItemRechargePerSecond")->getFloat();
"fMagicItemRechargePerSecond")->mValue.getFloat();
if (it->first->getCellRef().getEnchantmentCharge() <= it->second)
{

@ -76,7 +76,7 @@ namespace MWWorld
MWMechanics::CreatureStats& creatureStats = getPlayer().getClass().getCreatureStats(getPlayer());
MWMechanics::NpcStats& npcStats = getPlayer().getClass().getNpcStats(getPlayer());
MWMechanics::DynamicStat<float> health = creatureStats.getDynamic(0);
creatureStats.setHealth(int(health.getBase() / gmst.find("fWereWolfHealth")->getFloat()));
creatureStats.setHealth(int(health.getBase() / gmst.find("fWereWolfHealth")->mValue.getFloat()));
for (int i=0; i<ESM::Skill::Length; ++i)
npcStats.setSkill(i, mSaveSkills[i]);
for (int i=0; i<ESM::Attribute::Length; ++i)
@ -89,7 +89,7 @@ namespace MWWorld
MWMechanics::CreatureStats& creatureStats = getPlayer().getClass().getCreatureStats(getPlayer());
MWMechanics::NpcStats& npcStats = getPlayer().getClass().getNpcStats(getPlayer());
MWMechanics::DynamicStat<float> health = creatureStats.getDynamic(0);
creatureStats.setHealth(int(health.getBase() * gmst.find("fWereWolfHealth")->getFloat()));
creatureStats.setHealth(int(health.getBase() * gmst.find("fWereWolfHealth")->mValue.getFloat()));
for(size_t i = 0;i < ESM::Attribute::Length;++i)
{
// Oh, Bethesda. It's "Intelligence".
@ -97,7 +97,7 @@ namespace MWWorld
ESM::Attribute::sAttributeNames[i]);
MWMechanics::AttributeValue value = npcStats.getAttribute(i);
value.setBase(int(gmst.find(name)->getFloat()));
value.setBase(int(gmst.find(name)->mValue.getFloat()));
npcStats.setAttribute(i, value);
}
@ -112,7 +112,7 @@ namespace MWWorld
ESM::Skill::sSkillNames[i]);
MWMechanics::SkillValue value = npcStats.getSkill(i);
value.setBase(int(gmst.find(name)->getFloat()));
value.setBase(int(gmst.find(name)->mValue.getFloat()));
npcStats.setSkill(i, value);
}
}

@ -385,7 +385,7 @@ namespace MWWorld
{
osg::Quat orient = it->mNode->getAttitude();
static float fTargetSpellMaxSpeed = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fTargetSpellMaxSpeed")->getFloat();
.find("fTargetSpellMaxSpeed")->mValue.getFloat();
float speed = fTargetSpellMaxSpeed * it->mSpeed;
osg::Vec3f direction = orient * osg::Vec3f(0,1,0);
direction.normalize();

@ -1039,7 +1039,7 @@ inline void WeatherManager::addWeather(const std::string& name,
float dlFactor, float dlOffset,
const std::string& particleEffect)
{
static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->getFloat();
static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->mValue.getFloat();
Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect);

@ -211,7 +211,7 @@ namespace MWWorld
mStore.setUp(true);
mStore.movePlayerRecord();
mSwimHeightScale = mStore.get<ESM::GameSetting>().find("fSwimHeightScale")->getFloat();
mSwimHeightScale = mStore.get<ESM::GameSetting>().find("fSwimHeightScale")->mValue.getFloat();
mWeatherManager.reset(new MWWorld::WeatherManager(*mRendering, mFallback, mStore));
@ -1179,7 +1179,7 @@ namespace MWWorld
if (mActivationDistanceOverride >= 0)
return static_cast<float>(mActivationDistanceOverride);
static const int iMaxActivateDist = getStore().get<ESM::GameSetting>().find("iMaxActivateDist")->getInt();
static const int iMaxActivateDist = getStore().get<ESM::GameSetting>().find("iMaxActivateDist")->mValue.getInteger();
return static_cast<float>(iMaxActivateDist);
}
@ -1941,11 +1941,11 @@ namespace MWWorld
// Sink the camera while sneaking
bool sneaking = player.getClass().getCreatureStats(getPlayerPtr()).getStance(MWMechanics::CreatureStats::Stance_Sneak);
bool inair = !isOnGround(player);
bool swimming = isSwimming(player);
bool flying = isFlying(player);
static const float i1stPersonSneakDelta = getStore().get<ESM::GameSetting>().find("i1stPersonSneakDelta")->getFloat();
if (sneaking && !(swimming || inair))
static const float i1stPersonSneakDelta = getStore().get<ESM::GameSetting>().find("i1stPersonSneakDelta")->mValue.getFloat();
if (sneaking && !swimming && !flying)
mRendering->getCamera()->setSneakOffset(i1stPersonSneakDelta);
else
mRendering->getCamera()->setSneakOffset(0.f);
@ -2726,6 +2726,11 @@ namespace MWWorld
return !actors.empty();
}
void World::getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors)
{
mPhysics->getActorsStandingOn(object, actors);
}
bool World::getPlayerCollidingWith (const MWWorld::ConstPtr& object)
{
MWWorld::Ptr player = getPlayerPtr();
@ -3189,7 +3194,7 @@ namespace MWWorld
if (!actor.isEmpty() && actor != MWMechanics::getPlayer() && !manualSpell)
stats.getAiSequence().getCombatTargets(targetActors);
const float fCombatDistance = getStore().get<ESM::GameSetting>().find("fCombatDistance")->getFloat();
const float fCombatDistance = getStore().get<ESM::GameSetting>().find("fCombatDistance")->mValue.getFloat();
osg::Vec3f hitPosition = actor.getRefData().getPosition().asVec3();
@ -3307,10 +3312,34 @@ namespace MWWorld
}
}
void World::launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength)
void World::launchProjectile (MWWorld::Ptr& actor, MWWorld::Ptr& projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr& bow, float speed, float attackStrength)
{
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength);
// An initial position of projectile can be outside shooter's collision box, so any object between shooter and launch position will be ignored.
// To avoid this issue, we should check for impact immediately before launch the projectile.
// So we cast a 1-yard-length ray from shooter to launch position and check if there are collisions in this area.
// TODO: as a better solutuon we should handle projectiles during physics update, not during world update.
const osg::Vec3f sourcePos = worldPos + orient * osg::Vec3f(0,-1,0) * 64.f;
// Early out if the launch position is underwater
bool underwater = MWBase::Environment::get().getWorld()->isUnderwater(MWMechanics::getPlayer().getCell(), worldPos);
if (underwater)
{
mRendering->emitWaterRipple(worldPos);
return;
}
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit result.
std::vector<MWWorld::Ptr> targetActors;
if (!actor.isEmpty() && actor.getClass().isActor() && actor != MWMechanics::getPlayer())
actor.getClass().getCreatureStats(actor).getAiSequence().getCombatTargets(targetActors);
// Check for impact, if yes, handle hit, if not, launch projectile
MWPhysics::PhysicsSystem::RayResult result = mPhysics->castRay(sourcePos, worldPos, actor, targetActors, 0xff, MWPhysics::CollisionType_Projectile);
if (result.mHit)
MWMechanics::projectileHit(actor, result.mHitObject, bow, projectile, result.mHitPos, attackStrength);
else
mProjectileManager->launchProjectile(actor, projectile, worldPos, orient, bow, speed, attackStrength);
}
void World::launchMagicBolt (const std::string &spellId, const MWWorld::Ptr& caster, const osg::Vec3f& fallbackDirection)
@ -3653,8 +3682,8 @@ namespace MWWorld
int bounty = player.getClass().getNpcStats(player).getBounty();
int playerGold = player.getClass().getContainerStore(player).count(ContainerStore::sGoldId);
float fCrimeGoldDiscountMult = getStore().get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->getFloat();
float fCrimeGoldTurnInMult = getStore().get<ESM::GameSetting>().find("fCrimeGoldTurnInMult")->getFloat();
float fCrimeGoldDiscountMult = getStore().get<ESM::GameSetting>().find("fCrimeGoldDiscountMult")->mValue.getFloat();
float fCrimeGoldTurnInMult = getStore().get<ESM::GameSetting>().find("fCrimeGoldTurnInMult")->mValue.getFloat();
int discount = static_cast<int>(bounty * fCrimeGoldDiscountMult);
int turnIn = static_cast<int>(bounty * fCrimeGoldTurnInMult);
@ -3719,7 +3748,7 @@ namespace MWWorld
mPlayer->recordCrimeId();
confiscateStolenItems(player);
int iDaysinPrisonMod = getStore().get<ESM::GameSetting>().find("iDaysinPrisonMod")->getInt();
int iDaysinPrisonMod = getStore().get<ESM::GameSetting>().find("iDaysinPrisonMod")->mValue.getInteger();
mDaysInPrison = std::max(1, bounty / iDaysinPrisonMod);
return;
@ -3777,7 +3806,7 @@ namespace MWWorld
{
const ESM::CreatureLevList* list = getStore().get<ESM::CreatureLevList>().find(creatureList);
int iNumberCreatures = getStore().get<ESM::GameSetting>().find("iNumberCreatures")->getInt();
int iNumberCreatures = getStore().get<ESM::GameSetting>().find("iNumberCreatures")->mValue.getInteger();
int numCreatures = 1 + Misc::Rng::rollDice(iNumberCreatures); // [1, iNumberCreatures]
for (int i=0; i<numCreatures; ++i)

@ -684,6 +684,7 @@ namespace MWWorld
End of tes3mp addition
*/
void getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors); ///< get a list of actors standing on \a object
bool getPlayerStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if the player is standing on \a object
bool getActorStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if any actor is standing on \a object
bool getPlayerCollidingWith(const MWWorld::ConstPtr& object) override; ///< @return true if the player is colliding with \a object
@ -766,8 +767,8 @@ namespace MWWorld
void castSpell (const MWWorld::Ptr& actor, bool manualSpell=false) override;
void launchMagicBolt (const std::string& spellId, const MWWorld::Ptr& caster, const osg::Vec3f& fallbackDirection) override;
void launchProjectile (MWWorld::Ptr actor, MWWorld::ConstPtr projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr bow, float speed, float attackStrength) override;
void launchProjectile (MWWorld::Ptr& actor, MWWorld::Ptr& projectile,
const osg::Vec3f& worldPos, const osg::Quat& orient, MWWorld::Ptr& bow, float speed, float attackStrength) override;
void applyLoopingParticles(const MWWorld::Ptr& ptr) override;

@ -306,10 +306,22 @@ namespace Compiler
int i = 0;
std::string lowerCase = Misc::StringUtils::lowerCase(name);
bool isKeyword = false;
for (; sKeywords[i]; ++i)
if (lowerCase==sKeywords[i])
{
isKeyword = true;
break;
}
// Russian localization and some mods use a quirk - add newline character directly
// to compiled bytecode via HEX-editor to implement multiline messageboxes.
// Of course, original editor will not compile such script.
// Allow messageboxes to bybass the "incomplete string or name" error.
if (lowerCase == "messagebox")
enableIgnoreNewlines();
else if (isKeyword)
mIgnoreNewline = false;
if (sKeywords[i])
{
@ -357,9 +369,14 @@ namespace Compiler
// }
else if (c=='\n')
{
error = true;
mErrorHandler.error ("incomplete string or name", mLoc);
break;
if (mIgnoreNewline)
mErrorHandler.warning ("string contains newline character, make sure that it is intended", mLoc);
else
{
error = true;
mErrorHandler.error ("incomplete string or name", mLoc);
break;
}
}
}
else if (!(c=='"' && name.empty()))
@ -502,6 +519,11 @@ namespace Compiler
if (get (c) && c!='=') // <== is a allowed as an alternative to <= :(
putback (c);
}
else if (c == '<' || c == '>') // Treat <> and << as <
{
special = S_cmpLT;
mErrorHandler.warning (std::string("invalid operator <") + c + ", treating it as <", mLoc);
}
else
{
putback (c);
@ -525,6 +547,11 @@ namespace Compiler
if (get (c) && c!='=') // >== is a allowed as an alternative to >= :(
putback (c);
}
else if (c == '<' || c == '>') // Treat >< and >> as >
{
special = S_cmpGT;
mErrorHandler.warning (std::string("invalid operator >") + c + ", treating it as >", mLoc);
}
else
{
putback (c);
@ -578,7 +605,7 @@ namespace Compiler
const Extensions *extensions)
: mErrorHandler (errorHandler), mStream (inputStream), mExtensions (extensions),
mPutback (Putback_None), mPutbackCode(0), mPutbackInteger(0), mPutbackFloat(0),
mStrictKeywords (false), mTolerantNames (false)
mStrictKeywords (false), mTolerantNames (false), mIgnoreNewline(false)
{
}
@ -631,6 +658,11 @@ namespace Compiler
mExtensions->listKeywords (keywords);
}
void Scanner::enableIgnoreNewlines()
{
mIgnoreNewline = true;
}
void Scanner::enableStrictKeywords()
{
mStrictKeywords = true;

@ -39,6 +39,7 @@ namespace Compiler
TokenLoc mPutbackLoc;
bool mStrictKeywords;
bool mTolerantNames;
bool mIgnoreNewline;
public:
@ -126,6 +127,11 @@ namespace Compiler
void listKeywords (std::vector<std::string>& keywords);
///< Append all known keywords to \a keywords.
/// Treat newline character as a part of script command.
///
/// \attention This mode lasts only until the next keyword is reached.
void enableIgnoreNewlines();
/// Do not accept keywords in quotation marks anymore.
///
/// \attention This mode lasts only until the next newline is reached.

@ -22,21 +22,6 @@ namespace ESM
mValue.write (esm, ESM::Variant::Format_Gmst);
}
int GameSetting::getInt() const
{
return mValue.getInteger();
}
float GameSetting::getFloat() const
{
return mValue.getFloat();
}
std::string GameSetting::getString() const
{
return mValue.getString();
}
void GameSetting::blank()
{
mValue.setType (ESM::VT_None);

@ -28,17 +28,6 @@ struct GameSetting
void load(ESMReader &esm, bool &isDeleted);
/// \todo remove the get* functions (redundant, since mValue has equivalent functions now).
int getInt() const;
///< Throws an exception if GMST is not of type int or float.
float getFloat() const;
///< Throws an exception if GMST is not of type int or float.
std::string getString() const;
///< Throwns an exception if GMST is not of type string.
void save(ESMWriter &esm, bool isDeleted = false) const;
void blank();

@ -274,42 +274,45 @@ short MagicEffect::getResistanceEffect(short effect)
// Source https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attribute
// <Effect, Effect providing resistance against first effect>
std::map<short, short> effects;
effects[DisintegrateArmor] = Sanctuary;
effects[DisintegrateWeapon] = Sanctuary;
for (int i=0; i<5; ++i)
effects[DrainAttribute+i] = ResistMagicka;
for (int i=0; i<5; ++i)
effects[DamageAttribute+i] = ResistMagicka;
for (int i=0; i<5; ++i)
effects[AbsorbAttribute+i] = ResistMagicka;
for (int i=0; i<10; ++i)
effects[WeaknessToFire+i] = ResistMagicka;
effects[Burden] = ResistMagicka;
effects[Charm] = ResistMagicka;
effects[Silence] = ResistMagicka;
effects[Blind] = ResistMagicka;
effects[Sound] = ResistMagicka;
for (int i=0; i<2; ++i)
static std::map<short, short> effects;
if (effects.empty())
{
effects[CalmHumanoid+i] = ResistMagicka;
effects[FrenzyHumanoid+i] = ResistMagicka;
effects[DemoralizeHumanoid+i] = ResistMagicka;
effects[RallyHumanoid+i] = ResistMagicka;
}
effects[DisintegrateArmor] = Sanctuary;
effects[DisintegrateWeapon] = Sanctuary;
for (int i=0; i<5; ++i)
effects[DrainAttribute+i] = ResistMagicka;
for (int i=0; i<5; ++i)
effects[DamageAttribute+i] = ResistMagicka;
for (int i=0; i<5; ++i)
effects[AbsorbAttribute+i] = ResistMagicka;
for (int i=0; i<10; ++i)
effects[WeaknessToFire+i] = ResistMagicka;
effects[Burden] = ResistMagicka;
effects[Charm] = ResistMagicka;
effects[Silence] = ResistMagicka;
effects[Blind] = ResistMagicka;
effects[Sound] = ResistMagicka;
for (int i=0; i<2; ++i)
{
effects[CalmHumanoid+i] = ResistMagicka;
effects[FrenzyHumanoid+i] = ResistMagicka;
effects[DemoralizeHumanoid+i] = ResistMagicka;
effects[RallyHumanoid+i] = ResistMagicka;
}
effects[TurnUndead] = ResistMagicka;
effects[TurnUndead] = ResistMagicka;
effects[FireDamage] = ResistFire;
effects[FrostDamage] = ResistFrost;
effects[ShockDamage] = ResistShock;
effects[Vampirism] = ResistCommonDisease;
effects[Corprus] = ResistCorprusDisease;
effects[Poison] = ResistPoison;
effects[Paralyze] = ResistParalysis;
effects[FireDamage] = ResistFire;
effects[FrostDamage] = ResistFrost;
effects[ShockDamage] = ResistShock;
effects[Vampirism] = ResistCommonDisease;
effects[Corprus] = ResistCorprusDisease;
effects[Poison] = ResistPoison;
effects[Paralyze] = ResistParalysis;
}
if (effects.find(effect) != effects.end())
return effects[effect];
@ -319,41 +322,43 @@ short MagicEffect::getResistanceEffect(short effect)
short MagicEffect::getWeaknessEffect(short effect)
{
std::map<short, short> effects;
for (int i=0; i<5; ++i)
effects[DrainAttribute+i] = WeaknessToMagicka;
for (int i=0; i<5; ++i)
effects[DamageAttribute+i] = WeaknessToMagicka;
for (int i=0; i<5; ++i)
effects[AbsorbAttribute+i] = WeaknessToMagicka;
for (int i=0; i<10; ++i)
effects[WeaknessToFire+i] = WeaknessToMagicka;
effects[Burden] = WeaknessToMagicka;
effects[Charm] = WeaknessToMagicka;
effects[Silence] = WeaknessToMagicka;
effects[Blind] = WeaknessToMagicka;
effects[Sound] = WeaknessToMagicka;
for (int i=0; i<2; ++i)
static std::map<short, short> effects;
if (effects.empty())
{
effects[CalmHumanoid+i] = WeaknessToMagicka;
effects[FrenzyHumanoid+i] = WeaknessToMagicka;
effects[DemoralizeHumanoid+i] = WeaknessToMagicka;
effects[RallyHumanoid+i] = WeaknessToMagicka;
}
for (int i=0; i<5; ++i)
effects[DrainAttribute+i] = WeaknessToMagicka;
for (int i=0; i<5; ++i)
effects[DamageAttribute+i] = WeaknessToMagicka;
for (int i=0; i<5; ++i)
effects[AbsorbAttribute+i] = WeaknessToMagicka;
for (int i=0; i<10; ++i)
effects[WeaknessToFire+i] = WeaknessToMagicka;
effects[Burden] = WeaknessToMagicka;
effects[Charm] = WeaknessToMagicka;
effects[Silence] = WeaknessToMagicka;
effects[Blind] = WeaknessToMagicka;
effects[Sound] = WeaknessToMagicka;
for (int i=0; i<2; ++i)
{
effects[CalmHumanoid+i] = WeaknessToMagicka;
effects[FrenzyHumanoid+i] = WeaknessToMagicka;
effects[DemoralizeHumanoid+i] = WeaknessToMagicka;
effects[RallyHumanoid+i] = WeaknessToMagicka;
}
effects[TurnUndead] = WeaknessToMagicka;
effects[TurnUndead] = WeaknessToMagicka;
effects[FireDamage] = WeaknessToFire;
effects[FrostDamage] = WeaknessToFrost;
effects[ShockDamage] = WeaknessToShock;
effects[Vampirism] = WeaknessToCommonDisease;
effects[Corprus] = WeaknessToCorprusDisease;
effects[Poison] = WeaknessToPoison;
effects[FireDamage] = WeaknessToFire;
effects[FrostDamage] = WeaknessToFrost;
effects[ShockDamage] = WeaknessToShock;
effects[Vampirism] = WeaknessToCommonDisease;
effects[Corprus] = WeaknessToCorprusDisease;
effects[Poison] = WeaknessToPoison;
effects[Paralyze] = -1;
effects[Paralyze] = -1;
}
if (effects.find(effect) != effects.end())
return effects[effect];

@ -26,7 +26,7 @@ namespace
float v = 0.0f;
for(int i = 0;i < 3;++i)
v += std::sin(fb*time*f[i] + o[1])*m[i];
v += std::sin(fb*time*f[i] + o[i])*m[i];
return v * s;
}
@ -73,17 +73,15 @@ namespace SceneUtil
float cycle_time;
float time_distortion;
const float pi = 3.14159265359;
if(mType == LT_Pulse || mType == LT_PulseSlow)
{
cycle_time = 2.0f * pi;
time_distortion = mType == LT_Pulse ? 20.0f : 4.f;
cycle_time = 2.0f * osg::PI;
time_distortion = 3.0f;
}
else
{
static const float fa = 0.785398f;
static const float phase_wavelength = 120.0f * pi / fa;
static const float fa = osg::PI / 4.0f;
static const float phase_wavelength = 120.0f * osg::PI / fa;
cycle_time = 500.0f;
mPhase = std::fmod(mPhase + dt, phase_wavelength);
@ -94,12 +92,14 @@ namespace SceneUtil
if(mDirection > 0 && mDeltaCount > +cycle_time)
{
mDirection = -1.0f;
mDeltaCount = 2.0f*cycle_time - mDeltaCount;
float extra = mDeltaCount - cycle_time;
mDeltaCount -= 2*extra;
}
if(mDirection < 0 && mDeltaCount < -cycle_time)
{
mDirection = +1.0f;
mDeltaCount = -2.0f*cycle_time - mDeltaCount;
float extra = cycle_time - mDeltaCount;
mDeltaCount += 2*extra;
}
static const float fast = 4.0f/1.0f;

@ -8,6 +8,31 @@
#include "skeleton.hpp"
#include "util.hpp"
namespace
{
inline void accumulateMatrix(const osg::Matrixf& invBindMatrix, const osg::Matrixf& matrix, const float weight, osg::Matrixf& result)
{
osg::Matrixf m = invBindMatrix * matrix;
float* ptr = m.ptr();
float* ptrresult = result.ptr();
ptrresult[0] += ptr[0] * weight;
ptrresult[1] += ptr[1] * weight;
ptrresult[2] += ptr[2] * weight;
ptrresult[4] += ptr[4] * weight;
ptrresult[5] += ptr[5] * weight;
ptrresult[6] += ptr[6] * weight;
ptrresult[8] += ptr[8] * weight;
ptrresult[9] += ptr[9] * weight;
ptrresult[10] += ptr[10] * weight;
ptrresult[12] += ptr[12] * weight;
ptrresult[13] += ptr[13] * weight;
ptrresult[14] += ptr[14] * weight;
}
}
namespace SceneUtil
{
@ -141,28 +166,6 @@ bool RigGeometry::initFromParentSkeleton(osg::NodeVisitor* nv)
return true;
}
void accumulateMatrix(const osg::Matrixf& invBindMatrix, const osg::Matrixf& matrix, float weight, osg::Matrixf& result)
{
osg::Matrixf m = invBindMatrix * matrix;
float* ptr = m.ptr();
float* ptrresult = result.ptr();
ptrresult[0] += ptr[0] * weight;
ptrresult[1] += ptr[1] * weight;
ptrresult[2] += ptr[2] * weight;
ptrresult[4] += ptr[4] * weight;
ptrresult[5] += ptr[5] * weight;
ptrresult[6] += ptr[6] * weight;
ptrresult[8] += ptr[8] * weight;
ptrresult[9] += ptr[9] * weight;
ptrresult[10] += ptr[10] * weight;
ptrresult[12] += ptr[12] * weight;
ptrresult[13] += ptr[13] * weight;
ptrresult[14] += ptr[14] * weight;
}
void RigGeometry::cull(osg::NodeVisitor* nv)
{
if (!mSkeleton)
@ -173,7 +176,8 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
return;
}
if ((!mSkeleton->getActive() && mLastFrameNumber != 0) || mLastFrameNumber == nv->getTraversalNumber())
unsigned int traversalNumber = nv->getTraversalNumber();
if (mLastFrameNumber == traversalNumber || (mLastFrameNumber != 0 && !mSkeleton->getActive()))
{
osg::Geometry& geom = *getGeometry(mLastFrameNumber);
nv->pushOntoNodePath(&geom);
@ -181,10 +185,10 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
nv->popFromNodePath();
return;
}
mLastFrameNumber = nv->getTraversalNumber();
mLastFrameNumber = traversalNumber;
osg::Geometry& geom = *getGeometry(mLastFrameNumber);
mSkeleton->updateBoneMatrices(nv->getTraversalNumber());
mSkeleton->updateBoneMatrices(traversalNumber);
// skinning
const osg::Vec3Array* positionSrc = static_cast<osg::Vec3Array*>(mSourceGeometry->getVertexArray());
@ -195,34 +199,31 @@ void RigGeometry::cull(osg::NodeVisitor* nv)
osg::Vec3Array* normalDst = static_cast<osg::Vec3Array*>(geom.getNormalArray());
osg::Vec4Array* tangentDst = static_cast<osg::Vec4Array*>(geom.getTexCoordArray(7));
for (Bone2VertexMap::const_iterator it = mBone2VertexMap.begin(); it != mBone2VertexMap.end(); ++it)
for (auto &pair : mBone2VertexMap)
{
osg::Matrixf resultMat (0, 0, 0, 0,
osg::Matrixf resultMat (0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1);
for (std::vector<BoneWeight>::const_iterator weightIt = it->first.begin(); weightIt != it->first.end(); ++weightIt)
for (auto &weight : pair.first)
{
Bone* bone = weightIt->first.first;
const osg::Matrix& invBindMatrix = weightIt->first.second;
float weight = weightIt->second;
const osg::Matrixf& boneMatrix = bone->mMatrixInSkeletonSpace;
accumulateMatrix(invBindMatrix, boneMatrix, weight, resultMat);
accumulateMatrix(weight.first.second, weight.first.first->mMatrixInSkeletonSpace, weight.second, resultMat);
}
if (mGeomToSkelMatrix)
resultMat *= (*mGeomToSkelMatrix);
for (std::vector<unsigned short>::const_iterator vertexIt = it->second.begin(); vertexIt != it->second.end(); ++vertexIt)
for (auto &vertex : pair.second)
{
unsigned short vertex = *vertexIt;
(*positionDst)[vertex] = resultMat.preMult((*positionSrc)[vertex]);
if (normalDst)
(*normalDst)[vertex] = osg::Matrix::transform3x3((*normalSrc)[vertex], resultMat);
(*normalDst)[vertex] = osg::Matrixf::transform3x3((*normalSrc)[vertex], resultMat);
if (tangentDst)
{
osg::Vec4f srcTangent = (*tangentSrc)[vertex];
osg::Vec3f transformedTangent = osg::Matrix::transform3x3(osg::Vec3f(srcTangent.x(), srcTangent.y(), srcTangent.z()), resultMat);
const osg::Vec4f& srcTangent = (*tangentSrc)[vertex];
osg::Vec3f transformedTangent = osg::Matrixf::transform3x3(osg::Vec3f(srcTangent.x(), srcTangent.y(), srcTangent.z()), resultMat);
(*tangentDst)[vertex] = osg::Vec4f(transformedTangent, srcTangent.w());
}
}

@ -1,28 +1,15 @@
#include "unrefqueue.hpp"
#include <deque>
//#include <osg/Timer>
//#include <components/debug/debuglog.hpp>
#include <components/sceneutil/workqueue.hpp>
namespace SceneUtil
{
class UnrefWorkItem : public SceneUtil::WorkItem
void UnrefWorkItem::doWork()
{
public:
std::deque<osg::ref_ptr<const osg::Referenced> > mObjects;
virtual void doWork()
{
//osg::Timer timer;
//size_t objcount = mObjects.size();
mObjects.clear();
//Log(Debug::Verbose) << "cleared " << objcount << " objects in " << timer.time_m();
}
};
mObjects.clear();
}
UnrefQueue::UnrefQueue()
{

@ -1,13 +1,23 @@
#ifndef OPENMW_COMPONENTS_UNREFQUEUE_H
#define OPENMW_COMPONENTS_UNREFQUEUE_H
#include <deque>
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <components/sceneutil/workqueue.hpp>
namespace SceneUtil
{
class WorkQueue;
class UnrefWorkItem;
class UnrefWorkItem : public SceneUtil::WorkItem
{
public:
std::deque<osg::ref_ptr<const osg::Referenced> > mObjects;
virtual void doWork();
};
/// @brief Handles unreferencing of objects through the WorkQueue. Typical use scenario
/// would be the main thread pushing objects that are no longer needed, and the background thread deleting them.

@ -1383,9 +1383,9 @@ We add several new script instructions:
* PlayBackgroundMusic (t)
* PlaylistBackgroundMusic (pl)
* StopBackgroundMusic
* PlayEventMusic (t, loop=0, force=0)
* PlaylistEventMusic (pl, loop=0, force=0)
* StopEventMusic
* PlayEventMusic (t, priority, loop=0, force=0)
* PlaylistEventMusic (pl, priority, loop=0, force=0)
* StopEventMusic (priority)
Arguments:
@ -1393,8 +1393,14 @@ Arguments:
* pl (string): a playlist (specified by its ID)
* loop (integer): looping or not
* force (integer): Terminate any other running event music first. If this flag is 0 and there is already event music playing the new event music is ignored. Event music provided by content developers will usually not set this flag.
* priority (integer): Priority for event music. If there are multiple instances of active event music only the one with the highest priority will play. There can only ever be one instance of event music for any priority level. If event music of higher priority stops and there is event music of lower priority the event music of lower priority starts to play.
Note: An attempt to play a track or playlist that is currently playing is ignored. In this case the track or playlist does not restart.
Note: An attempt to play a track or playlist that is currently playing is ignored. In this case the track or playlist does not restart. Changes in looping behaviour are considered though.
New games starting with a new format omwgame file can use priorities as the developer sees fit. For old games where automatic injection of scripts and music records take place we define the following priorities:
* 10: Combat music
* 0: Basic event music
### Transition of Existing System

@ -47,4 +47,33 @@ Installing game files via Steam on macOS: DISK WRITE ERROR
[other entries]
}
Restart the Steam client. The download should now proceed.
Restart the Steam client. The download should now proceed.
In-game textures show up as pink
################################
:Symptoms:
Some textures don't show up and are replaced by pink "filler" textures.
:Cause:
Textures shipped with Morrowind are compressed with S3TC, a texture compression algorithm that was patented in
the United States until October 2017. Software drivers and operating system distributions released before that date
may not include support for this algorithm.
:Fix:
Upgrade your graphics drivers and/or operating system to the latest version.
Music plays, but only a black screen is shown
#############################################
:Symptoms:
When launching OpenMW, audio is heard but there is only a black screen.
:Cause:
This can occur when you did not import the Morrowind.ini file when the launcher asked for it.
:Fix:
To fix it, you need to delete the `launcher.cfg` file from your configuration path
([Path description on Wiki](https://wiki.openmw.org/index.php?title=Paths)), then start the launcher, select your
Morrowind installation, and when the launcher asks whether the `Morrowind.ini` file should be imported, make sure
to select "Yes".
Loading…
Cancel
Save