mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-11 00:44:33 +00:00
Merge pull request #2655 from Capostrophic/spellcasting
Fix reported spellcasting discrepancies
This commit is contained in:
commit
70f6e1c81d
@ -188,6 +188,8 @@
|
|||||||
Bug #5226: Reputation should be capped
|
Bug #5226: Reputation should be capped
|
||||||
Bug #5229: Crash if mesh controller node has no data node
|
Bug #5229: Crash if mesh controller node has no data node
|
||||||
Bug #5239: OpenMW-CS does not support non-ASCII characters in path names
|
Bug #5239: OpenMW-CS does not support non-ASCII characters in path names
|
||||||
|
Bug #5241: On-self absorb spells cannot be detected
|
||||||
|
Bug #5242: ExplodeSpell behavior differs from Cast behavior
|
||||||
Feature #1774: Handle AvoidNode
|
Feature #1774: Handle AvoidNode
|
||||||
Feature #2229: Improve pathfinding AI
|
Feature #2229: Improve pathfinding AI
|
||||||
Feature #3025: Analogue gamepad movement controls
|
Feature #3025: Analogue gamepad movement controls
|
||||||
|
@ -447,9 +447,9 @@ namespace MWMechanics
|
|||||||
if (!checkEffectTarget(effectIt->mEffectID, target, caster, castByPlayer))
|
if (!checkEffectTarget(effectIt->mEffectID, target, caster, castByPlayer))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// caster needs to be an actor that's not the target for linked effects (e.g. Absorb)
|
// caster needs to be an actor for linked effects (e.g. Absorb)
|
||||||
if (magicEffect->mData.mFlags & ESM::MagicEffect::CasterLinked
|
if (magicEffect->mData.mFlags & ESM::MagicEffect::CasterLinked
|
||||||
&& (caster.isEmpty() || !caster.getClass().isActor() || caster == target))
|
&& (caster.isEmpty() || !caster.getClass().isActor()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If player is healing someone, show the target's HP bar
|
// If player is healing someone, show the target's HP bar
|
||||||
@ -552,6 +552,15 @@ namespace MWMechanics
|
|||||||
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
effect.mArg = MWMechanics::EffectKey(*effectIt).mArg;
|
||||||
effect.mMagnitude = magnitude;
|
effect.mMagnitude = magnitude;
|
||||||
|
|
||||||
|
// Avoid applying absorb effects if the caster is the target
|
||||||
|
// We still need the spell to be added
|
||||||
|
if (caster == target
|
||||||
|
&& effectIt->mEffectID >= ESM::MagicEffect::AbsorbAttribute
|
||||||
|
&& effectIt->mEffectID <= ESM::MagicEffect::AbsorbSkill)
|
||||||
|
{
|
||||||
|
effect.mMagnitude = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
bool hasDuration = !(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration);
|
||||||
if (hasDuration && effectIt->mDuration == 0)
|
if (hasDuration && effectIt->mDuration == 0)
|
||||||
{
|
{
|
||||||
@ -600,21 +609,19 @@ namespace MWMechanics
|
|||||||
// magnitude, since we're transferring stats from the target to the caster
|
// magnitude, since we're transferring stats from the target to the caster
|
||||||
if (!caster.isEmpty() && caster != target && caster.getClass().isActor())
|
if (!caster.isEmpty() && caster != target && caster.getClass().isActor())
|
||||||
{
|
{
|
||||||
for (int i=0; i<5; ++i)
|
if (effectIt->mEffectID >= ESM::MagicEffect::AbsorbAttribute &&
|
||||||
|
effectIt->mEffectID <= ESM::MagicEffect::AbsorbSkill)
|
||||||
{
|
{
|
||||||
if (effectIt->mEffectID == ESM::MagicEffect::AbsorbAttribute+i)
|
std::vector<ActiveSpells::ActiveEffect> absorbEffects;
|
||||||
{
|
ActiveSpells::ActiveEffect effect_ = effect;
|
||||||
std::vector<ActiveSpells::ActiveEffect> absorbEffects;
|
effect_.mMagnitude *= -1;
|
||||||
ActiveSpells::ActiveEffect effect_ = effect;
|
absorbEffects.push_back(effect_);
|
||||||
effect_.mMagnitude *= -1;
|
if (reflected && Settings::Manager::getBool("classic reflected absorb spells behavior", "Game"))
|
||||||
absorbEffects.push_back(effect_);
|
target.getClass().getCreatureStats(target).getActiveSpells().addSpell("", true,
|
||||||
if (reflected && Settings::Manager::getBool("classic reflected absorb spells behavior", "Game"))
|
absorbEffects, mSourceName, caster.getClass().getCreatureStats(caster).getActorId());
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().addSpell("", true,
|
else
|
||||||
absorbEffects, mSourceName, caster.getClass().getCreatureStats(caster).getActorId());
|
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
|
||||||
else
|
absorbEffects, mSourceName, target.getClass().getCreatureStats(target).getActorId());
|
||||||
caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell("", true,
|
|
||||||
absorbEffects, mSourceName, target.getClass().getCreatureStats(target).getActorId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1109,18 +1109,9 @@ namespace MWScript
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power)
|
|
||||||
{
|
|
||||||
runtime.getContext().report("spellcasting failed: you can only cast spells and powers.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr == MWMechanics::getPlayer())
|
if (ptr == MWMechanics::getPlayer())
|
||||||
{
|
{
|
||||||
MWWorld::InventoryStore& store = ptr.getClass().getInventoryStore(ptr);
|
MWBase::Environment::get().getWorld()->getPlayer().setSelectedSpell(spellId);
|
||||||
store.setSelectedEnchantItem(store.end());
|
|
||||||
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, ptr)));
|
|
||||||
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,7 +1119,6 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
MWMechanics::AiCast castPackage(targetId, spellId, true);
|
MWMechanics::AiCast castPackage(targetId, spellId, true);
|
||||||
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(castPackage, ptr);
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(castPackage, ptr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1152,9 +1142,29 @@ namespace MWScript
|
|||||||
{
|
{
|
||||||
MWWorld::Ptr ptr = R()(runtime);
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
|
||||||
std::string spell = runtime.getStringLiteral (runtime[0].mInteger);
|
std::string spellId = runtime.getStringLiteral (runtime[0].mInteger);
|
||||||
runtime.pop();
|
runtime.pop();
|
||||||
|
|
||||||
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(spellId);
|
||||||
|
if (!spell)
|
||||||
|
{
|
||||||
|
runtime.getContext().report("spellcasting failed: cannot find spell \""+spellId+"\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr == MWMechanics::getPlayer())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setSelectedSpell(spellId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptr.getClass().isActor())
|
||||||
|
{
|
||||||
|
MWMechanics::AiCast castPackage(ptr.getCellRef().getRefId(), spellId, true);
|
||||||
|
ptr.getClass().getCreatureStats (ptr).getAiSequence().stack(castPackage, ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MWMechanics::CastSpell cast(ptr, ptr, false, true);
|
MWMechanics::CastSpell cast(ptr, ptr, false, true);
|
||||||
cast.mHitPosition = ptr.getRefData().getPosition().asVec3();
|
cast.mHitPosition = ptr.getRefData().getPosition().asVec3();
|
||||||
cast.mAlwaysSucceed = true;
|
cast.mAlwaysSucceed = true;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <components/esm/loadbsgn.hpp>
|
#include <components/esm/loadbsgn.hpp>
|
||||||
|
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
@ -19,6 +20,7 @@
|
|||||||
|
|
||||||
#include "../mwmechanics/movement.hpp"
|
#include "../mwmechanics/movement.hpp"
|
||||||
#include "../mwmechanics/npcstats.hpp"
|
#include "../mwmechanics/npcstats.hpp"
|
||||||
|
#include "../mwmechanics/spellcasting.hpp"
|
||||||
|
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
#include "ptr.hpp"
|
#include "ptr.hpp"
|
||||||
@ -492,4 +494,14 @@ namespace MWWorld
|
|||||||
{
|
{
|
||||||
mPreviousItems.erase(boundItemId);
|
mPreviousItems.erase(boundItemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::setSelectedSpell(const std::string& spellId)
|
||||||
|
{
|
||||||
|
Ptr player = getPlayer();
|
||||||
|
InventoryStore& store = player.getClass().getInventoryStore(player);
|
||||||
|
store.setSelectedEnchantItem(store.end());
|
||||||
|
int castChance = int(MWMechanics::getSpellSuccessChance(spellId, player));
|
||||||
|
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, castChance);
|
||||||
|
MWBase::Environment::get().getWindowManager()->updateSpellWindow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,8 @@ namespace MWWorld
|
|||||||
void setPreviousItem(const std::string& boundItemId, const std::string& previousItemId);
|
void setPreviousItem(const std::string& boundItemId, const std::string& previousItemId);
|
||||||
std::string getPreviousItem(const std::string& boundItemId);
|
std::string getPreviousItem(const std::string& boundItemId);
|
||||||
void erasePreviousItem(const std::string& boundItemId);
|
void erasePreviousItem(const std::string& boundItemId);
|
||||||
|
|
||||||
|
void setSelectedSpell(const std::string& spellId);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user