1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-03 23:45:33 +00:00

Merge branch 'master' of git://github.com/zinnschlag/openmw into globalmap

This commit is contained in:
scrawl 2012-11-16 22:28:00 +01:00
commit 8ef3edd416
26 changed files with 872 additions and 204 deletions

View file

@ -63,7 +63,7 @@ add_openmw_dir (mwclass
add_openmw_dir (mwmechanics add_openmw_dir (mwmechanics
mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells mechanicsmanagerimp stat creaturestats magiceffects movement actors drawstate spells
activespells npcstats aipackage aisequence alchemy activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow aiescort aiactivate
) )
add_openmw_dir (mwbase add_openmw_dir (mwbase

View file

@ -356,7 +356,7 @@ void OMW::Engine::go()
// Create dialog system // Create dialog system
mEnvironment.setJournal (new MWDialogue::Journal); mEnvironment.setJournal (new MWDialogue::Journal);
mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions)); mEnvironment.setDialogueManager (new MWDialogue::DialogueManager (mExtensions, mVerboseScripts));
// Sets up the input system // Sets up the input system
mEnvironment.setInputManager (new MWInput::InputManager (*mOgre, mEnvironment.setInputManager (new MWInput::InputManager (*mOgre,

View file

@ -75,11 +75,11 @@ namespace
namespace MWDialogue namespace MWDialogue
{ {
DialogueManager::DialogueManager (const Compiler::Extensions& extensions) : DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose) :
mCompilerContext (MWScript::CompilerContext::Type_Dialgoue), mCompilerContext (MWScript::CompilerContext::Type_Dialgoue),
mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream) mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream)
, mTemporaryDispositionChange(0.f) , mTemporaryDispositionChange(0.f)
, mPermanentDispositionChange(0.f) , mPermanentDispositionChange(0.f), mScriptVerbose (scriptVerbose)
{ {
mChoice = -1; mChoice = -1;
mIsInChoice = false; mIsInChoice = false;
@ -129,7 +129,7 @@ namespace MWDialogue
mIsInChoice = false; mIsInChoice = false;
mActor = actor; mActor = actor;
MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor); MWMechanics::CreatureStats& creatureStats = MWWorld::Class::get (actor).getCreatureStats (actor);
mTalkedTo = creatureStats.hasTalkedToPlayer(); mTalkedTo = creatureStats.hasTalkedToPlayer();
creatureStats.talkedToPlayer(); creatureStats.talkedToPlayer();
@ -174,6 +174,8 @@ namespace MWDialogue
bool DialogueManager::compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code) bool DialogueManager::compile (const std::string& cmd,std::vector<Interpreter::Type_Code>& code)
{ {
bool success = true;
try try
{ {
mErrorHandler.reset(); mErrorHandler.reset();
@ -195,23 +197,33 @@ namespace MWDialogue
Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false); Compiler::ScriptParser parser(mErrorHandler,mCompilerContext, locals, false);
scanner.scan (parser); scanner.scan (parser);
if(mErrorHandler.isGood())
{ if (!mErrorHandler.isGood())
parser.getCode(code); success = false;
return true;
} if (success)
return false; parser.getCode (code);
} }
catch (const Compiler::SourceException& /* error */) catch (const Compiler::SourceException& /* error */)
{ {
// error has already been reported via error handler // error has already been reported via error handler
success = false;
} }
catch (const std::exception& error) catch (const std::exception& error)
{ {
printError (std::string ("An exception has been thrown: ") + error.what()); std::cerr << std::string ("Dialogue error: An exception has been thrown: ") + error.what() << std::endl;
success = false;
} }
return false; if (!success && mScriptVerbose)
{
std::cerr
<< "compiling failed (dialogue script)" << std::endl
<< cmd
<< std::endl << std::endl;
}
return success;
} }
void DialogueManager::executeScript (const std::string& script) void DialogueManager::executeScript (const std::string& script)
@ -228,7 +240,7 @@ namespace MWDialogue
} }
catch (const std::exception& error) catch (const std::exception& error)
{ {
printError (std::string ("An exception has been thrown: ") + error.what()); std::cerr << std::string ("Dialogue error: An exception has been thrown: ") + error.what();
} }
} }
} }
@ -252,7 +264,7 @@ namespace MWDialogue
if (filter.search (*iter)) if (filter.search (*iter))
{ {
mActorKnownTopics.push_back (toLower (iter->mId)); mActorKnownTopics.push_back (toLower (iter->mId));
//does the player know the topic? //does the player know the topic?
if (mKnownTopics.find (toLower (iter->mId)) != mKnownTopics.end()) if (mKnownTopics.find (toLower (iter->mId)) != mKnownTopics.end())
{ {
@ -328,8 +340,8 @@ namespace MWDialogue
if (mDialogueMap[keyword].mType == ESM::Dialogue::Topic) if (mDialogueMap[keyword].mType == ESM::Dialogue::Topic)
{ {
Filter filter (mActor, mChoice, mTalkedTo); Filter filter (mActor, mChoice, mTalkedTo);
if (const ESM::DialInfo *info = filter.search (mDialogueMap[keyword])) if (const ESM::DialInfo *info = filter.search (mDialogueMap[keyword]))
{ {
std::string text = info->mResponse; std::string text = info->mResponse;
std::string script = info->mResultScript; std::string script = info->mResultScript;
@ -377,7 +389,7 @@ namespace MWDialogue
if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic) if (mDialogueMap[mLastTopic].mType == ESM::Dialogue::Topic)
{ {
Filter filter (mActor, mChoice, mTalkedTo); Filter filter (mActor, mChoice, mTalkedTo);
if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic])) if (const ESM::DialInfo *info = filter.search (mDialogueMap[mLastTopic]))
{ {
mChoiceMap.clear(); mChoiceMap.clear();
@ -392,7 +404,7 @@ namespace MWDialogue
} }
} }
} }
updateTopics(); updateTopics();
} }
} }

View file

@ -35,6 +35,7 @@ namespace MWDialogue
float mTemporaryDispositionChange; float mTemporaryDispositionChange;
float mPermanentDispositionChange; float mPermanentDispositionChange;
bool mScriptVerbose;
void parseText (const std::string& text); void parseText (const std::string& text);
@ -47,7 +48,7 @@ namespace MWDialogue
public: public:
DialogueManager (const Compiler::Extensions& extensions); DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose);
virtual void startDialogue (const MWWorld::Ptr& actor); virtual void startDialogue (const MWWorld::Ptr& actor);

View file

