Merge branch 'active-effect-modifiers' into 'master'

Lua bindings for modifying active effects/spells

See merge request OpenMW/openmw!3128
revert-6246b479
Petr Mikheev 2 years ago
commit 0b9bcf58e2

@ -9,6 +9,7 @@
#include <components/resource/resourcesystem.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwmechanics/activespells.hpp"
@ -46,6 +47,8 @@ namespace MWLua
bool isActor() const { return !mActor.ptr().isEmpty() && mActor.ptr().getClass().isActor(); }
bool isLObject() const { return mActor.isLObject(); }
void reset()
{
mIndex = 0;
@ -521,6 +524,18 @@ namespace MWLua
return false;
};
// types.Actor.activeSpells(o):remove(id)
activeSpellsT["remove"] = [](const ActorActiveSpells& spells, const sol::object& spellOrId) {
if (spells.isLObject())
throw std::runtime_error("Local scripts can modify effect only on the actor they are attached to.");
auto id = toSpellId(spellOrId);
if (auto* store = spells.getStore())
{
store->removeEffects(spells.mActor.ptr(), id);
}
};
// pairs(types.Actor.activeEffects(o))
// Note that the indexes are fake, and only for consistency with other lua pairs interfaces. You can't use them
// for anything.
@ -544,12 +559,8 @@ namespace MWLua
});
};
// types.Actor.activeEffects(o):getEffect(id, ?arg)
activeEffectsT["getEffect"] = [](const ActorActiveEffects& effects, std::string_view idStr,
sol::optional<std::string_view> argStr) -> sol::optional<ActiveEffect> {
if (!effects.isActor())
return sol::nullopt;
auto getEffectKey
= [](std::string_view idStr, sol::optional<std::string_view> argStr) -> MWMechanics::EffectKey {
auto id = ESM::MagicEffect::indexNameToIndex(idStr);
auto* rec = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(id);
@ -566,10 +577,73 @@ namespace MWLua
key = MWMechanics::EffectKey(id, ESM::Skill::stringToSkillId(argStr.value()));
}
return key;
};
// types.Actor.activeEffects(o):getEffect(id, ?arg)
activeEffectsT["getEffect"] = [getEffectKey](const ActorActiveEffects& effects, std::string_view idStr,
sol::optional<std::string_view> argStr) -> sol::optional<ActiveEffect> {
if (!effects.isActor())
return sol::nullopt;
MWMechanics::EffectKey key = getEffectKey(idStr, argStr);
if (auto* store = effects.getStore())
if (auto effect = store->get(key))
return ActiveEffect{ key, effect.value() };
return sol::nullopt;
};
// types.Actor.activeEffects(o):removeEffect(id, ?arg)
activeEffectsT["remove"] = [getEffectKey](const ActorActiveEffects& effects, std::string_view idStr,
sol::optional<std::string_view> argStr) {
if (!effects.isActor())
return;
if (effects.isLObject())
throw std::runtime_error("Local scripts can modify effect only on the actor they are attached to.");
MWMechanics::EffectKey key = getEffectKey(idStr, argStr);
// Note that, although this is member method of ActorActiveEffects and we are removing an effect (not a
// spell), we still need to use the active spells store to purge this effect from active spells.
auto ptr = effects.mActor.ptr();
// TODO: The current ActiveSpell API does not allow us to differentiate between skill/attribute parameters
// of effects. So this cannot remove e.g. "Fortify Luck" without also removing all other fortify attribute
// effects such as "Fortify Speed".
auto& activeSpells = ptr.getClass().getCreatureStats(ptr).getActiveSpells();
activeSpells.purgeEffect(ptr, key.mId, key.mArg);
// Now remove any leftover effects that have been added by script/console.
effects.getStore()->remove(key);
};
// types.Actor.activeEffects(o):set(value, id, ?arg)
activeEffectsT["set"] = [getEffectKey](const ActorActiveEffects& effects, int value, std::string_view idStr,
sol::optional<std::string_view> argStr) {
if (!effects.isActor())
return;
if (effects.isLObject())
throw std::runtime_error("Local scripts can modify effect only on the actor they are attached to.");
MWMechanics::EffectKey key = getEffectKey(idStr, argStr);
int currentValue = effects.getStore()->getOrDefault(key).getMagnitude();
effects.getStore()->modifyBase(key, value - currentValue);
};
// types.Actor.activeEffects(o):modify(value, id, ?arg)
activeEffectsT["modify"] = [getEffectKey](const ActorActiveEffects& effects, int value, std::string_view idStr,
sol::optional<std::string_view> argStr) {
if (!effects.isActor())
return;
if (effects.isLObject())
throw std::runtime_error("Local scripts can modify effect only on the actor they are attached to.");
MWMechanics::EffectKey key = getEffectKey(idStr, argStr);
effects.getStore()->modifyBase(key, value);
};
}
}

