bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const { if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name())) // If the actor is a creature, we pass all conditions only applicable to NPCs. return true; if (select.getFunction() == SelectWrapper::Function_Choice && mChoice == -1) // If not currently in a choice, we reject all conditions that test against choices. return false; if (select.getFunction() == SelectWrapper::Function_Weather && !(MWBase::Environment::get().getWorld()->isCellExterior() || MWBase::Environment::get().getWorld()->isCellQuasiExterior())) // Reject weather conditions in interior cells // Note that the original engine doesn't include the "|| isCellQuasiExterior()" check, which could be considered a bug. return false; switch (select.getType()) { case SelectWrapper::Type_None: return true; case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select)); case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select)); // We must not do the comparison for inverted functions (eg. Function_NotClass) case SelectWrapper::Type_Inverted: return getSelectStructBoolean (select); } return true; }
bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) const { switch (select.getFunction()) { case SelectWrapper::Function_Global: // internally all globals are float :( return select.selectCompare ( MWBase::Environment::get().getWorld()->getGlobalFloat (select.getName())); case SelectWrapper::Function_Local: { return testFunctionLocal(select); } case SelectWrapper::Function_NotLocal: { return !testFunctionLocal(select); } case SelectWrapper::Function_PcHealthPercent: { MWWorld::Ptr player = MWMechanics::getPlayer(); float ratio = player.getClass().getCreatureStats (player).getHealth().getCurrent() / player.getClass().getCreatureStats (player).getHealth().getModified(); return select.selectCompare (static_cast<int>(ratio*100)); } case SelectWrapper::Function_PcDynamicStat: { MWWorld::Ptr player = MWMechanics::getPlayer(); float value = player.getClass().getCreatureStats (player). getDynamic (select.getArgument()).getCurrent(); return select.selectCompare (value); } case SelectWrapper::Function_HealthPercent: { float ratio = mActor.getClass().getCreatureStats (mActor).getHealth().getCurrent() / mActor.getClass().getCreatureStats (mActor).getHealth().getModified(); return select.selectCompare (static_cast<int>(ratio*100)); } default: throw std::runtime_error ("unknown numeric select function"); } }
bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const { if (select.isNpcOnly() && mActor.getTypeName()!=typeid (ESM::NPC).name()) return select.isInverted(); switch (select.getType()) { case SelectWrapper::Type_None: return true; case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select)); case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select)); } return true; }
bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const { if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name())) // If the actor is a creature, we do not test the conditions applicable // only to NPCs. Such conditions can never be satisfied, apart // inverted ones (NotClass, NotRace, NotFaction return true // because creatures are not of any race, class or faction). return select.getType() == SelectWrapper::Type_Inverted; switch (select.getType()) { case SelectWrapper::Type_None: return true; case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select)); case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select)); // We must not do the comparison for inverted functions (eg. Function_NotClass) case SelectWrapper::Type_Inverted: return getSelectStructBoolean (select); } return true; }
bool MWDialogue::Filter::testSelectStruct (const SelectWrapper& select) const { if (select.isNpcOnly() && (mActor.getTypeName() != typeid (ESM::NPC).name())) // If the actor is a creature, we pass all conditions only applicable to NPCs. return true; if (select.getFunction() == SelectWrapper::Function_Choice && mChoice == -1) // If not currently in a choice, we reject all conditions that test against choices. return false; switch (select.getType()) { case SelectWrapper::Type_None: return true; case SelectWrapper::Type_Integer: return select.selectCompare (getSelectStructInteger (select)); case SelectWrapper::Type_Numeric: return testSelectStructNumeric (select); case SelectWrapper::Type_Boolean: return select.selectCompare (getSelectStructBoolean (select)); // We must not do the comparison for inverted functions (eg. Function_NotClass) case SelectWrapper::Type_Inverted: return getSelectStructBoolean (select); } return true; }
bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) const { switch (select.getFunction()) { case SelectWrapper::Function_Global: // internally all globals are float :( return select.selectCompare ( MWBase::Environment::get().getWorld()->getGlobalFloat (select.getName())); case SelectWrapper::Function_Local: { std::string scriptName = mActor.getClass().getScript (mActor); if (scriptName.empty()) return false; // no script std::string name = Misc::StringUtils::lowerCase (select.getName()); const Compiler::Locals& localDefs = MWBase::Environment::get().getScriptManager()->getLocals (scriptName); char type = localDefs.getType (name); if (type==' ') return false; // script does not have a variable of this name. int index = localDefs.getIndex (name); if (index < 0) return false; // shouldn't happen, we checked that variable has a type above, so must exist const MWScript::Locals& locals = mActor.getRefData().getLocals(); switch (type) { case 's': return select.selectCompare (static_cast<int> (locals.mShorts[index])); case 'l': return select.selectCompare (locals.mLongs[index]); case 'f': return select.selectCompare (locals.mFloats[index]); } throw std::logic_error ("unknown local variable type in dialogue filter"); } case SelectWrapper::Function_PcHealthPercent: { MWWorld::Ptr player = MWMechanics::getPlayer(); float ratio = player.getClass().getCreatureStats (player).getHealth().getCurrent() / player.getClass().getCreatureStats (player).getHealth().getModified(); return select.selectCompare (static_cast<int>(ratio*100)); } case SelectWrapper::Function_PcDynamicStat: { MWWorld::Ptr player = MWMechanics::getPlayer(); float value = player.getClass().getCreatureStats (player). getDynamic (select.getArgument()).getCurrent(); return select.selectCompare (value); } case SelectWrapper::Function_HealthPercent: { float ratio = mActor.getClass().getCreatureStats (mActor).getHealth().getCurrent() / mActor.getClass().getCreatureStats (mActor).getHealth().getModified(); return select.selectCompare (static_cast<int>(ratio*100)); } default: throw std::runtime_error ("unknown numeric select function"); } }
bool MWDialogue::Filter::testSelectStructNumeric (const SelectWrapper& select) const { switch (select.getFunction()) { case SelectWrapper::Function_Global: // internally all globals are float :( return select.selectCompare ( MWBase::Environment::get().getWorld()->getGlobalVariable (select.getName()).mFloat); case SelectWrapper::Function_Local: { std::string scriptName = MWWorld::Class::get (mActor).getScript (mActor); if (scriptName.empty()) return false; // no script const ESM::Script *script = MWBase::Environment::get().getWorld()->getStore().get<ESM::Script>().find (scriptName); std::string name = select.getName(); int i = 0; for (; i<static_cast<int> (script->mVarNames.size()); ++i) if (Misc::StringUtils::lowerCase(script->mVarNames[i]) == name) break; if (i>=static_cast<int> (script->mVarNames.size())) return false; // script does not have a variable of this name const MWScript::Locals& locals = mActor.getRefData().getLocals(); if (i<script->mData.mNumShorts) return select.selectCompare (static_cast<int> (locals.mShorts[i])); i -= script->mData.mNumShorts; if (i<script->mData.mNumLongs) return select.selectCompare (locals.mLongs[i]); i -= script->mData.mNumLongs; return select.selectCompare (locals.mFloats.at (i)); } case SelectWrapper::Function_PcHealthPercent: { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); float ratio = MWWorld::Class::get (player).getCreatureStats (player).getHealth().getCurrent() / MWWorld::Class::get (player).getCreatureStats (player).getHealth().getModified(); return select.selectCompare (ratio); } case SelectWrapper::Function_PcDynamicStat: { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); float value = MWWorld::Class::get (player).getCreatureStats (player). getDynamic (select.getArgument()).getCurrent(); return select.selectCompare (value); } case SelectWrapper::Function_HealthPercent: { float ratio = MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getCurrent() / MWWorld::Class::get (mActor).getCreatureStats (mActor).getHealth().getModified(); return select.selectCompare (ratio); } default: throw std::runtime_error ("unknown numeric select function"); } }