@ -74,7 +74,7 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
if (iter==stats.getFactionRanks().end()) if (iter==stats.getFactionRanks().end())
return false; return false;
// check rank // check rank
if (iter->second < info.mData.mRank) if (iter->second < info.mData.mRank)
return false; return false;
@ -87,14 +87,14 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
if (info.mData.mGender==(npc->mBase->mFlags & npc->mBase->Female ? 0 : 1)) if (info.mData.mGender==(npc->mBase->mFlags & npc->mBase->Female ? 0 : 1))
return false; return false;
} }
return true; return true;
} }
bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const bool MWDialogue::Filter::testPlayer (const ESM::DialInfo& info) const
{ {
const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
// check player faction // check player faction
if (!info.mPcFaction.empty()) if (!info.mPcFaction.empty())
{ {
@ -123,7 +123,7 @@ bool MWDialogue::Filter::testSelectStructs (const ESM::DialInfo& info) const
iter != info.mSelects.end(); ++iter) iter != info.mSelects.end(); ++iter)
if (!testSelectStruct (*iter)) if (!testSelectStruct (*iter))
return false; return false;
return true; return true;
} }
@ -131,7 +131,7 @@ bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
{ {
if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name()) if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name())
return select.isInverted(); return select.isInverted();
switch (select.getType()) switch (select.getType())
{ {
case SelectWrapper::Type_None: return true; case SelectWrapper::Type_None: return true;
@ -139,7 +139,7 @@ bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const
case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select);
case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select)); case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select));
} }
return true; return true;
} }
@ -148,11 +148,11 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
switch (select.getFunction()) switch (select.getFunction())
{ {
case SelectWrapper::Function_Global: case SelectWrapper::Function_Global:
// internally all globals are float :( // internally all globals are float :(
return select.selectCompare ( return select.selectCompare (
MWBase::Environment::get().getWorld()->getGlobalVariable (select.getName()).mFloat); MWBase::Environment::get().getWorld()->getGlobalVariable (select.getName()).mFloat);
case SelectWrapper::Function_Local: case SelectWrapper::Function_Local:
{ {
std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor); std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor);
@ -178,7 +178,7 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
if (i<script->mData.mNumShorts) if (i<script->mData.mNumShorts)
return select.selectCompare (static_cast<int> (locals.mShorts[i])); return select.selectCompare (static_cast<int> (locals.mShorts[i]));
i -= script->mData.mNumShorts; i -= script->mData.mNumShorts;
if (i<script->mData.mNumLongs) if (i<script->mData.mNumLongs)
@ -186,39 +186,39 @@ bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) c
i -= script->mData.mNumShorts; i -= script->mData.mNumShorts;
return select.selectCompare (locals.mFloats.at (i)); return select.selectCompare (locals.mFloats.at (i));
} }
case SelectWrapper::Function_PcHealthPercent: case SelectWrapper::Function_PcHealthPercent:
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() / float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() /
MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified(); MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified();
return select.selectCompare (ratio); return select.selectCompare (ratio);
} }
case SelectWrapper::Function_PcDynamicStat: case SelectWrapper::Function_PcDynamicStat:
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
float value = MWWorld::Class::get (player).getCreatureStats (player). float value = MWWorld::Class::get (player).getCreatureStats (player).
getDynamic (select.getArgument()).getCurrent(); getDynamic (select.getArgument()).getCurrent();
return select.selectCompare (value); return select.selectCompare (value);
} }
case SelectWrapper::Function_HealthPercent: case SelectWrapper::Function_HealthPercent:
{ {
float ratio = MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getCurrent() / float ratio = MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getCurrent() /
MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getModified(); MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getModified();
return select.selectCompare (ratio); return select.selectCompare (ratio);
} }
default: default:
throw std::runtime_error ("unknown numeric select function"); throw std::runtime_error ("unknown numeric select function");
} }
} }
@ -230,11 +230,11 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
switch (select.getFunction()) switch (select.getFunction())
{ {
case SelectWrapper::Function_Journal: case SelectWrapper::Function_Journal:
return MWBase::Environment::get().getJournal()->getJournalIndex (select.getName()); return MWBase::Environment::get().getJournal()->getJournalIndex (select.getName());
case SelectWrapper::Function_Item: case SelectWrapper::Function_Item:
{ {
MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player); MWWorld::ContainerStore& store = MWWorld::Class::get (player).getContainerStore (player);
int sum = 0; int sum = 0;
@ -244,39 +244,39 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter) for (MWWorld::ContainerStoreIterator iter (store.begin()); iter!=store.end(); ++iter)
if (toLower(iter->getCellRef().mRefID) == name) if (toLower(iter->getCellRef().mRefID) == name)
sum += iter->getRefData().getCount(); sum += iter->getRefData().getCount();
return sum; return sum;
} }
case SelectWrapper::Function_Dead: case SelectWrapper::Function_Dead:
return MWBase::Environment::get().getMechanicsManager()->countDeaths (select.getName()); return MWBase::Environment::get().getMechanicsManager()->countDeaths (select.getName());
case SelectWrapper::Function_Choice: case SelectWrapper::Function_Choice:
return mChoice; return mChoice;
case SelectWrapper::Function_AiSetting: case SelectWrapper::Function_AiSetting:
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (select.getArgument()); return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAiSetting (select.getArgument());
case SelectWrapper::Function_PcAttribute: case SelectWrapper::Function_PcAttribute:
return MWWorld::Class::get (player).getCreatureStats (player). return MWWorld::Class::get (player).getCreatureStats (player).
getAttribute (select.getArgument()).getModified(); getAttribute (select.getArgument()).getModified();
case SelectWrapper::Function_PcSkill: case SelectWrapper::Function_PcSkill:
return static_cast<int> (MWWorld::Class::get (player). return static_cast<int> (MWWorld::Class::get (player).
getNpcStats (player).getSkill (select.getArgument()).getModified()); getNpcStats (player).getSkill (select.getArgument()).getModified());
case SelectWrapper::Function_FriendlyHit: case SelectWrapper::Function_FriendlyHit:
{ {
int hits = MWWorld::Class::get (mActor).getCreatureStats (mActor).getFriendlyHits(); int hits = MWWorld::Class::get (mActor).getCreatureStats (mActor).getFriendlyHits();
return hits>4 ? 4 : hits; return hits>4 ? 4 : hits;
} }
case SelectWrapper::Function_PcLevel: case SelectWrapper::Function_PcLevel:
return MWWorld::Class::get (player).getCreatureStats (player).getLevel(); return MWWorld::Class::get (player).getCreatureStats (player).getLevel();
@ -284,26 +284,26 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
case SelectWrapper::Function_PcGender: case SelectWrapper::Function_PcGender:
return player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female ? 0 : 1; return player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female ? 0 : 1;
case SelectWrapper::Function_PcClothingModifier: case SelectWrapper::Function_PcClothingModifier:
{ {
MWWorld::InventoryStore& store = MWWorld::Class::get (player).getInventoryStore (player); MWWorld::InventoryStore& store = MWWorld::Class::get (player).getInventoryStore (player);
int value = 0; int value = 0;
for (int i=0; i<=15; ++i) // everything except thigns held in hands and amunition for (int i=0; i<=15; ++i) // everything except thigns held in hands and amunition
{ {
MWWorld::ContainerStoreIterator slot = store.getSlot (i); MWWorld::ContainerStoreIterator slot = store.getSlot (i);
if (slot!=store.end()) if (slot!=store.end())
value += MWWorld::Class::get (*slot).getValue (*slot); value += MWWorld::Class::get (*slot).getValue (*slot);
} }
return value; return value;
} }
case SelectWrapper::Function_PcCrimeLevel: case SelectWrapper::Function_PcCrimeLevel:
return MWWorld::Class::get (player).getNpcStats (player).getBounty(); return MWWorld::Class::get (player).getNpcStats (player).getBounty();
case SelectWrapper::Function_RankRequirement: case SelectWrapper::Function_RankRequirement:
@ -313,12 +313,12 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
std::string faction = std::string faction =
MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first;
int rank = getFactionRank (player, faction); int rank = getFactionRank (player, faction);
if (rank>=9) if (rank>=9)
return 0; // max rank return 0; // max rank
int result = 0; int result = 0;
if (hasFactionRankSkillRequirements (player, faction, rank+1)) if (hasFactionRankSkillRequirements (player, faction, rank+1))
@ -328,16 +328,68 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
result += 2; result += 2;
return result; return result;
} }
case SelectWrapper::Function_Level: case SelectWrapper::Function_Level:
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getLevel(); return MWWorld::Class::get (mActor).getCreatureStats (mActor).getLevel();
case SelectWrapper::Function_PCReputation: case SelectWrapper::Function_PCReputation:
return MWWorld::Class::get (player).getNpcStats (player).getReputation(); return MWWorld::Class::get (player).getNpcStats (player).getReputation();
case SelectWrapper::Function_Weather:
return MWBase::Environment::get().getWorld()->getCurrentWeather();
case SelectWrapper::Function_Reputation:
return MWWorld::Class::get (mActor).getNpcStats (mActor).getReputation();
case SelectWrapper::Function_FactionRankDiff:
{
if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty())
return 0;
std::pair<std::string, int> faction =
*MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin();
int rank = getFactionRank (player, faction.first);
return rank-faction.second;
}
case SelectWrapper::Function_WerewolfKills:
return MWWorld::Class::get (player).getNpcStats (player).getWerewolfKills();
case SelectWrapper::Function_RankLow:
case SelectWrapper::Function_RankHigh:
{
bool low = select.getFunction()==SelectWrapper::Function_RankLow;
if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty())
return 0;
std::string factionId =
MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first;
int value = 0;
const ESM::Faction& faction =
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find (factionId);
MWMechanics::NpcStats& playerStats = MWWorld::Class::get (player).getNpcStats (player);
for (std::vector<ESM::Faction::Reaction>::const_iterator iter (faction.mReactions.begin());
iter!=faction.mReactions.end(); ++iter)
if (playerStats.getFactionRanks().find (iter->mFaction)!=playerStats.getFactionRanks().end())
if (low ? iter->mReaction<value : iter->mReaction>value)
value = iter->mReaction;
return value;
}
default: default:
throw std::runtime_error ("unknown integer select function"); throw std::runtime_error ("unknown integer select function");
@ -351,13 +403,13 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
switch (select.getFunction()) switch (select.getFunction())
{ {
case SelectWrapper::Function_False: case SelectWrapper::Function_False:
return false; return false;
case SelectWrapper::Function_Id: case SelectWrapper::Function_Id:
return select.getName()==toLower (MWWorld::Class::get (mActor).getId (mActor)); return select.getName()==toLower (MWWorld::Class::get (mActor).getId (mActor));
case SelectWrapper::Function_Faction: case SelectWrapper::Function_Faction:
return toLower (mActor.get<ESM::NPC>()->mBase->mFaction)==select.getName(); return toLower (mActor.get<ESM::NPC>()->mBase->mFaction)==select.getName();
@ -371,9 +423,9 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
return toLower (mActor.get<ESM::NPC>()->mBase->mRace)==select.getName(); return toLower (mActor.get<ESM::NPC>()->mBase->mRace)==select.getName();
case SelectWrapper::Function_Cell: case SelectWrapper::Function_Cell:
return toLower (mActor.getCell()->mCell->mName)==select.getName(); return toLower (mActor.getCell()->mCell->mName)==select.getName();
case SelectWrapper::Function_SameGender: case SelectWrapper::Function_SameGender:
return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)== return (player.get<ESM::NPC>()->mBase->mFlags & ESM::NPC::Female)==
@ -383,46 +435,70 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
return toLower (mActor.get<ESM::NPC>()->mBase->mRace)!= return toLower (mActor.get<ESM::NPC>()->mBase->mRace)!=
toLower (player.get<ESM::NPC>()->mBase->mRace); toLower (player.get<ESM::NPC>()->mBase->mRace);
case SelectWrapper::Function_SameFaction: case SelectWrapper::Function_SameFaction:
return MWWorld::Class::get (mActor).getNpcStats (mActor).isSameFaction ( return MWWorld::Class::get (mActor).getNpcStats (mActor).isSameFaction (
MWWorld::Class::get (player).getNpcStats (player)); MWWorld::Class::get (player).getNpcStats (player));
case SelectWrapper::Function_PcCommonDisease: case SelectWrapper::Function_PcCommonDisease:
return MWWorld::Class::get (player).getCreatureStats (player).hasCommonDisease(); return MWWorld::Class::get (player).getCreatureStats (player).hasCommonDisease();
case SelectWrapper::Function_PcBlightDisease: case SelectWrapper::Function_PcBlightDisease:
return MWWorld::Class::get (player).getCreatureStats (player).hasBlightDisease(); return MWWorld::Class::get (player).getCreatureStats (player).hasBlightDisease();
case SelectWrapper::Function_PcCorprus: case SelectWrapper::Function_PcCorprus:
return MWWorld::Class::get (player).getCreatureStats (player). return MWWorld::Class::get (player).getCreatureStats (player).
getMagicEffects().get (132).mMagnitude!=0; getMagicEffects().get (132).mMagnitude!=0;
case SelectWrapper::Function_PcExpelled: case SelectWrapper::Function_PcExpelled:
{ {
if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty()) if (MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().empty())
return false; return false;
std::string faction = std::string faction =
MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first; MWWorld::Class::get (mActor).getNpcStats (mActor).getFactionRanks().begin()->first;
std::set<std::string>& expelled = MWWorld::Class::get (player).getNpcStats (player).getExpelled(); std::set<std::string>& expelled = MWWorld::Class::get (player).getNpcStats (player).getExpelled();
return expelled.find (faction)!=expelled.end(); return expelled.find (faction)!=expelled.end();
} }
case SelectWrapper::Function_PcVampire: case SelectWrapper::Function_PcVampire:
return MWWorld::Class::get (player).getNpcStats (player).isVampire(); return MWWorld::Class::get (player).getNpcStats (player).isVampire();
case SelectWrapper::Function_TalkedToPc: case SelectWrapper::Function_TalkedToPc:
return mTalkedToPlayer; return mTalkedToPlayer;
case SelectWrapper::Function_Alarmed:
return MWWorld::Class::get (mActor).getCreatureStats (mActor).isAlarmed();
case SelectWrapper::Function_Detected:
return MWWorld::Class::get (mActor).hasDetected (mActor, player);
case SelectWrapper::Function_Attacked:
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getAttacked();
case SelectWrapper::Function_ShouldAttack:
return MWWorld::Class::get (mActor).getCreatureStats (mActor).isHostile();
case SelectWrapper::Function_CreatureTargetted:
return MWWorld::Class::get (mActor).getCreatureStats (mActor).getCreatureTargetted();
case SelectWrapper::Function_PCWerewolf:
return MWWorld::Class::get (player).getNpcStats (player).isWerewolf();
default: default:
throw std::runtime_error ("unknown boolean select function"); throw std::runtime_error ("unknown boolean select function");
@ -432,12 +508,12 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
int MWDialogue::Filter::getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const int MWDialogue::Filter::getFactionRank (const MWWorld::Ptr& actor, const std::string& factionId) const
{ {
MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor); MWMechanics::NpcStats& stats = MWWorld::Class::get (actor).getNpcStats (actor);
std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find (factionId); std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find (factionId);
if (iter==stats.getFactionRanks().end()) if (iter==stats.getFactionRanks().end())
return -1; return -1;
return iter->second; return iter->second;
} }

