1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 04:19:55 +00:00
openmw-tes3mp/apps/openmw/mwscript/statsextensions.cpp
scrawl 29556a1802 More consistent wording of errors/warnings
A Warning indicates a potential problem in the content file(s) that the user told OpenMW to load. E.g. this might cause an object to not display at all or as intended, however the rest of the game will run fine.

An Error, however, is more likely to be a bug with the engine itself - it means that basic assumptions have been violated and the engine might not run correctly anymore.

The above mostly applies to errors/warnings during game-play; startup issues are handled differently: when a file is completely invalid/corrupted to the point that the engine can not start, that might cause messages that are worded as Error due to the severity of the issue but are not necessarily the engine's fault.

Hopefully, being a little more consistent here will alleviate confusion among users as to when a log message should be reported and to whom.
2017-03-04 21:48:31 +01:00

1425 lines
55 KiB
C++

#include "statsextensions.hpp"
#include <iostream>
#include <cmath>
#include <components/esm/loadnpc.hpp>
#include "../mwworld/esmstore.hpp"
#include <components/compiler/extensions.hpp>
#include <components/compiler/opcodes.hpp>
#include <components/interpreter/interpreter.hpp>
#include <components/interpreter/runtime.hpp>
#include <components/interpreter/opcodes.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "../mwmechanics/npcstats.hpp"
#include "../mwmechanics/actorutil.hpp"
#include "interpretercontext.hpp"
#include "ref.hpp"
namespace
{
std::string getDialogueActorFaction(MWWorld::ConstPtr actor)
{
std::string factionId = actor.getClass().getPrimaryFaction(actor);
if (factionId.empty())
throw std::runtime_error (
"failed to determine dialogue actors faction (because actor is factionless)");
return factionId;
}
}
namespace MWScript
{
namespace Stats
{
template<class R>
class OpGetLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value =
ptr.getClass()
.getCreatureStats (ptr)
.getLevel();
runtime.push (value);
}
};
template<class R>
class OpSetLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
ptr.getClass()
.getCreatureStats (ptr)
.setLevel(value);
}
};
template<class R>
class OpGetAttribute : public Interpreter::Opcode0
{
int mIndex;
public:
OpGetAttribute (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value =
ptr.getClass()
.getCreatureStats (ptr)
.getAttribute(mIndex)
.getModified();
runtime.push (value);
}
};
template<class R>
class OpSetAttribute : public Interpreter::Opcode0
{
int mIndex;
public:
OpSetAttribute (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWMechanics::AttributeValue attribute = ptr.getClass().getCreatureStats(ptr).getAttribute(mIndex);
attribute.setBase (value - (attribute.getModified() - attribute.getBase()));
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
}
};
template<class R>
class OpModAttribute : public Interpreter::Opcode0
{
int mIndex;
public:
OpModAttribute (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWMechanics::AttributeValue attribute = ptr.getClass()
.getCreatureStats(ptr)
.getAttribute(mIndex);
attribute.setBase (std::min(100, attribute.getBase() + value));
ptr.getClass().getCreatureStats(ptr).setAttribute(mIndex, attribute);
}
};
template<class R>
class OpGetDynamic : public Interpreter::Opcode0
{
int mIndex;
public:
OpGetDynamic (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float value;
if (mIndex==0 && ptr.getClass().hasItemHealth (ptr))
{
// health is a special case
value = static_cast<Interpreter::Type_Float>(ptr.getClass().getItemMaxHealth(ptr));
} else {
value =
ptr.getClass()
.getCreatureStats(ptr)
.getDynamic(mIndex)
.getCurrent();
}
runtime.push (value);
}
};
template<class R>
class OpSetDynamic : public Interpreter::Opcode0
{
int mIndex;
public:
OpSetDynamic (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float value = runtime[0].mFloat;
runtime.pop();
MWMechanics::DynamicStat<float> stat (ptr.getClass().getCreatureStats (ptr)
.getDynamic (mIndex));
stat.setModified (value, 0);
stat.setCurrent(value);
ptr.getClass().getCreatureStats (ptr).setDynamic (mIndex, stat);
}
};
template<class R>
class OpModDynamic : public Interpreter::Opcode0
{
int mIndex;
public:
OpModDynamic (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
int peek = R::implicit ? 0 : runtime[0].mInteger;
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float diff = runtime[0].mFloat;
runtime.pop();
// workaround broken endgame scripts that kill dagoth ur
if (!R::implicit &&
::Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "dagoth_ur_1"))
{
runtime.push (peek);
if (R()(runtime, false, true).isEmpty())
{
std::cerr
<< "Warning: Compensating for broken script in Morrowind.esm by "
<< "ignoring remote access to dagoth_ur_1" << std::endl;
return;
}
}
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
Interpreter::Type_Float current = stats.getDynamic(mIndex).getCurrent();
MWMechanics::DynamicStat<float> stat (ptr.getClass().getCreatureStats (ptr)
.getDynamic (mIndex));
stat.setModified (diff + stat.getModified(), 0);
stat.setCurrent (diff + current);
ptr.getClass().getCreatureStats (ptr).setDynamic (mIndex, stat);
}
};
template<class R>
class OpModCurrentDynamic : public Interpreter::Opcode0
{
int mIndex;
public:
OpModCurrentDynamic (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Float diff = runtime[0].mFloat;
runtime.pop();
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
Interpreter::Type_Float current = stats.getDynamic(mIndex).getCurrent();
MWMechanics::DynamicStat<float> stat (ptr.getClass().getCreatureStats (ptr)
.getDynamic (mIndex));
// for fatigue, a negative current value is allowed and means the actor will be knocked down
bool allowDecreaseBelowZero = (mIndex == 2);
stat.setCurrent (diff + current, allowDecreaseBelowZero);
ptr.getClass().getCreatureStats (ptr).setDynamic (mIndex, stat);
}
};
template<class R>
class OpGetDynamicGetRatio : public Interpreter::Opcode0
{
int mIndex;
public:
OpGetDynamicGetRatio (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
Interpreter::Type_Float value = 0;
Interpreter::Type_Float max = stats.getDynamic(mIndex).getModified();
if (max>0)
value = stats.getDynamic(mIndex).getCurrent() / max;
runtime.push (value);
}
};
template<class R>
class OpGetSkill : public Interpreter::Opcode0
{
int mIndex;
public:
OpGetSkill (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = ptr.getClass().getSkill(ptr, mIndex);
runtime.push (value);
}
};
template<class R>
class OpSetSkill : public Interpreter::Opcode0
{
int mIndex;
public:
OpSetSkill (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats (ptr);
int newLevel = value - (stats.getSkill(mIndex).getModified() - stats.getSkill(mIndex).getBase());
if (newLevel<0)
newLevel = 0;
stats.getSkill (mIndex).setBase (newLevel);
}
};
template<class R>
class OpModSkill : public Interpreter::Opcode0
{
int mIndex;
public:
OpModSkill (int index) : mIndex (index) {}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats(ptr);
stats.getSkill(mIndex).
setBase (std::min(100, stats.getSkill(mIndex).getBase() + value));
}
};
class OpGetPCCrimeLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr();
runtime.push (static_cast <Interpreter::Type_Float> (player.getClass().getNpcStats (player).getBounty()));
}
};
class OpSetPCCrimeLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr();
int bounty = static_cast<int>(runtime[0].mFloat);
runtime.pop();
player.getClass().getNpcStats (player).setBounty(bounty);
if (bounty == 0)
MWBase::Environment::get().getWorld()->getPlayer().recordCrimeId();
}
};
class OpModPCCrimeLevel : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr();
player.getClass().getNpcStats(player).setBounty(static_cast<int>(runtime[0].mFloat) + player.getClass().getNpcStats(player).getBounty());
runtime.pop();
}
};
template<class R>
class OpAddSpell : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
// make sure a spell with this ID actually exists.
MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (id);
ptr.getClass().getCreatureStats (ptr).getSpells().add (id);
}
};
template<class R>
class OpRemoveSpell : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
ptr.getClass().getCreatureStats (ptr).getSpells().remove (id);
MWBase::WindowManager *wm = MWBase::Environment::get().getWindowManager();
if (ptr == MWMechanics::getPlayer() &&
id == wm->getSelectedSpell())
{
wm->unsetSelectedSpell();
}
}
};
template<class R>
class OpRemoveSpellEffects : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string spellid = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
ptr.getClass().getCreatureStats (ptr).getActiveSpells().removeEffects(spellid);
}
};
template<class R>
class OpRemoveEffects : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer effectId = runtime[0].mInteger;
runtime.pop();
ptr.getClass().getCreatureStats (ptr).getActiveSpells().purgeEffect(effectId);
}
};
template<class R>
class OpGetSpell : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
Interpreter::Type_Integer value = 0;
if (ptr.getClass().getCreatureStats(ptr).getSpells().hasSpell(id))
value = 1;
runtime.push (value);
}
};
template<class R>
class OpPCJoinFaction : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr actor = R()(runtime, false);
std::string factionID = "";
if(arg0==0)
{
factionID = getDialogueActorFaction(actor);
}
else
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
::Misc::StringUtils::lowerCaseInPlace(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
if(factionID != "")
{
MWWorld::Ptr player = MWMechanics::getPlayer();
player.getClass().getNpcStats(player).joinFaction(factionID);
}
}
};
template<class R>
class OpPCRaiseRank : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr actor = R()(runtime, false);
std::string factionID = "";
if(arg0==0)
{
factionID = getDialogueActorFaction(actor);
}
else
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
::Misc::StringUtils::lowerCaseInPlace(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
if(factionID != "")
{
MWWorld::Ptr player = MWMechanics::getPlayer();
if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) == player.getClass().getNpcStats(player).getFactionRanks().end())
{
player.getClass().getNpcStats(player).joinFaction(factionID);
}
else
{
player.getClass().getNpcStats(player).raiseRank(factionID);
}
}
}
};
template<class R>
class OpPCLowerRank : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr actor = R()(runtime, false);
std::string factionID = "";
if(arg0==0)
{
factionID = getDialogueActorFaction(actor);
}
else
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
::Misc::StringUtils::lowerCaseInPlace(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
if(factionID != "")
{
MWWorld::Ptr player = MWMechanics::getPlayer();
player.getClass().getNpcStats(player).lowerRank(factionID);
}
}
};
template<class R>
class OpGetPCRank : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr ptr = R()(runtime, false);
std::string factionID = "";
if(arg0 >0)
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
factionID = ptr.getClass().getPrimaryFaction(ptr);
}
::Misc::StringUtils::lowerCaseInPlace(factionID);
// Make sure this faction exists
MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find(factionID);
MWWorld::Ptr player = MWMechanics::getPlayer();
if(factionID!="")
{
if(player.getClass().getNpcStats(player).getFactionRanks().find(factionID) != player.getClass().getNpcStats(player).getFactionRanks().end())
{
runtime.push(player.getClass().getNpcStats(player).getFactionRanks().at(factionID));
}
else
{
runtime.push(-1);
}
}
else
{
runtime.push(-1);
}
}
};
template<class R>
class OpModDisposition : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
if (ptr.getClass().isNpc())
ptr.getClass().getNpcStats (ptr).setBaseDisposition
(ptr.getClass().getNpcStats (ptr).getBaseDisposition() + value);
// else: must not throw exception (used by an Almalexia dialogue script)
}
};
template<class R>
class OpSetDisposition : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
if (ptr.getClass().isNpc())
ptr.getClass().getNpcStats (ptr).setBaseDisposition (value);
}
};
template<class R>
class OpGetDisposition : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
if (!ptr.getClass().isNpc())
runtime.push(0);
else
runtime.push (MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(ptr));
}
};
class OpGetDeadCount : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
std::string id = runtime.getStringLiteral (runtime[0].mInteger);
runtime[0].mInteger = MWBase::Environment::get().getMechanicsManager()->countDeaths (id);
}
};
template<class R>
class OpGetPCFacRep : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr ptr = R()(runtime, false);
std::string factionId;
if (arg0==1)
{
factionId = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
factionId = getDialogueActorFaction(ptr);
}
if (factionId.empty())
throw std::runtime_error ("failed to determine faction");
::Misc::StringUtils::lowerCaseInPlace (factionId);
MWWorld::Ptr player = MWMechanics::getPlayer();
runtime.push (
player.getClass().getNpcStats (player).getFactionReputation (factionId));
}
};
template<class R>
class OpSetPCFacRep : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr ptr = R()(runtime, false);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::string factionId;
if (arg0==1)
{
factionId = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
factionId = getDialogueActorFaction(ptr);
}
if (factionId.empty())
throw std::runtime_error ("failed to determine faction");
::Misc::StringUtils::lowerCaseInPlace (factionId);
MWWorld::Ptr player = MWMechanics::getPlayer();
player.getClass().getNpcStats (player).setFactionReputation (factionId, value);
}
};
template<class R>
class OpModPCFacRep : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr ptr = R()(runtime, false);
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::string factionId;
if (arg0==1)
{
factionId = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
factionId = getDialogueActorFaction(ptr);
}
if (factionId.empty())
throw std::runtime_error ("failed to determine faction");
::Misc::StringUtils::lowerCaseInPlace (factionId);
MWWorld::Ptr player = MWMechanics::getPlayer();
player.getClass().getNpcStats (player).setFactionReputation (factionId,
player.getClass().getNpcStats (player).getFactionReputation (factionId)+
value);
}
};
template<class R>
class OpGetCommonDisease : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push (ptr.getClass().getCreatureStats (ptr).hasCommonDisease());
}
};
template<class R>
class OpGetBlightDisease : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push (ptr.getClass().getCreatureStats (ptr).hasBlightDisease());
}
};
template<class R>
class OpGetRace : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::ConstPtr ptr = R()(runtime);
std::string race = runtime.getStringLiteral(runtime[0].mInteger);
::Misc::StringUtils::lowerCaseInPlace(race);
runtime.pop();
std::string npcRace = ptr.get<ESM::NPC>()->mBase->mRace;
::Misc::StringUtils::lowerCaseInPlace(npcRace);
runtime.push (npcRace == race);
}
};
class OpGetWerewolfKills : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
runtime.push (ptr.getClass().getNpcStats (ptr).getWerewolfKills ());
}
};
template <class R>
class OpPcExpelled : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr ptr = R()(runtime, false);
std::string factionID = "";
if(arg0 >0 )
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
factionID = ptr.getClass().getPrimaryFaction(ptr);
}
::Misc::StringUtils::lowerCaseInPlace(factionID);
MWWorld::Ptr player = MWMechanics::getPlayer();
if(factionID!="")
{
runtime.push(player.getClass().getNpcStats(player).getExpelled(factionID));
}
else
{
runtime.push(0);
}
}
};
template <class R>
class OpPcExpell : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr ptr = R()(runtime, false);
std::string factionID = "";
if(arg0 >0 )
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
factionID = ptr.getClass().getPrimaryFaction(ptr);
}
MWWorld::Ptr player = MWMechanics::getPlayer();
if(factionID!="")
{
player.getClass().getNpcStats(player).expell(factionID);
}
}
};
template <class R>
class OpPcClearExpelled : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
MWWorld::ConstPtr ptr = R()(runtime, false);
std::string factionID = "";
if(arg0 >0 )
{
factionID = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
factionID = ptr.getClass().getPrimaryFaction(ptr);
}
MWWorld::Ptr player = MWMechanics::getPlayer();
if(factionID!="")
player.getClass().getNpcStats(player).clearExpelled(factionID);
}
};
template <class R>
class OpRaiseRank : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = ptr.getClass().getPrimaryFaction(ptr);
if(factionID.empty())
return;
MWWorld::Ptr player = MWMechanics::getPlayer();
// no-op when executed on the player
if (ptr == player)
return;
ptr.getClass().getNpcStats(ptr).raiseRank(factionID);
}
};
template <class R>
class OpLowerRank : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
std::string factionID = ptr.getClass().getPrimaryFaction(ptr);
if(factionID.empty())
return;
MWWorld::Ptr player = MWMechanics::getPlayer();
// no-op when executed on the player
if (ptr == player)
return;
ptr.getClass().getNpcStats(ptr).lowerRank(factionID);
}
};
template <class R>
class OpOnDeath : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value =
ptr.getClass().getCreatureStats (ptr).hasDied();
if (value)
ptr.getClass().getCreatureStats (ptr).clearHasDied();
runtime.push (value);
}
};
template <class R>
class OpOnMurder : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value =
ptr.getClass().getCreatureStats (ptr).hasBeenMurdered();
if (value)
ptr.getClass().getCreatureStats (ptr).clearHasBeenMurdered();
runtime.push (value);
}
};
template <class R>
class OpOnKnockout : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
Interpreter::Type_Integer value =
ptr.getClass().getCreatureStats (ptr).getKnockedDownOneFrame();
runtime.push (value);
}
};
template <class R>
class OpIsWerewolf : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push(ptr.getClass().getNpcStats(ptr).isWerewolf());
}
};
template <class R, bool set>
class OpSetWerewolf : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptr, set);
}
};
template <class R>
class OpSetWerewolfAcrobatics : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWBase::Environment::get().getMechanicsManager()->applyWerewolfAcrobatics(ptr);
}
};
template <class R>
class OpResurrect : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
if (ptr == MWMechanics::getPlayer())
ptr.getClass().getCreatureStats(ptr).resurrect();
else if (ptr.getClass().getCreatureStats(ptr).isDead())
{
bool wasEnabled = ptr.getRefData().isEnabled();
MWBase::Environment::get().getWorld()->undeleteObject(ptr);
MWBase::Environment::get().getWorld()->removeContainerScripts(ptr);
// HACK: disable/enable object to re-add it to the scene properly (need a new Animation).
MWBase::Environment::get().getWorld()->disable(ptr);
// resets runtime state such as inventory, stats and AI. does not reset position in the world
ptr.getRefData().setCustomData(NULL);
if (wasEnabled)
MWBase::Environment::get().getWorld()->enable(ptr);
}
}
};
template <class R>
class OpGetStat : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
// dummy
runtime.push(0);
}
};
template <class R>
class OpGetMagicEffect : public Interpreter::Opcode0
{
int mPositiveEffect;
int mNegativeEffect;
public:
OpGetMagicEffect (int positiveEffect, int negativeEffect)
: mPositiveEffect(positiveEffect)
, mNegativeEffect(negativeEffect)
{
}
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
const MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
float currentValue = effects.get(mPositiveEffect).getMagnitude();
if (mNegativeEffect != -1)
currentValue -= effects.get(mNegativeEffect).getMagnitude();
int ret = static_cast<int>(currentValue);
runtime.push(ret);
}
};
template <class R>
class OpSetMagicEffect : public Interpreter::Opcode0
{
int mPositiveEffect;
int mNegativeEffect;
public:
OpSetMagicEffect (int positiveEffect, int negativeEffect)
: mPositiveEffect(positiveEffect)
, mNegativeEffect(negativeEffect)
{
}
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::MagicEffects& effects = ptr.getClass().getCreatureStats(ptr).getMagicEffects();
float currentValue = effects.get(mPositiveEffect).getMagnitude();
if (mNegativeEffect != -1)
currentValue -= effects.get(mNegativeEffect).getMagnitude();
int arg = runtime[0].mInteger;
runtime.pop();
effects.modifyBase(mPositiveEffect, (arg - static_cast<int>(currentValue)));
}
};
template <class R>
class OpModMagicEffect : public Interpreter::Opcode0
{
int mPositiveEffect;
int mNegativeEffect;
public:
OpModMagicEffect (int positiveEffect, int negativeEffect)
: mPositiveEffect(positiveEffect)
, mNegativeEffect(negativeEffect)
{
}
virtual void execute(Interpreter::Runtime &runtime)
{
MWWorld::Ptr ptr = R()(runtime);
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
int arg = runtime[0].mInteger;
runtime.pop();
stats.getMagicEffects().modifyBase(mPositiveEffect, arg);
}
};
struct MagicEffect
{
int mPositiveEffect;
int mNegativeEffect;
};
void installOpcodes (Interpreter::Interpreter& interpreter)
{
for (int i=0; i<Compiler::Stats::numberOfAttributes; ++i)
{
interpreter.installSegment5 (Compiler::Stats::opcodeGetAttribute+i, new OpGetAttribute<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeGetAttributeExplicit+i,
new OpGetAttribute<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeSetAttribute+i, new OpSetAttribute<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeSetAttributeExplicit+i,
new OpSetAttribute<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModAttribute+i, new OpModAttribute<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModAttributeExplicit+i,
new OpModAttribute<ExplicitRef> (i));
}
for (int i=0; i<Compiler::Stats::numberOfDynamics; ++i)
{
interpreter.installSegment5 (Compiler::Stats::opcodeGetDynamic+i, new OpGetDynamic<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeGetDynamicExplicit+i,
new OpGetDynamic<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeSetDynamic+i, new OpSetDynamic<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeSetDynamicExplicit+i,
new OpSetDynamic<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModDynamic+i, new OpModDynamic<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModDynamicExplicit+i,
new OpModDynamic<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModCurrentDynamic+i,
new OpModCurrentDynamic<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModCurrentDynamicExplicit+i,
new OpModCurrentDynamic<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeGetDynamicGetRatio+i,
new OpGetDynamicGetRatio<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeGetDynamicGetRatioExplicit+i,
new OpGetDynamicGetRatio<ExplicitRef> (i));
}
for (int i=0; i<Compiler::Stats::numberOfSkills; ++i)
{
interpreter.installSegment5 (Compiler::Stats::opcodeGetSkill+i, new OpGetSkill<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeGetSkillExplicit+i, new OpGetSkill<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeSetSkill+i, new OpSetSkill<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeSetSkillExplicit+i, new OpSetSkill<ExplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModSkill+i, new OpModSkill<ImplicitRef> (i));
interpreter.installSegment5 (Compiler::Stats::opcodeModSkillExplicit+i, new OpModSkill<ExplicitRef> (i));
}
interpreter.installSegment5 (Compiler::Stats::opcodeGetPCCrimeLevel, new OpGetPCCrimeLevel);
interpreter.installSegment5 (Compiler::Stats::opcodeSetPCCrimeLevel, new OpSetPCCrimeLevel);
interpreter.installSegment5 (Compiler::Stats::opcodeModPCCrimeLevel, new OpModPCCrimeLevel);
interpreter.installSegment5 (Compiler::Stats::opcodeAddSpell, new OpAddSpell<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeAddSpellExplicit, new OpAddSpell<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpell, new OpRemoveSpell<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellExplicit,
new OpRemoveSpell<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellEffects, new OpRemoveSpellEffects<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveSpellEffectsExplicit,
new OpRemoveSpellEffects<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeResurrect, new OpResurrect<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeResurrectExplicit,
new OpResurrect<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveEffects, new OpRemoveEffects<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRemoveEffectsExplicit,
new OpRemoveEffects<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpell, new OpGetSpell<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetSpellExplicit, new OpGetSpell<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRank,new OpPCRaiseRank<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCLowerRank,new OpPCLowerRank<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCJoinFaction,new OpPCJoinFaction<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCRaiseRankExplicit,new OpPCRaiseRank<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCLowerRankExplicit,new OpPCLowerRank<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodePCJoinFactionExplicit,new OpPCJoinFaction<ExplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodeGetPCRank,new OpGetPCRank<ImplicitRef>);
interpreter.installSegment3(Compiler::Stats::opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>);
interpreter.installSegment5(Compiler::Stats::opcodeModDisposition,new OpModDisposition<ImplicitRef>);
interpreter.installSegment5(Compiler::Stats::opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>);
interpreter.installSegment5(Compiler::Stats::opcodeSetDisposition,new OpSetDisposition<ImplicitRef>);
interpreter.installSegment5(Compiler::Stats::opcodeSetDispositionExplicit,new OpSetDisposition<ExplicitRef>);
interpreter.installSegment5(Compiler::Stats::opcodeGetDisposition,new OpGetDisposition<ImplicitRef>);
interpreter.installSegment5(Compiler::Stats::opcodeGetDispositionExplicit,new OpGetDisposition<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetLevel, new OpGetLevel<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetLevelExplicit, new OpGetLevel<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeSetLevel, new OpSetLevel<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeSetLevelExplicit, new OpSetLevel<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetDeadCount, new OpGetDeadCount);
interpreter.installSegment3 (Compiler::Stats::opcodeGetPCFacRep, new OpGetPCFacRep<ImplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodeGetPCFacRepExplicit, new OpGetPCFacRep<ExplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodeSetPCFacRep, new OpSetPCFacRep<ImplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodeSetPCFacRepExplicit, new OpSetPCFacRep<ExplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodeModPCFacRep, new OpModPCFacRep<ImplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodeModPCFacRepExplicit, new OpModPCFacRep<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetCommonDisease, new OpGetCommonDisease<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetCommonDiseaseExplicit, new OpGetCommonDisease<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetBlightDisease, new OpGetBlightDisease<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetBlightDiseaseExplicit, new OpGetBlightDisease<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetRace, new OpGetRace<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetRaceExplicit, new OpGetRace<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetWerewolfKills, new OpGetWerewolfKills);
interpreter.installSegment3 (Compiler::Stats::opcodePcExpelled, new OpPcExpelled<ImplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodePcExpelledExplicit, new OpPcExpelled<ExplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodePcExpell, new OpPcExpell<ImplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodePcExpellExplicit, new OpPcExpell<ExplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodePcClearExpelled, new OpPcClearExpelled<ImplicitRef>);
interpreter.installSegment3 (Compiler::Stats::opcodePcClearExpelledExplicit, new OpPcClearExpelled<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRaiseRank, new OpRaiseRank<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeRaiseRankExplicit, new OpRaiseRank<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeLowerRank, new OpLowerRank<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeLowerRankExplicit, new OpLowerRank<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeOnDeath, new OpOnDeath<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeOnDeathExplicit, new OpOnDeath<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeOnMurder, new OpOnMurder<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeOnMurderExplicit, new OpOnMurder<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeOnKnockout, new OpOnKnockout<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeOnKnockoutExplicit, new OpOnKnockout<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeIsWerewolf, new OpIsWerewolf<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeIsWerewolfExplicit, new OpIsWerewolf<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeBecomeWerewolf, new OpSetWerewolf<ImplicitRef, true>);
interpreter.installSegment5 (Compiler::Stats::opcodeBecomeWerewolfExplicit, new OpSetWerewolf<ExplicitRef, true>);
interpreter.installSegment5 (Compiler::Stats::opcodeUndoWerewolf, new OpSetWerewolf<ImplicitRef, false>);
interpreter.installSegment5 (Compiler::Stats::opcodeUndoWerewolfExplicit, new OpSetWerewolf<ExplicitRef, false>);
interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobatics, new OpSetWerewolfAcrobatics<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeSetWerewolfAcrobaticsExplicit, new OpSetWerewolfAcrobatics<ExplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetStat, new OpGetStat<ImplicitRef>);
interpreter.installSegment5 (Compiler::Stats::opcodeGetStatExplicit, new OpGetStat<ExplicitRef>);
static const MagicEffect sMagicEffects[] = {
{ ESM::MagicEffect::ResistMagicka, ESM::MagicEffect::WeaknessToMagicka },
{ ESM::MagicEffect::ResistFire, ESM::MagicEffect::WeaknessToFire },
{ ESM::MagicEffect::ResistFrost, ESM::MagicEffect::WeaknessToFrost },
{ ESM::MagicEffect::ResistShock, ESM::MagicEffect::WeaknessToShock },
{ ESM::MagicEffect::ResistCommonDisease, ESM::MagicEffect::WeaknessToCommonDisease },
{ ESM::MagicEffect::ResistBlightDisease, ESM::MagicEffect::WeaknessToBlightDisease },
{ ESM::MagicEffect::ResistCorprusDisease, ESM::MagicEffect::WeaknessToCorprusDisease },
{ ESM::MagicEffect::ResistPoison, ESM::MagicEffect::WeaknessToPoison },
{ ESM::MagicEffect::ResistParalysis, -1 },
{ ESM::MagicEffect::ResistNormalWeapons, ESM::MagicEffect::WeaknessToNormalWeapons },
{ ESM::MagicEffect::WaterBreathing, -1 },
{ ESM::MagicEffect::Chameleon, -1 },
{ ESM::MagicEffect::WaterWalking, -1 },
{ ESM::MagicEffect::SwiftSwim, -1 },
{ ESM::MagicEffect::Jump, -1 },
{ ESM::MagicEffect::Levitate, -1 },
{ ESM::MagicEffect::Shield, -1 },
{ ESM::MagicEffect::Sound, -1 },
{ ESM::MagicEffect::Silence, -1 },
{ ESM::MagicEffect::Blind, -1 },
{ ESM::MagicEffect::Paralyze, -1 },
{ ESM::MagicEffect::Invisibility, -1 },
{ ESM::MagicEffect::FortifyAttack, -1 },
{ ESM::MagicEffect::Sanctuary, -1 },
};
for (int i=0; i<24; ++i)
{
int positive = sMagicEffects[i].mPositiveEffect;
int negative = sMagicEffects[i].mNegativeEffect;
interpreter.installSegment5 (Compiler::Stats::opcodeGetMagicEffect+i, new OpGetMagicEffect<ImplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeGetMagicEffectExplicit+i, new OpGetMagicEffect<ExplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeSetMagicEffect+i, new OpSetMagicEffect<ImplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeSetMagicEffectExplicit+i, new OpSetMagicEffect<ExplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeModMagicEffect+i, new OpModMagicEffect<ImplicitRef> (positive, negative));
interpreter.installSegment5 (Compiler::Stats::opcodeModMagicEffectExplicit+i, new OpModMagicEffect<ExplicitRef> (positive, negative));
}
}
}
}