@ -521,9 +521,15 @@ namespace MWMechanics
purge([=](const ActiveSpellParams& params) { return params.mId == id; }, ptr);
}
void ActiveSpells::purgeEffect(const MWWorld::Ptr& ptr, short effectId)
void ActiveSpells::purgeEffect(const MWWorld::Ptr& ptr, int effectId, int effectArg)
{
purge([=](const ActiveSpellParams&, const ESM::ActiveEffect& effect) { return effect.mEffectId == effectId; },
purge(
[=](const ActiveSpellParams&, const ESM::ActiveEffect& effect) {
if (effectArg < 0)
return effect.mEffectId == effectId;
else
return effect.mEffectId == effectId && effect.mArg == effectArg;
},
ptr);
}

@ -131,7 +131,7 @@ namespace MWMechanics
void removeEffects(const MWWorld::Ptr& ptr, const ESM::RefId& id);
/// Remove all active effects with this effect id
void purgeEffect(const MWWorld::Ptr& ptr, short effectId);
void purgeEffect(const MWWorld::Ptr& ptr, int effectId, int effectArg = -1);
void purge(EffectPredicate predicate, const MWWorld::Ptr& ptr);
void purge(ParamsPredicate predicate, const MWWorld::Ptr& ptr);

@ -192,10 +192,35 @@
-- Get a specific active effect on the actor.
-- @function [parent=#ActorActiveEffects] getEffect
-- @param self
-- @param string effect ID
-- @param string Optional skill or attribute ID
-- @param #string effectId effect ID
-- @param #string extraParam Optional skill or attribute ID
-- @return #ActiveEffect if such an effect is active, nil otherwise
---
-- Completely removes the active effect from the actor.
-- This removes both the effects incurred by active spells and effect added by console, mwscript, or luascript.
-- @function [parent=#ActorActiveEffects] remove
-- @param self
-- @param #string effectId effect ID
-- @param #string extraParam Optional skill or attribute ID
---
-- Permanently modifies the magnitude of an active effect to be exactly equal to the provided value. This adds the effect to the list of active effects if not already active.
-- Note that although the modification is permanent, the magnitude will not stay equal to the value if any active spells with this effects are added/removed.
-- @function [parent=#ActorActiveEffects] set
-- @param self
-- @param #number value
-- @param #string effectId effect ID
-- @param #string extraParam Optional skill or attribute ID
---
-- Permanently modifies the magnitude of an active effect by increasing it by the provided value. This adds the effect to the list of active effects if not already active.
-- @function [parent=#ActorActiveEffects] modify
-- @param self
-- @param #number value
-- @param #string effectId effect ID
-- @param #string extraParam Optional skill or attribute ID
---
-- Return the active spells (@{#ActorActiveSpells}) currently affecting the given actor.
-- @function [parent=#Actor] activeSpells
@ -222,6 +247,12 @@
-- @param #any spellOrId @{openmw.core#Spell} or string spell id
-- @return true if spell is active, false otherwise
---
-- Remove the given spell and all its effects from the given actor's active spells.
-- @function [parent=#ActorActiveSpells] remove
-- @param self
-- @param #any spellOrId @{openmw.core#Spell} or string spell id
---
-- Return the spells (@{#ActorSpells}) of the given actor.
-- @function [parent=#Actor] spells

Loading…
Cancel
Save