View file

@ -34,7 +34,7 @@ namespace
throw std::runtime_error ("unknown compare type in dialogue info select"); throw std::runtime_error ("unknown compare type in dialogue info select");
} }
template<typename T> template<typename T>
bool selectCompareImp (const ESM::DialInfo::SelectStruct& select, T value1) bool selectCompareImp (const ESM::DialInfo::SelectStruct& select, T value1)
{ {
@ -49,21 +49,22 @@ namespace
} }
else else
throw std::runtime_error ( throw std::runtime_error (
"unsupported variable type in dialogue info select"); "unsupported variable type in dialogue info select");
} }
} }
MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() const MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() const
{ {
int index = 0; int index = 0;
std::istringstream (mSelect.mSelectRule.substr(2,2)) >> index; std::istringstream (mSelect.mSelectRule.substr(2,2)) >> index;
switch (index) switch (index)
{ {
// 0, 1 case 0: return Function_RankLow;
case 1: return Function_RankHigh;
case 2: return Function_RankRequirement; case 2: return Function_RankRequirement;
// 3 case 3: return Function_Reputation;
case 4: return Function_HealthPercent; case 4: return Function_HealthPercent;
case 5: return Function_PCReputation; case 5: return Function_PCReputation;
case 6: return Function_PcLevel; case 6: return Function_PcLevel;
@ -82,22 +83,26 @@ MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction()
case 44: return Function_SameGender; case 44: return Function_SameGender;
case 45: return Function_SameRace; case 45: return Function_SameRace;
case 46: return Function_SameFaction; case 46: return Function_SameFaction;
// 47-49 case 47: return Function_FactionRankDiff;
case 48: return Function_Detected;
case 49: return Function_Alarmed;
case 50: return Function_Choice; case 50: return Function_Choice;
case 51: case 52: case 53: case 54: case 55: case 56: case 57: return Function_PcAttribute; case 51: case 52: case 53: case 54: case 55: case 56: case 57: return Function_PcAttribute;
case 58: return Function_PcCorprus; case 58: return Function_PcCorprus;
// 59 case 59: return Function_Weather;
case 60: return Function_PcVampire; case 60: return Function_PcVampire;
case 61: return Function_Level; case 61: return Function_Level;
// 62 case 62: return Function_Attacked;
case 63: return Function_TalkedToPc; case 63: return Function_TalkedToPc;
case 64: return Function_PcDynamicStat; case 64: return Function_PcDynamicStat;
// 65 case 65: return Function_CreatureTargetted;
case 66: return Function_FriendlyHit; case 66: return Function_FriendlyHit;
case 67: case 68: case 69: case 70: return Function_AiSetting; case 67: case 68: case 69: case 70: return Function_AiSetting;
// 71 case 71: return Function_ShouldAttack;
case 72: return Function_PCWerewolf;
case 73: return Function_WerewolfKills;
} }
return Function_False; return Function_False;
} }
@ -130,11 +135,11 @@ int MWDialogue::SelectWrapper::getArgument() const
{ {
if (mSelect.mSelectRule[1]!='1') if (mSelect.mSelectRule[1]!='1')
return 0; return 0;
int index = 0; int index = 0;
std::istringstream (mSelect.mSelectRule.substr(2,2)) >> index; std::istringstream (mSelect.mSelectRule.substr(2,2)) >> index;
switch (index) switch (index)
{ {
// AI settings // AI settings
@ -142,7 +147,7 @@ int MWDialogue::SelectWrapper::getArgument() const
case 68: return 0; case 68: return 0;
case 69: return 3; case 69: return 3;
case 70: return 2; case 70: return 2;
// attributes // attributes
case 10: return 0; case 10: return 0;
case 51: return 1; case 51: return 1;
@ -152,7 +157,7 @@ int MWDialogue::SelectWrapper::getArgument() const
case 55: return 5; case 55: return 5;
case 56: return 6; case 56: return 6;
case 57: return 7; case 57: return 7;
// skills // skills
case 11: return 0; case 11: return 0;
case 12: return 1; case 12: return 1;
@ -181,13 +186,13 @@ int MWDialogue::SelectWrapper::getArgument() const
case 35: return 24; case 35: return 24;
case 36: return 25; case 36: return 25;
case 37: return 26; case 37: return 26;
// dynamic stats // dynamic stats
case 8: return 1; case 8: return 1;
case 9: return 2; case 9: return 2;
case 64: return 0; case 64: return 0;
} }
return 0; return 0;
} }
@ -204,17 +209,21 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
Function_PcCrimeLevel, Function_PcCrimeLevel,
Function_RankRequirement, Function_RankRequirement,
Function_Level, Function_PCReputation, Function_Level, Function_PCReputation,
Function_Weather,
Function_Reputation, Function_FactionRankDiff,
Function_WerewolfKills,
Function_RankLow, Function_RankHigh,
Function_None // end marker Function_None // end marker
}; };
static const Function numericFunctions[] = static const Function numericFunctions[] =
{ {
Function_Global, Function_Local, Function_Global, Function_Local,
Function_PcDynamicStat, Function_PcHealthPercent, Function_PcDynamicStat, Function_PcHealthPercent,
Function_HealthPercent, Function_HealthPercent,
Function_None // end marker Function_None // end marker
}; };
static const Function booleanFunctions[] = static const Function booleanFunctions[] =
{ {
Function_False, Function_False,
@ -223,15 +232,19 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
Function_PcCommonDisease, Function_PcBlightDisease, Function_PcCorprus, Function_PcCommonDisease, Function_PcBlightDisease, Function_PcCorprus,
Function_PcExpelled, Function_PcExpelled,
Function_PcVampire, Function_TalkedToPc, Function_PcVampire, Function_TalkedToPc,
Function_Alarmed, Function_Detected,
Function_Attacked, Function_ShouldAttack,
Function_CreatureTargetted,
Function_PCWerewolf,
Function_None // end marker Function_None // end marker
}; };
Function function = getFunction(); Function function = getFunction();
for (int i=0; integerFunctions[i]!=Function_None; ++i) for (int i=0; integerFunctions[i]!=Function_None; ++i)
if (integerFunctions[i]==function) if (integerFunctions[i]==function)
return Type_Integer; return Type_Integer;
for (int i=0; numericFunctions[i]!=Function_None; ++i) for (int i=0; numericFunctions[i]!=Function_None; ++i)
if (numericFunctions[i]==function) if (numericFunctions[i]==function)
return Type_Numeric; return Type_Numeric;
@ -239,7 +252,7 @@ MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
for (int i=0; booleanFunctions[i]!=Function_None; ++i) for (int i=0; booleanFunctions[i]!=Function_None; ++i)
if (booleanFunctions[i]==function) if (booleanFunctions[i]==function)
return Type_Boolean; return Type_Boolean;
return Type_None; return Type_None;
} }
@ -261,15 +274,18 @@ bool MWDialogue::SelectWrapper::isNpcOnly() const
Function_PcVampire, Function_PcVampire,
Function_PcCrimeLevel, Function_PcCrimeLevel,
Function_RankRequirement, Function_RankRequirement,
Function_Reputation, Function_FactionRankDiff,
Function_PCWerewolf, Function_WerewolfKills,
Function_RankLow, Function_RankHigh,
Function_None // end marker Function_None // end marker
}; };
Function function = getFunction(); Function function = getFunction();
for (int i=0; functions[i]!=Function_None; ++i) for (int i=0; functions[i]!=Function_None; ++i)
if (functions[i]==function) if (functions[i]==function)
return true; return true;
return false; return false;
} }

