Merge pull request #400 from OpenMW/master while resolving conflicts

# Conflicts:
#	apps/openmw/mwmechanics/spellcasting.cpp
0.6.3
David Cernat 6 years ago
commit e3c43c6af7

@ -39,6 +39,7 @@ namespace MWBase
class ResponseCallback
{
public:
virtual ~ResponseCallback() = default;
virtual void addResponse(const std::string& title, const std::string& text) = 0;
};

@ -536,30 +536,29 @@ namespace MWInput
isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25;
if(triedToMove) resetIdleTime();
if (actionIsActive(A_MoveLeft))
if (actionIsActive(A_MoveLeft) && !actionIsActive(A_MoveRight))
{
triedToMove = true;
mPlayer->setLeftRight (-1);
}
else if (actionIsActive(A_MoveRight))
else if (actionIsActive(A_MoveRight) && !actionIsActive(A_MoveLeft))
{
triedToMove = true;
mPlayer->setLeftRight (1);
}
if (actionIsActive(A_MoveForward))
if (actionIsActive(A_MoveForward) && !actionIsActive(A_MoveBackward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1);
}
else if (actionIsActive(A_MoveBackward))
else if (actionIsActive(A_MoveBackward) && !actionIsActive(A_MoveForward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1);
}
else if(mPlayer->getAutoMove())
{
triedToMove = true;

@ -428,7 +428,7 @@ namespace MWMechanics
{
// Player followers and escorters with high fight should not initiate combat with the player or with
// other player followers or escorters
if (std::find(playerAllies.begin(), playerAllies.end(), actor1) == playerAllies.end())
if (!isPlayerFollowerOrEscorter)
aggressive = MWBase::Environment::get().getMechanicsManager()->isAggressive(actor1, actor2);
}
/*

@ -1,6 +1,7 @@
#include "combat.hpp"
#include <components/misc/rng.hpp>
#include <components/settings/settings.hpp>
#include <components/sceneutil/positionattitudetransform.hpp>
@ -194,7 +195,11 @@ namespace MWMechanics
if (!(weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Silver
|| weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Magical))
damage *= multiplier;
{
if (weapon.getClass().getEnchantment(weapon).empty()
|| !Settings::Manager::getBool("enchanted weapons are magical", "Game"))
damage *= multiplier;
}
if ((weapon.get<ESM::Weapon>()->mBase->mData.mFlags & ESM::Weapon::Silver)
&& actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf())

@ -1779,11 +1779,11 @@ namespace MWMechanics
{
if (werewolf)
{
player->saveSkillsAttributes();
player->setWerewolfSkillsAttributes();
player->saveStats();
player->setWerewolfStats();
}
else
player->restoreSkillsAttributes();
player->restoreStats();
}
// Werewolfs can not cast spells, so we need to unset the prepared spell if there is one.

@ -7,6 +7,7 @@
#include <boost/format.hpp>
#include <components/misc/rng.hpp>
#include <components/settings/settings.hpp>
/*
Start of tes3mp addition
@ -504,6 +505,9 @@ namespace MWMechanics
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicTargetResisted}");
}
if (target == getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState())
magnitudeMult = 0;
// If player is attempting to cast a harmful spell, show the target's HP bar
if (castByPlayer && target != caster)
MWBase::Environment::get().getWindowManager()->setEnemy(target);
@ -582,9 +586,12 @@ namespace MWMechanics
ActiveSpells::ActiveEffect effect_ = effect;
effect_.mMagnitude *= -1;
absorbEffects.push_back(effect_);
// Also make sure to set casterActorId = target, so that the effect on the caster gets purged when the target dies
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
absorbEffects, mSourceName, target.getClass().getCreatureStats(target).getActorId());
if (reflected && Settings::Manager::getBool("classic reflected absorb attribute behavior", "Game"))
target.getClass().getCreatureStats(target).getActiveSpells().addSpell("", true,
absorbEffects, mSourceName, caster.getClass().getCreatureStats(caster).getActorId());
else
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
absorbEffects, mSourceName, target.getClass().getCreatureStats(target).getActorId());
}
}
}
@ -928,7 +935,8 @@ namespace MWMechanics
const float normalizedEncumbrance = mCaster.getClass().getNormalizedEncumbrance(mCaster);
float fatigueLoss = spell->mData.mCost * (fFatigueSpellBase + normalizedEncumbrance * fFatigueSpellMult);
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss); stats.setFatigue(fatigue);
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
stats.setFatigue(fatigue);
bool fail = false;
@ -951,9 +959,7 @@ namespace MWMechanics
(dedicatedAttack && dedicatedAttack->success == false))
{
if (mCaster == getPlayer())
{
MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicSkillFail}");
}
fail = true;
}
/*
@ -1178,8 +1184,6 @@ namespace MWMechanics
bool receivedMagicDamage = false;
bool godmode = actor == MWMechanics::getPlayer() && MWBase::Environment::get().getWorld()->getGodModeState();
switch (effectKey.mId)
{
case ESM::MagicEffect::DamageAttribute:
@ -1202,40 +1206,25 @@ namespace MWMechanics
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::RestoreHealth, magnitude);
break;
case ESM::MagicEffect::DamageHealth:
if (!godmode)
{
receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
}
receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
break;
case ESM::MagicEffect::DamageMagicka:
case ESM::MagicEffect::DamageFatigue:
if (!godmode)
{
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
}
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::DamageHealth, -magnitude);
break;
case ESM::MagicEffect::AbsorbHealth:
if (!godmode)
{
if (magnitude > 0.f)
receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
}
if (magnitude > 0.f)
receivedMagicDamage = true;
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
break;
case ESM::MagicEffect::AbsorbMagicka:
case ESM::MagicEffect::AbsorbFatigue:
if (!godmode)
{
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
}
adjustDynamicStat(creatureStats, effectKey.mId-ESM::MagicEffect::AbsorbHealth, -magnitude);
break;
case ESM::MagicEffect::DisintegrateArmor:
@ -1258,6 +1247,7 @@ namespace MWMechanics
if (disintegrateSlot(actor, priorities[i], magnitude))
break;
}
break;
}
case ESM::MagicEffect::DisintegrateWeapon:
@ -1280,12 +1270,9 @@ namespace MWMechanics
if (weather > 1)
damageScale *= fMagicSunBlockedMult;
if (!godmode)
{
adjustDynamicStat(creatureStats, 0, -magnitude * damageScale);
if (magnitude * damageScale > 0.f)
receivedMagicDamage = true;
}
adjustDynamicStat(creatureStats, 0, -magnitude * damageScale);
if (magnitude * damageScale > 0.f)
receivedMagicDamage = true;
break;
}
@ -1295,12 +1282,8 @@ namespace MWMechanics
case ESM::MagicEffect::FrostDamage:
case ESM::MagicEffect::Poison:
{
if (!godmode)
{
adjustDynamicStat(creatureStats, 0, -magnitude);
receivedMagicDamage = true;
}
adjustDynamicStat(creatureStats, 0, -magnitude);
receivedMagicDamage = true;
break;
}

@ -256,11 +256,7 @@ bool MWWorld::ContainerStore::stacks(const ConstPtr& ptr1, const ConstPtr& ptr2)
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add(const std::string &id, int count, const Ptr &actorPtr)
{
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), id, count);
// a bit pointless to set owner for the player
if (actorPtr != MWMechanics::getPlayer())
return add(ref.getPtr(), count, actorPtr, true);
else
return add(ref.getPtr(), count, actorPtr, false);
return add(ref.getPtr(), count, actorPtr, true);
}
MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner)

@ -47,37 +47,45 @@ namespace MWWorld
mPlayer.mData.setPosition(playerPos);
}
void Player::saveSkillsAttributes()
void Player::saveStats()
{
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
for (int i=0; i<ESM::Skill::Length; ++i)
mSaveSkills[i] = stats.getSkill(i);
for (int i=0; i<ESM::Attribute::Length; ++i)
mSaveAttributes[i] = stats.getAttribute(i);
}
void Player::restoreSkillsAttributes()
void Player::restoreStats()
{
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
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()));
for (int i=0; i<ESM::Skill::Length; ++i)
stats.setSkill(i, mSaveSkills[i]);
npcStats.setSkill(i, mSaveSkills[i]);
for (int i=0; i<ESM::Attribute::Length; ++i)
stats.setAttribute(i, mSaveAttributes[i]);
npcStats.setAttribute(i, mSaveAttributes[i]);
}
void Player::setWerewolfSkillsAttributes()
void Player::setWerewolfStats()
{
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer());
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()));
for(size_t i = 0;i < ESM::Attribute::Length;++i)
{
// Oh, Bethesda. It's "Intelligence".
std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") :
ESM::Attribute::sAttributeNames[i]);
MWMechanics::AttributeValue value = stats.getAttribute(i);
MWMechanics::AttributeValue value = npcStats.getAttribute(i);
value.setBase(int(gmst.find(name)->getFloat()));
stats.setAttribute(i, value);
npcStats.setAttribute(i, value);
}
for(size_t i = 0;i < ESM::Skill::Length;i++)
@ -90,9 +98,9 @@ namespace MWWorld
std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") :
ESM::Skill::sSkillNames[i]);
MWMechanics::SkillValue value = stats.getSkill(i);
MWMechanics::SkillValue value = npcStats.getSkill(i);
value.setBase(int(gmst.find(name)->getFloat()));
stats.setSkill(i, value);
npcStats.setSkill(i, value);
}
}
@ -366,8 +374,8 @@ namespace MWWorld
if (player.mObject.mNpcStats.mWerewolfDeprecatedData && player.mObject.mNpcStats.mIsWerewolf)
{
saveSkillsAttributes();
setWerewolfSkillsAttributes();
saveStats();
setWerewolfStats();
}
getPlayer().getClass().getCreatureStats(getPlayer()).getAiSequence().clear();

@ -46,7 +46,7 @@ namespace MWWorld
int mCurrentCrimeId; // the id assigned witnesses
int mPaidCrimeId; // the last id paid off (0 bounty)
// Saved skills and attributes prior to becoming a werewolf
// Saved stats prior to becoming a werewolf
MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length];
MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length];
@ -56,9 +56,9 @@ namespace MWWorld
Player(const ESM::NPC *player);
void saveSkillsAttributes();
void restoreSkillsAttributes();
void setWerewolfSkillsAttributes();
void saveStats();
void restoreStats();
void setWerewolfStats();
// For mark/recall magic effects
void markPosition (CellStore* markedCell, const ESM::Position& markedPosition);

@ -62,10 +62,11 @@ Wizard::MainWizard::MainWizard(QWidget *parent) :
setupInstallations();
setupPages();
const boost::filesystem::path& installedPath = mCfgMgr.getInstallPath();
if (!installedPath.empty())
const boost::filesystem::path& installationPath = mCfgMgr.getInstallPath();
if (!installationPath.empty())
{
addInstallation(toQString(installedPath));
const boost::filesystem::path& dataPath = installationPath / "Data Files";
addInstallation(toQString(dataPath));
}
}

@ -493,8 +493,10 @@ bool Config::GameSettings::hasMaster()
{
bool result = false;
QStringList content = mSettings.values(QString(Config::GameSettings::sContentKey));
for (int i = 0; i < content.count(); ++i) {
if (content.at(i).contains(".omwgame") || content.at(i).contains(".esm")) {
for (int i = 0; i < content.count(); ++i)
{
if (content.at(i).endsWith(QLatin1String(".omwgame"), Qt::CaseInsensitive) || content.at(i).endsWith(QLatin1String(".esm"), Qt::CaseInsensitive))
{
result = true;
break;
}

@ -25,6 +25,8 @@ namespace SceneUtil
class ControllerFunction
{
public:
virtual ~ControllerFunction() = default;
virtual float calculate(float input) const = 0;
/// Get the "stop time" of the controller function, typically the maximum of the calculate() function.

@ -90,12 +90,26 @@ difficulty
This setting adjusts the difficulty of the game and is intended to be in the range -100 to 100 inclusive.
Given the default game setting for fDifficultyMult of 5.0,
a value of -100 results in the player taking 80% of the usual damage, doing 6 times the normal damage.
A value of 100 results in the player taking 6 times as much damage, but inflicting only 80% of the usual damage.
Values less than -500 will result in the player receiving no damage,
and values greater than 500 will result in the player inflicting no damage.
A value of 100 results in the player taking 6 times as much damage, while inflicting only 80% of the usual damage.
Values below -500 will result in the player receiving no damage,
and values above 500 will result in the player inflicting no damage.
This setting can be controlled in game with the Difficulty slider in the Prefs panel of the Options menu.
classic reflect absorb attribute behavior
-----------------------------------------
:Type: boolean
:Range: True/False
:Default: True
If this setting is true, "Absorb Attribute" spells which were reflected by the target are not "mirrored",
and the caster will absorb their own attribute resulting in no effect on both the caster and the target.
This makes the gameplay as a mage easier, but these spells become imbalanced.
This is how the original Morrowind behaves.
This setting can only be configured by editing the settings configuration file.
show effect duration
--------------------
@ -108,6 +122,18 @@ The remaining duration is displayed in the tooltip by hovering over the magical
This setting can only be configured by editing the settings configuration file.
enchanted weapons are magical
-----------------------------
:Type: boolean
:Range: True/False
:Default: True
Makes enchanted weapons without Magical flag bypass normal weapons resistance (and weakness) certain creatures have.
This is how original Morrowind behaves.
This setting can only be configured by editing the settings configuration file.
prevent merchant equipping
--------------------------

@ -176,12 +176,18 @@ best attack = false
# Difficulty. Expressed as damage dealt and received. (e.g. -100 to 100).
difficulty = 0
# Replicate how reflected "absorb attribute" spells do not have any effect in Morrowind engine. The caster absorbs the attribute from themselves.
classic reflect absorb attribute behavior = true
# Show duration of magic effect and lights in the spells window.
show effect duration = false
# Prevents merchants from equipping items that are sold to them.
prevent merchant equipping = false
# Make enchanted weaponry without Magical flag bypass normal weapons resistance
enchanted weapons are magical = true
# Makes player followers and escorters start combat with enemies who have started combat with them
# or the player. Otherwise they wait for the enemies or the player to do an attack first.
followers attack on sight = false

Loading…
Cancel
Save