View file

@ -8,9 +8,9 @@ namespace MWDialogue
class SelectWrapper class SelectWrapper
{ {
const ESM::DialInfo::SelectStruct& mSelect; const ESM::DialInfo::SelectStruct& mSelect;
public: public:
enum Function enum Function
{ {
Function_None, Function_False, Function_None, Function_False,
@ -36,7 +36,13 @@ namespace MWDialogue
Function_PcLevel, Function_PcHealthPercent, Function_PcDynamicStat, Function_PcLevel, Function_PcHealthPercent, Function_PcDynamicStat,
Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel, Function_PcGender, Function_PcClothingModifier, Function_PcCrimeLevel,
Function_RankRequirement, Function_RankRequirement,
Function_HealthPercent, Function_Level, Function_PCReputation Function_HealthPercent, Function_Level, Function_PCReputation,
Function_Weather,
Function_Reputation, Function_Alarmed, Function_FactionRankDiff, Function_Detected,
Function_Attacked, Function_ShouldAttack,
Function_CreatureTargetted,
Function_PCWerewolf, Function_WerewolfKills,
Function_RankLow, Function_RankHigh
}; };
enum Type enum Type
@ -46,32 +52,32 @@ namespace MWDialogue
Type_Numeric, Type_Numeric,
Type_Boolean Type_Boolean
}; };
private: private:
Function decodeFunction() const; Function decodeFunction() const;
public: public:
SelectWrapper (const ESM::DialInfo::SelectStruct& select); SelectWrapper (const ESM::DialInfo::SelectStruct& select);
Function getFunction() const; Function getFunction() const;
int getArgument() const; int getArgument() const;
Type getType() const; Type getType() const;
bool isInverted() const; bool isInverted() const;
bool isNpcOnly() const; bool isNpcOnly() const;
///< \attention Do not call any of the select functions for this select struct! ///< \attention Do not call any of the select functions for this select struct!
bool selectCompare (int value) const; bool selectCompare (int value) const;
bool selectCompare (float value) const; bool selectCompare (float value) const;
bool selectCompare (bool value) const; bool selectCompare (bool value) const;
std::string getName() const; std::string getName() const;
///< Return case-smashed name. ///< Return case-smashed name.
}; };

View file

@ -0,0 +1,21 @@
#include "aiactivate.hpp"
#include <iostream>
MWMechanics::AiActivate::AiActivate(const std::string &objectId)
: mObjectId(objectId)
{
}
MWMechanics::AiActivate *MWMechanics::AiActivate::clone() const
{
return new AiActivate(*this);
}
bool MWMechanics::AiActivate::execute (const MWWorld::Ptr& actor)
{
std::cout << "AiActivate completed.\n";
return true;
}
int MWMechanics::AiActivate::getTypeId() const
{
return 4;
}

View file

@ -0,0 +1,23 @@
#ifndef GAME_MWMECHANICS_AIACTIVATE_H
#define GAME_MWMECHANICS_AIACTIVATE_H
#include "aipackage.hpp"
#include <string>
namespace MWMechanics
{
class AiActivate : public AiPackage
{
public:
AiActivate(const std::string &objectId);
virtual AiActivate *clone() const;
virtual bool execute (const MWWorld::Ptr& actor);
///< \return Package completed?
virtual int getTypeId() const;
private:
std::string mObjectId;
};
}
#endif // GAME_MWMECHANICS_AIACTIVATE_H

View file

@ -0,0 +1,24 @@
#include "aiescort.hpp"
#include <iostream>
MWMechanics::AiEscort::AiEscort(const std::string &actorId,int duration, float x, float y, float z)
: mActorId(actorId), mX(x), mY(y), mZ(z), mDuration(duration)
{
}
MWMechanics::AiEscort *MWMechanics::AiEscort::clone() const
{
return new AiEscort(*this);
}
bool MWMechanics::AiEscort::execute (const MWWorld::Ptr& actor)
{
std::cout << "AiEscort completed. \n";
return true;
}
int MWMechanics::AiEscort::getTypeId() const
{
return 2;
}

View file

@ -0,0 +1,29 @@
#ifndef GAME_MWMECHANICS_AIESCORT_H
#define GAME_MWMECHANICS_AIESCORT_H
#include "aipackage.hpp"
#include <string>
namespace MWMechanics
{
class AiEscort : public AiPackage
{
public:
AiEscort(const std::string &actorId,int duration, float x, float y, float z);
virtual AiEscort *clone() const;
virtual bool execute (const MWWorld::Ptr& actor);
///< \return Package completed?
virtual int getTypeId() const;
private:
std::string mActorId;
float mX;
float mY;
float mZ;
int mDuration;
};
}
#endif

View file

@ -0,0 +1,22 @@
#include "aifollow.hpp"
#include <iostream>
MWMechanics::AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z)
: mDuration(duration), mX(x), mY(y), mZ(z), mActorId(actorId)
{
}
MWMechanics::AiFollow *MWMechanics::AiFollow::clone() const
{
return new AiFollow(*this);
}
bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor)
{
std::cout << "AiFollow completed.\n";
return true;
}
int MWMechanics::AiFollow::getTypeId() const
{
return 3;
}

View file

@ -0,0 +1,27 @@
#ifndef GAME_MWMECHANICS_AIFALLOW_H
#define GAME_MWMECHANICS_AIFALLOW_H
#include "aipackage.hpp"
#include <string>
namespace MWMechanics
{
class AiFollow : public AiPackage
{
public:
AiFollow(const std::string &ActorId,float duration, float X, float Y, float Z);
virtual AiFollow *clone() const;
virtual bool execute (const MWWorld::Ptr& actor);
///< \return Package completed?
virtual int getTypeId() const;
private:
float mDuration;
float mX;
float mY;
float mZ;
std::string mActorId;
};
}
#endif

View file

@ -0,0 +1,25 @@
#include "aitravel.hpp"
#include <iostream>
MWMechanics::AiTravel::AiTravel(float x, float y, float z)
: mX(x),mY(y),mZ(z)
{
}
MWMechanics::AiTravel * MWMechanics::AiTravel::clone() const
{
return new AiTravel(*this);
}
bool MWMechanics::AiTravel::execute (const MWWorld::Ptr& actor)
{
std::cout << "AiTravel completed.\n";
return true;
}
int MWMechanics::AiTravel::getTypeId() const
{
return 1;
}

View file

@ -0,0 +1,27 @@
#ifndef GAME_MWMECHANICS_AITRAVEL_H
#define GAME_MWMECHANICS_AITRAVEL_H
#include "aipackage.hpp"
namespace MWMechanics
{
class AiTravel : public AiPackage
{
public:
AiTravel(float x, float y, float z);
virtual AiTravel *clone() const;
virtual bool execute (const MWWorld::Ptr& actor);
///< \return Package completed?
virtual int getTypeId() const;
private:
float mX;
float mY;
float mZ;
};
}
#endif

View file

@ -0,0 +1,23 @@
#include "aiwander.hpp"
#include <iostream>
MWMechanics::AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle):
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle)
{
}
MWMechanics::AiPackage * MWMechanics::AiWander::clone() const
{
return new AiWander(*this);
}
bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
{
std::cout << "AiWadner completed.\n";
return true;
}
int MWMechanics::AiWander::getTypeId() const
{
return 0;
}

View file

@ -0,0 +1,29 @@
#ifndef GAME_MWMECHANICS_AIWANDER_H
#define GAME_MWMECHANICS_AIWANDER_H
#include "aipackage.hpp"
#include <vector>
namespace MWMechanics
{
class AiWander : public AiPackage
{
public:
AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle);
virtual AiPackage *clone() const;
virtual bool execute (const MWWorld::Ptr& actor);
///< \return Package completed?
virtual int getTypeId() const;
///< 0: Wander
private:
int mDistance;
int mDuration;
int mTimeOfDay;
std::vector<int> mIdle;
};
}
#endif

View file

@ -8,9 +8,10 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
namespace MWMechanics namespace MWMechanics
{ {
CreatureStats::CreatureStats() CreatureStats::CreatureStats()
: mLevel (0), mLevelHealthBonus(0.f), mDead (false), mFriendlyHits (0), mTalkedTo (false) : mLevel (0), mLevelHealthBonus(0.f), mDead (false), mFriendlyHits (0), mTalkedTo (false), mAlarmed (false),
mAttacked (false), mHostile (false)
{ {
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
mAiSettings[i] = 0; mAiSettings[i] = 0;
@ -30,26 +31,26 @@ namespace MWMechanics
{ {
return mAiSequence; return mAiSequence;
} }
AiSequence& CreatureStats::getAiSequence() AiSequence& CreatureStats::getAiSequence()
{ {
return mAiSequence; return mAiSequence;
} }
float CreatureStats::getFatigueTerm() const float CreatureStats::getFatigueTerm() const
{ {
int max = getFatigue().getModified(); int max = getFatigue().getModified();
int current = getFatigue().getCurrent(); int current = getFatigue().getCurrent();
float normalised = max==0 ? 1 : std::max (0.0f, static_cast<float> (current)/max); float normalised = max==0 ? 1 : std::max (0.0f, static_cast<float> (current)/max);
const MWWorld::Store<ESM::GameSetting> &gmst = const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
return gmst.find ("fFatigueBase")->getFloat() return gmst.find ("fFatigueBase")->getFloat()
- gmst.find ("fFatigueMult")->getFloat() * (1-normalised); - gmst.find ("fFatigueMult")->getFloat() * (1-normalised);
} }
const Stat<int> &CreatureStats::getAttribute(int index) const const Stat<int> &CreatureStats::getAttribute(int index) const
{ {
if (index < 0 || index > 7) { if (index < 0 || index > 7) {
@ -92,13 +93,13 @@ namespace MWMechanics
{ {
return mLevel; return mLevel;
} }
int CreatureStats::getAiSetting (int index) const int CreatureStats::getAiSetting (int index) const
{ {
assert (index>=0 && index<4); assert (index>=0 && index<4);
return mAiSettings[index]; return mAiSettings[index];
} }
Stat<int> &CreatureStats::getAttribute(int index) Stat<int> &CreatureStats::getAttribute(int index)
{ {
if (index < 0 || index > 7) { if (index < 0 || index > 7) {
@ -168,7 +169,7 @@ namespace MWMechanics
if (index==0 && mDynamic[index].getCurrent()<1) if (index==0 && mDynamic[index].getCurrent()<1)
mDead = true; mDead = true;
} }
void CreatureStats::setLevel(int level) void CreatureStats::setLevel(int level)
{ {
mLevel = level; mLevel = level;
@ -189,24 +190,24 @@ namespace MWMechanics
assert (index>=0 && index<4); assert (index>=0 && index<4);
mAiSettings[index] = value; mAiSettings[index] = value;
} }
bool CreatureStats::isDead() const bool CreatureStats::isDead() const
{ {
return mDead; return mDead;
} }
void CreatureStats::resurrect() void CreatureStats::resurrect()
{ {
if (mDead) if (mDead)
{ {
if (mDynamic[0].getCurrent()<1) if (mDynamic[0].getCurrent()<1)
mDynamic[0].setCurrent (1); mDynamic[0].setCurrent (1);
if (mDynamic[0].getCurrent()>=1) if (mDynamic[0].getCurrent()>=1)
mDead = false; mDead = false;
} }
} }
bool CreatureStats::hasCommonDisease() const bool CreatureStats::hasCommonDisease() const
{ {
return mSpells.hasCommonDisease(); return mSpells.hasCommonDisease();
@ -216,24 +217,59 @@ namespace MWMechanics
{ {
return mSpells.hasBlightDisease(); return mSpells.hasBlightDisease();
} }
int CreatureStats::getFriendlyHits() const int CreatureStats::getFriendlyHits() const
{ {
return mFriendlyHits; return mFriendlyHits;
} }
void CreatureStats::friendlyHit() void CreatureStats::friendlyHit()
{ {
++mFriendlyHits; ++mFriendlyHits;
} }
bool CreatureStats::hasTalkedToPlayer() const bool CreatureStats::hasTalkedToPlayer() const
{ {
return mTalkedTo; return mTalkedTo;
} }
void CreatureStats::talkedToPlayer() void CreatureStats::talkedToPlayer()
{ {
mTalkedTo = true; mTalkedTo = true;
} }
bool CreatureStats::isAlarmed() const
{
return mAlarmed;
}
void CreatureStats::setAlarmed (bool alarmed)
{
mAlarmed = alarmed;
}
bool CreatureStats::getAttacked() const
{
return mAttacked;
}
void CreatureStats::setAttacked (bool attacked)
{
mAttacked = attacked;
}
bool CreatureStats::isHostile() const
{
return mHostile;
}
void CreatureStats::setHostile (bool hostile)
{
mHostile = hostile;
}
bool CreatureStats::getCreatureTargetted() const
{
return false;
}
} }

View file

@ -30,6 +30,9 @@ namespace MWMechanics
bool mDead; bool mDead;
int mFriendlyHits; int mFriendlyHits;
bool mTalkedTo; bool mTalkedTo;
bool mAlarmed;
bool mAttacked;
bool mHostile;
public: public:
CreatureStats(); CreatureStats();
@ -83,11 +86,11 @@ namespace MWMechanics
void setAiSetting (int index, int value); void setAiSetting (int index, int value);
///< 0: hello, 1 fight, 2 flee, 3 alarm ///< 0: hello, 1 fight, 2 flee, 3 alarm
const AiSequence& getAiSequence() const; const AiSequence& getAiSequence() const;
AiSequence& getAiSequence(); AiSequence& getAiSequence();
float getFatigueTerm() const; float getFatigueTerm() const;
///< Return effective fatigue ///< Return effective fatigue
@ -96,23 +99,37 @@ namespace MWMechanics
float getLevelHealthBonus() const; float getLevelHealthBonus() const;
bool isDead() const; bool isDead() const;
void resurrect(); void resurrect();
bool hasCommonDisease() const; bool hasCommonDisease() const;
bool hasBlightDisease() const; bool hasBlightDisease() const;
int getFriendlyHits() const; int getFriendlyHits() const;
///< Number of friendly hits received. ///< Number of friendly hits received.
void friendlyHit(); void friendlyHit();
///< Increase number of friendly hits by one. ///< Increase number of friendly hits by one.
bool hasTalkedToPlayer() const; bool hasTalkedToPlayer() const;
///< Has this creature talked with the player before? ///< Has this creature talked with the player before?
void talkedToPlayer(); void talkedToPlayer();
bool isAlarmed() const;
void setAlarmed (bool alarmed);
bool getAttacked() const;
void setAttacked (bool attacked);
bool isHostile() const;
void setHostile (bool hostile);
bool getCreatureTargetted() const;
}; };
} }

View file

@ -22,7 +22,7 @@
MWMechanics::NpcStats::NpcStats() MWMechanics::NpcStats::NpcStats()
: mMovementFlags (0), mDrawState (DrawState_Nothing), mBounty (0) : mMovementFlags (0), mDrawState (DrawState_Nothing), mBounty (0)
, mLevelProgress(0), mDisposition(0), mVampire (0), mReputation(0) , mLevelProgress(0), mDisposition(0), mVampire (0), mReputation(0), mWerewolf (false), mWerewolfKills (0)
{ {
mSkillIncreases.resize (ESM::Attribute::Length); mSkillIncreases.resize (ESM::Attribute::Length);
for (int i=0; i<ESM::Attribute::Length; ++i) for (int i=0; i<ESM::Attribute::Length; ++i)
@ -99,7 +99,7 @@ bool MWMechanics::NpcStats::isSameFaction (const NpcStats& npcStats) const
++iter) ++iter)
if (npcStats.mFactionRank.find (iter->first)!=npcStats.mFactionRank.end()) if (npcStats.mFactionRank.find (iter->first)!=npcStats.mFactionRank.end())
return true; return true;
return false; return false;
} }
@ -280,10 +280,10 @@ void MWMechanics::NpcStats::setBounty (int bounty)
int MWMechanics::NpcStats::getFactionReputation (const std::string& faction) const int MWMechanics::NpcStats::getFactionReputation (const std::string& faction) const
{ {
std::map<std::string, int>::const_iterator iter = mFactionReputation.find (faction); std::map<std::string, int>::const_iterator iter = mFactionReputation.find (faction);
if (iter==mFactionReputation.end()) if (iter==mFactionReputation.end())
return 0; return 0;
return iter->second; return iter->second;
} }
@ -321,19 +321,33 @@ bool MWMechanics::NpcStats::hasSkillsForRank (const std::string& factionId, int
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find (factionId); *MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().find (factionId);
std::vector<int> skills; std::vector<int> skills;
for (int i=0; i<6; ++i) for (int i=0; i<6; ++i)
skills.push_back (static_cast<int> (getSkill (faction.mData.mSkillID[i]).getModified())); skills.push_back (static_cast<int> (getSkill (faction.mData.mSkillID[i]).getModified()));
std::sort (skills.begin(), skills.end()); std::sort (skills.begin(), skills.end());
std::vector<int>::const_reverse_iterator iter = skills.rbegin(); std::vector<int>::const_reverse_iterator iter = skills.rbegin();
const ESM::RankData& rankData = faction.mData.mRankData[rank]; const ESM::RankData& rankData = faction.mData.mRankData[rank];
if (*iter<rankData.mSkill1) if (*iter<rankData.mSkill1)
return false; return false;
return *++iter>=rankData.mSkill2; return *++iter>=rankData.mSkill2;
} }
bool MWMechanics::NpcStats::isWerewolf() const
{
return mWerewolf;
}
void MWMechanics::NpcStats::setWerewolf (bool set)
{
mWerewolf = set;
}
int MWMechanics::NpcStats::getWerewolfKills() const
{
return mWerewolfKills;
}

View file

@ -51,6 +51,8 @@ namespace MWMechanics
std::map<std::string, int> mFactionReputation; std::map<std::string, int> mFactionReputation;
bool mVampire; bool mVampire;
int mReputation; int mReputation;
bool mWerewolf;
int mWerewolfKills;
int mLevelProgress; // 0-10 int mLevelProgress; // 0-10
@ -83,7 +85,7 @@ namespace MWMechanics
Stat<float>& getSkill (int index); Stat<float>& getSkill (int index);
std::map<std::string, int>& getFactionRanks(); std::map<std::string, int>& getFactionRanks();
std::set<std::string>& getExpelled(); std::set<std::string>& getExpelled();
bool isSameFaction (const NpcStats& npcStats) const; bool isSameFaction (const NpcStats& npcStats) const;
@ -107,24 +109,30 @@ namespace MWMechanics
int getLevelupAttributeMultiplier(int attribute) const; int getLevelupAttributeMultiplier(int attribute) const;
void levelUp(); void levelUp();
void flagAsUsed (const std::string& id); void flagAsUsed (const std::string& id);
bool hasBeenUsed (const std::string& id) const; bool hasBeenUsed (const std::string& id) const;
int getBounty() const; int getBounty() const;
void setBounty (int bounty); void setBounty (int bounty);
int getFactionReputation (const std::string& faction) const; int getFactionReputation (const std::string& faction) const;
void setFactionReputation (const std::string& faction, int value); void setFactionReputation (const std::string& faction, int value);
bool isVampire() const; bool isVampire() const;
void setVampire (bool set); void setVampire (bool set);
bool hasSkillsForRank (const std::string& factionId, int rank) const; bool hasSkillsForRank (const std::string& factionId, int rank) const;
bool isWerewolf() const;
void setWerewolf (bool set);
int getWerewolfKills() const;
}; };
} }

View file

@ -31,7 +31,13 @@ op 0x2000e: PCGetRank implicit
op 0x2000f: PCGetRank explicit op 0x2000f: PCGetRank explicit
op 0x20010: AiWander op 0x20010: AiWander
op 0x20011: AiWander, explicit reference op 0x20011: AiWander, explicit reference
op s 0x20012-0x3ffff unused op 0x20012: GetPCFacRep
op 0x20013: GetPCFacRep, explicit reference
op 0x20014: SetPCFacRep
op 0x20015: SetPCFacRep, explicit reference
op 0x20016: ModPCFacRep
op 0x20017: ModPCFacRep, explicit reference
op s 0x20018-0x3ffff unused
Segment 4: Segment 4:
(not implemented yet) (not implemented yet)
@ -198,14 +204,22 @@ op 0x2000197: Position Explicit
op 0x2000198: PositionCell op 0x2000198: PositionCell
op 0x2000199: PositionCell Explicit op 0x2000199: PositionCell Explicit
op 0x200019a: PlaceItemCell op 0x200019a: PlaceItemCell
op 0x200019b: PlaceItem op 0x200019b: PlaceItem
op 0x200019c: PlaceAtPc op 0x200019c: PlaceAtPc
op 0x200019d: PlaceAtMe op 0x200019d: PlaceAtMe
op 0x200019e: PlaceAtMe Explicit op 0x200019e: PlaceAtMe Explicit
op 0x200019f: GetPcSleep op 0x200019f: GetPcSleep
op 0x20001a0: ShowMap op 0x20001a0: ShowMap
op 0x20001a1: FillMap op 0x20001a1: FillMap
op 0x20001a2: WakeUpPc op 0x20001a2: WakeUpPc
op 0x20001a3: GetDeadCount op 0x20001a3: GetDeadCount
opcodes 0x20001a4-0x3ffffff unused op 0x20001a4: SetDisposition
op 0x20001a5: SetDisposition, Explicit
op 0x20001a6: GetDisposition
op 0x20001a7: GetDisposition, Explicit
op 0x20001a8: CommonDisease
op 0x20001a9: CommonDisease, explicit reference
op 0x20001aa: BlightDisease
op 0x20001ab: BlightDisease, explicit reference
opcodes 0x20001ac-0x3ffffff unused

View file

@ -33,13 +33,13 @@ namespace
std::string getDialogueActorFaction() std::string getDialogueActorFaction()
{ {
MWWorld::Ptr actor = MWBase::Environment::get().getDialogueManager()->getActor(); MWWorld::Ptr actor = MWBase::Environment::get().getDialogueManager()->getActor();
MWMechanics::NpcStats stats = MWWorld::Class::get (actor).getNpcStats (actor); MWMechanics::NpcStats stats = MWWorld::Class::get (actor).getNpcStats (actor);
if (stats.getFactionRanks().empty()) if (stats.getFactionRanks().empty())
throw std::runtime_error ( throw std::runtime_error (
"failed to determine dialogue actors faction (because actor is factionless)"); "failed to determine dialogue actors faction (because actor is factionless)");
return stats.getFactionRanks().begin()->first; return stats.getFactionRanks().begin()->first;
} }
} }
@ -208,7 +208,7 @@ namespace MWScript
.getDynamic (mIndex)); .getDynamic (mIndex));
stat.setModified (value, 0); stat.setModified (value, 0);
MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat); MWWorld::Class::get (ptr).getCreatureStats (ptr).setDynamic (mIndex, stat);
} }
}; };
@ -565,7 +565,7 @@ namespace MWScript
{ {
if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty()) if(MWWorld::Class::get(ptr).getNpcStats(ptr).getFactionRanks().empty())
{ {
//throw exception? factionID = "";
} }
else else
{ {
@ -601,13 +601,43 @@ namespace MWScript
{ {
MWWorld::Ptr ptr = R()(runtime); MWWorld::Ptr ptr = R()(runtime);
// Interpreter::Type_Integer value = runtime[0].mInteger; Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop(); runtime.pop();
/// \todo modify disposition towards the player MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition
(MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition() + value);
} }
}; };
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();
MWWorld::Class::get (ptr).getNpcStats (ptr).setBaseDisposition (value);
}
};
template<class R>
class OpGetDisposition : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
MWWorld::Ptr ptr = R()(runtime);
runtime.push (MWWorld::Class::get (ptr).getNpcStats (ptr).getBaseDisposition());
}
};
class OpGetDeadCount : public Interpreter::Opcode0 class OpGetDeadCount : public Interpreter::Opcode0
{ {
public: public:
@ -617,7 +647,138 @@ namespace MWScript
std::string id = runtime.getStringLiteral (runtime[0].mInteger); std::string id = runtime.getStringLiteral (runtime[0].mInteger);
runtime[0].mInteger = MWBase::Environment::get().getMechanicsManager()->countDeaths (id); 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)
{
std::string factionId;
if (arg0==1)
{
factionId = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
MWWorld::Ptr ptr = R()(runtime);
if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty())
factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first;
}
if (factionId.empty())
throw std::runtime_error ("failed to determine faction");
boost::algorithm::to_lower (factionId);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
runtime.push (
MWWorld::Class::get (player).getNpcStats (player).getFactionReputation (factionId));
}
};
template<class R>
class OpSetPCFacRep : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::string factionId;
if (arg0==1)
{
factionId = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
MWWorld::Ptr ptr = R()(runtime);
if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty())
factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first;
}
if (factionId.empty())
throw std::runtime_error ("failed to determine faction");
boost::algorithm::to_lower (factionId);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId, value);
}
};
template<class R>
class OpModPCFacRep : public Interpreter::Opcode1
{
public:
virtual void execute (Interpreter::Runtime& runtime, unsigned int arg0)
{
Interpreter::Type_Integer value = runtime[0].mInteger;
runtime.pop();
std::string factionId;
if (arg0==1)
{
factionId = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
}
else
{
MWWorld::Ptr ptr = R()(runtime);
if (!MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().empty())
factionId = MWWorld::Class::get (ptr).getNpcStats (ptr).getFactionRanks().begin()->first;
}
if (factionId.empty())
throw std::runtime_error ("failed to determine faction");
boost::algorithm::to_lower (factionId);
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
MWWorld::Class::get (player).getNpcStats (player).setFactionReputation (factionId,
MWWorld::Class::get (player).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 (MWWorld::Class::get (ptr).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 (MWWorld::Class::get (ptr).getCreatureStats (ptr).hasBlightDisease());
}
};
const int numberOfAttributes = 8; const int numberOfAttributes = 8;
@ -665,14 +826,30 @@ namespace MWScript
const int opcodeGetPCRankExplicit = 0x2000f; const int opcodeGetPCRankExplicit = 0x2000f;
const int opcodeModDisposition = 0x200014d; const int opcodeModDisposition = 0x200014d;
const int opcodeModDispositionExplicit = 0x200014e; const int opcodeModDispositionExplicit = 0x200014e;
const int opcodeSetDisposition = 0x20001a4;
const int opcodeSetDispositionExplicit = 0x20001a5;
const int opcodeGetDisposition = 0x20001a6;
const int opcodeGetDispositionExplicit = 0x20001a7;
const int opcodeGetLevel = 0x200018c; const int opcodeGetLevel = 0x200018c;
const int opcodeGetLevelExplicit = 0x200018d; const int opcodeGetLevelExplicit = 0x200018d;
const int opcodeSetLevel = 0x200018e; const int opcodeSetLevel = 0x200018e;
const int opcodeSetLevelExplicit = 0x200018f; const int opcodeSetLevelExplicit = 0x200018f;
const int opcodeGetDeadCount = 0x20001a3; const int opcodeGetDeadCount = 0x20001a3;
const int opcodeGetPCFacRep = 0x20012;
const int opcodeGetPCFacRepExplicit = 0x20013;
const int opcodeSetPCFacRep = 0x20014;
const int opcodeSetPCFacRepExplicit = 0x20015;
const int opcodeModPCFacRep = 0x20016;
const int opcodeModPCFacRepExplicit = 0x20017;
const int opcodeGetCommonDisease = 0x20001a8;
const int opcodeGetCommonDiseaseExplicit = 0x20001a9;
const int opcodeGetBlightDisease = 0x20001aa;
const int opcodeGetBlightDiseaseExplicit = 0x20001ab;
void registerExtensions (Compiler::Extensions& extensions) void registerExtensions (Compiler::Extensions& extensions)
{ {
static const char *attributes[numberOfAttributes] = static const char *attributes[numberOfAttributes] =
@ -752,14 +929,27 @@ namespace MWScript
extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank); extensions.registerInstruction("pcraiserank","/S",opcodePCRaiseRank);
extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank); extensions.registerInstruction("pclowerrank","/S",opcodePCLowerRank);
extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction); extensions.registerInstruction("pcjoinfaction","/S",opcodePCJoinFaction);
extensions.registerInstruction("moddisposition","l",opcodeModDisposition, extensions.registerInstruction ("moddisposition","l",opcodeModDisposition,
opcodeModDispositionExplicit); opcodeModDispositionExplicit);
extensions.registerInstruction ("setdisposition","l",opcodeSetDisposition,
opcodeSetDispositionExplicit);
extensions.registerFunction ("getdisposition",'l', "",opcodeGetDisposition,
opcodeGetDispositionExplicit);
extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit); extensions.registerFunction("getpcrank",'l',"/S",opcodeGetPCRank,opcodeGetPCRankExplicit);
extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit); extensions.registerInstruction("setlevel", "l", opcodeSetLevel, opcodeSetLevelExplicit);
extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit); extensions.registerFunction("getlevel", 'l', "", opcodeGetLevel, opcodeGetLevelExplicit);
extensions.registerFunction("getdeadcount", 'l', "c", opcodeGetDeadCount); extensions.registerFunction ("getdeadcount", 'l', "c", opcodeGetDeadCount);
extensions.registerFunction ("getpcfacrep", 'l', "/c", opcodeGetPCFacRep, opcodeGetPCFacRepExplicit);
extensions.registerInstruction ("setpcfacrep", "l/c", opcodeSetPCFacRep, opcodeSetPCFacRepExplicit);
extensions.registerInstruction ("modpcfacrep", "l/c", opcodeModPCFacRep, opcodeModPCFacRepExplicit);
extensions.registerFunction ("getcommondisease", 'l', "", opcodeGetCommonDisease,
opcodeGetCommonDiseaseExplicit);
extensions.registerFunction ("getblightdisease", 'l', "", opcodeGetBlightDisease,
opcodeGetBlightDiseaseExplicit);
} }
void installOpcodes (Interpreter::Interpreter& interpreter) void installOpcodes (Interpreter::Interpreter& interpreter)
@ -827,17 +1017,34 @@ namespace MWScript
interpreter.installSegment3(opcodePCRaiseRank,new OpPCRaiseRank); interpreter.installSegment3(opcodePCRaiseRank,new OpPCRaiseRank);
interpreter.installSegment3(opcodePCLowerRank,new OpPCLowerRank); interpreter.installSegment3(opcodePCLowerRank,new OpPCLowerRank);
interpreter.installSegment3(opcodePCJoinFaction,new OpPCJoinFaction); interpreter.installSegment3(opcodePCJoinFaction,new OpPCJoinFaction);
interpreter.installSegment5(opcodeModDisposition,new OpModDisposition<ImplicitRef>);
interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>);
interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>); interpreter.installSegment3(opcodeGetPCRank,new OpGetPCRank<ImplicitRef>);
interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>); interpreter.installSegment3(opcodeGetPCRankExplicit,new OpGetPCRank<ExplicitRef>);
interpreter.installSegment5(opcodeModDisposition,new OpModDisposition<ImplicitRef>);
interpreter.installSegment5(opcodeModDispositionExplicit,new OpModDisposition<ExplicitRef>);
interpreter.installSegment5(opcodeSetDisposition,new OpSetDisposition<ImplicitRef>);
interpreter.installSegment5(opcodeSetDispositionExplicit,new OpSetDisposition<ExplicitRef>);
interpreter.installSegment5(opcodeGetDisposition,new OpGetDisposition<ImplicitRef>);
interpreter.installSegment5(opcodeGetDispositionExplicit,new OpGetDisposition<ExplicitRef>);
interpreter.installSegment5 (opcodeGetLevel, new OpGetLevel<ImplicitRef>); interpreter.installSegment5 (opcodeGetLevel, new OpGetLevel<ImplicitRef>);
interpreter.installSegment5 (opcodeGetLevelExplicit, new OpGetLevel<ExplicitRef>); interpreter.installSegment5 (opcodeGetLevelExplicit, new OpGetLevel<ExplicitRef>);
interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel<ImplicitRef>); interpreter.installSegment5 (opcodeSetLevel, new OpSetLevel<ImplicitRef>);
interpreter.installSegment5 (opcodeSetLevelExplicit, new OpSetLevel<ExplicitRef>); interpreter.installSegment5 (opcodeSetLevelExplicit, new OpSetLevel<ExplicitRef>);
interpreter.installSegment5 (opcodeGetDeadCount, new OpGetDeadCount); interpreter.installSegment5 (opcodeGetDeadCount, new OpGetDeadCount);
interpreter.installSegment3 (opcodeGetPCFacRep, new OpGetPCFacRep<ImplicitRef>);
interpreter.installSegment3 (opcodeGetPCFacRepExplicit, new OpGetPCFacRep<ExplicitRef>);
interpreter.installSegment3 (opcodeSetPCFacRep, new OpSetPCFacRep<ImplicitRef>);
interpreter.installSegment3 (opcodeSetPCFacRepExplicit, new OpSetPCFacRep<ExplicitRef>);
interpreter.installSegment3 (opcodeModPCFacRep, new OpModPCFacRep<ImplicitRef>);
interpreter.installSegment3 (opcodeModPCFacRepExplicit, new OpModPCFacRep<ExplicitRef>);
interpreter.installSegment5 (opcodeGetCommonDisease, new OpGetCommonDisease<ImplicitRef>);
interpreter.installSegment5 (opcodeGetCommonDiseaseExplicit, new OpGetCommonDisease<ExplicitRef>);
interpreter.installSegment5 (opcodeGetBlightDisease, new OpGetBlightDisease<ImplicitRef>);
interpreter.installSegment5 (opcodeGetBlightDiseaseExplicit, new OpGetBlightDisease<ExplicitRef>);
} }
} }
} }

View file

@ -162,6 +162,11 @@ namespace MWWorld
return false; return false;
} }
bool Class::hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const
{
return false;
}
const Class& Class::get (const std::string& key) const Class& Class::get (const std::string& key)
{ {
std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key); std::map<std::string, boost::shared_ptr<Class> >::const_iterator iter = sClasses.find (key);

View file

@ -191,6 +191,11 @@ namespace MWWorld
/// ///
/// (default implementation: return false) /// (default implementation: return false)
virtual bool hasDetected (const MWWorld::Ptr& ptr, const MWWorld::Ptr& ptr2) const;
///< Has \æ ptr detected \a ptr2?
///
/// (default implementation: return false)
static const Class& get (const std::string& key); static const Class& get (const std::string& key);
///< If there is no class for this \a key, an exception is thrown. ///< If there is no class for this \a key, an exception is thrown.

View file

@ -27,6 +27,7 @@ Jason Hooks (jhooks)
Karl-Felix Glatzer (k1ll) Karl-Felix Glatzer (k1ll)
Leon Saunders (emoose) Leon Saunders (emoose)
Lukasz Gromanowski (lgro) Lukasz Gromanowski (lgro)
Marcin Hulist (Gohan)
Michael Mc Donnell Michael Mc Donnell
Michael Papageorgiou (werdanith) Michael Papageorgiou (werdanith)
Nikolay Kasyanov (corristo) Nikolay Kasyanov (corristo)