mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
702 lines
25 KiB
C++
702 lines
25 KiB
C++
#include "infoselectwrapper.hpp"
|
|
|
|
#include <limits>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
|
|
#include <components/esm3/variant.hpp>
|
|
|
|
const char* CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings[] = {
|
|
"Faction Reaction Low",
|
|
"Faction Reaction High",
|
|
"Rank Requirement",
|
|
"Reputation",
|
|
"Health Percent",
|
|
"PC Reputation",
|
|
"PC Level",
|
|
"PC Health Percent",
|
|
"PC Magicka",
|
|
"PC Fatigue",
|
|
"PC Strength",
|
|
"PC Block",
|
|
"PC Armorer",
|
|
"PC Medium Armor",
|
|
"PC Heavy Armor",
|
|
"PC Blunt Weapon",
|
|
"PC Long Blade",
|
|
"PC Axe",
|
|
"PC Spear",
|
|
"PC Athletics",
|
|
"PC Enchant",
|
|
"PC Detruction",
|
|
"PC Alteration",
|
|
"PC Illusion",
|
|
"PC Conjuration",
|
|
"PC Mysticism",
|
|
"PC Restoration",
|
|
"PC Alchemy",
|
|
"PC Unarmored",
|
|
"PC Security",
|
|
"PC Sneak",
|
|
"PC Acrobatics",
|
|
"PC Light Armor",
|
|
"PC Short Blade",
|
|
"PC Marksman",
|
|
"PC Merchantile",
|
|
"PC Speechcraft",
|
|
"PC Hand to Hand",
|
|
"PC Sex",
|
|
"PC Expelled",
|
|
"PC Common Disease",
|
|
"PC Blight Disease",
|
|
"PC Clothing Modifier",
|
|
"PC Crime Level",
|
|
"Same Sex",
|
|
"Same Race",
|
|
"Same Faction",
|
|
"Faction Rank Difference",
|
|
"Detected",
|
|
"Alarmed",
|
|
"Choice",
|
|
"PC Intelligence",
|
|
"PC Willpower",
|
|
"PC Agility",
|
|
"PC Speed",
|
|
"PC Endurance",
|
|
"PC Personality",
|
|
"PC Luck",
|
|
"PC Corprus",
|
|
"Weather",
|
|
"PC Vampire",
|
|
"Level",
|
|
"Attacked",
|
|
"Talked to PC",
|
|
"PC Health",
|
|
"Creature Target",
|
|
"Friend Hit",
|
|
"Fight",
|
|
"Hello",
|
|
"Alarm",
|
|
"Flee",
|
|
"Should Attack",
|
|
"Werewolf",
|
|
"PC Werewolf Kills",
|
|
"Global",
|
|
"Local",
|
|
"Journal",
|
|
"Item",
|
|
"Dead",
|
|
"Not Id",
|
|
"Not Faction",
|
|
"Not Class",
|
|
"Not Race",
|
|
"Not Cell",
|
|
"Not Local",
|
|
nullptr,
|
|
};
|
|
|
|
const char* CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings[] = {
|
|
"=",
|
|
"!=",
|
|
">",
|
|
">=",
|
|
"<",
|
|
"<=",
|
|
nullptr,
|
|
};
|
|
|
|
namespace
|
|
{
|
|
std::string_view convertToString(ESM::DialogueCondition::Function name)
|
|
{
|
|
if (name < ESM::DialogueCondition::Function_None)
|
|
return CSMWorld::ConstInfoSelectWrapper::FunctionEnumStrings[name];
|
|
return "(Invalid Data: Function)";
|
|
}
|
|
|
|
std::string_view convertToString(ESM::DialogueCondition::Comparison type)
|
|
{
|
|
if (type != ESM::DialogueCondition::Comp_None)
|
|
return CSMWorld::ConstInfoSelectWrapper::RelationEnumStrings[type - ESM::DialogueCondition::Comp_Eq];
|
|
return "(Invalid Data: Relation)";
|
|
}
|
|
}
|
|
|
|
// ConstInfoSelectWrapper
|
|
|
|
CSMWorld::ConstInfoSelectWrapper::ConstInfoSelectWrapper(const ESM::DialogueCondition& select)
|
|
: mConstSelect(select)
|
|
{
|
|
updateHasVariable();
|
|
updateComparisonType();
|
|
}
|
|
|
|
ESM::DialogueCondition::Function CSMWorld::ConstInfoSelectWrapper::getFunctionName() const
|
|
{
|
|
return mConstSelect.mFunction;
|
|
}
|
|
|
|
ESM::DialogueCondition::Comparison CSMWorld::ConstInfoSelectWrapper::getRelationType() const
|
|
{
|
|
return mConstSelect.mComparison;
|
|
}
|
|
|
|
CSMWorld::ConstInfoSelectWrapper::ComparisonType CSMWorld::ConstInfoSelectWrapper::getComparisonType() const
|
|
{
|
|
return mComparisonType;
|
|
}
|
|
|
|
bool CSMWorld::ConstInfoSelectWrapper::hasVariable() const
|
|
{
|
|
return mHasVariable;
|
|
}
|
|
|
|
const std::string& CSMWorld::ConstInfoSelectWrapper::getVariableName() const
|
|
{
|
|
return mConstSelect.mVariable;
|
|
}
|
|
|
|
bool CSMWorld::ConstInfoSelectWrapper::conditionIsAlwaysTrue() const
|
|
{
|
|
if (mComparisonType == Comparison_Boolean || mComparisonType == Comparison_Integer)
|
|
{
|
|
if (std::holds_alternative<float>(mConstSelect.mValue))
|
|
return conditionIsAlwaysTrue(getConditionFloatRange(), getValidIntRange());
|
|
else
|
|
return conditionIsAlwaysTrue(getConditionIntRange(), getValidIntRange());
|
|
}
|
|
else if (mComparisonType == Comparison_Numeric)
|
|
{
|
|
if (std::holds_alternative<float>(mConstSelect.mValue))
|
|
return conditionIsAlwaysTrue(getConditionFloatRange(), getValidFloatRange());
|
|
else
|
|
return conditionIsAlwaysTrue(getConditionIntRange(), getValidFloatRange());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CSMWorld::ConstInfoSelectWrapper::conditionIsNeverTrue() const
|
|
{
|
|
if (mComparisonType == Comparison_Boolean || mComparisonType == Comparison_Integer)
|
|
{
|
|
if (std::holds_alternative<float>(mConstSelect.mValue))
|
|
return conditionIsNeverTrue(getConditionFloatRange(), getValidIntRange());
|
|
else
|
|
return conditionIsNeverTrue(getConditionIntRange(), getValidIntRange());
|
|
}
|
|
else if (mComparisonType == Comparison_Numeric)
|
|
{
|
|
if (std::holds_alternative<float>(mConstSelect.mValue))
|
|
return conditionIsNeverTrue(getConditionFloatRange(), getValidFloatRange());
|
|
else
|
|
return conditionIsNeverTrue(getConditionIntRange(), getValidFloatRange());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
std::string CSMWorld::ConstInfoSelectWrapper::toString() const
|
|
{
|
|
std::ostringstream stream;
|
|
stream << convertToString(getFunctionName()) << " ";
|
|
|
|
if (mHasVariable)
|
|
stream << getVariableName() << " ";
|
|
|
|
stream << convertToString(getRelationType()) << " ";
|
|
|
|
std::visit([&](auto value) { stream << value; }, mConstSelect.mValue);
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
void CSMWorld::ConstInfoSelectWrapper::updateHasVariable()
|
|
{
|
|
switch (getFunctionName())
|
|
{
|
|
case ESM::DialogueCondition::Function_Global:
|
|
case ESM::DialogueCondition::Function_Local:
|
|
case ESM::DialogueCondition::Function_Journal:
|
|
case ESM::DialogueCondition::Function_Item:
|
|
case ESM::DialogueCondition::Function_Dead:
|
|
case ESM::DialogueCondition::Function_NotId:
|
|
case ESM::DialogueCondition::Function_NotFaction:
|
|
case ESM::DialogueCondition::Function_NotClass:
|
|
case ESM::DialogueCondition::Function_NotRace:
|
|
case ESM::DialogueCondition::Function_NotCell:
|
|
case ESM::DialogueCondition::Function_NotLocal:
|
|
mHasVariable = true;
|
|
break;
|
|
|
|
default:
|
|
mHasVariable = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CSMWorld::ConstInfoSelectWrapper::updateComparisonType()
|
|
{
|
|
switch (getFunctionName())
|
|
{
|
|
// Boolean
|
|
case ESM::DialogueCondition::Function_NotId:
|
|
case ESM::DialogueCondition::Function_NotFaction:
|
|
case ESM::DialogueCondition::Function_NotClass:
|
|
case ESM::DialogueCondition::Function_NotRace:
|
|
case ESM::DialogueCondition::Function_NotCell:
|
|
case ESM::DialogueCondition::Function_PcExpelled:
|
|
case ESM::DialogueCondition::Function_PcCommonDisease:
|
|
case ESM::DialogueCondition::Function_PcBlightDisease:
|
|
case ESM::DialogueCondition::Function_SameSex:
|
|
case ESM::DialogueCondition::Function_SameRace:
|
|
case ESM::DialogueCondition::Function_SameFaction:
|
|
case ESM::DialogueCondition::Function_Detected:
|
|
case ESM::DialogueCondition::Function_Alarmed:
|
|
case ESM::DialogueCondition::Function_PcCorprus:
|
|
case ESM::DialogueCondition::Function_PcVampire:
|
|
case ESM::DialogueCondition::Function_Attacked:
|
|
case ESM::DialogueCondition::Function_TalkedToPc:
|
|
case ESM::DialogueCondition::Function_ShouldAttack:
|
|
case ESM::DialogueCondition::Function_Werewolf:
|
|
mComparisonType = Comparison_Boolean;
|
|
break;
|
|
|
|
// Integer
|
|
case ESM::DialogueCondition::Function_Journal:
|
|
case ESM::DialogueCondition::Function_Item:
|
|
case ESM::DialogueCondition::Function_Dead:
|
|
case ESM::DialogueCondition::Function_FacReactionLowest:
|
|
case ESM::DialogueCondition::Function_FacReactionHighest:
|
|
case ESM::DialogueCondition::Function_RankRequirement:
|
|
case ESM::DialogueCondition::Function_Reputation:
|
|
case ESM::DialogueCondition::Function_PcReputation:
|
|
case ESM::DialogueCondition::Function_PcLevel:
|
|
case ESM::DialogueCondition::Function_PcStrength:
|
|
case ESM::DialogueCondition::Function_PcBlock:
|
|
case ESM::DialogueCondition::Function_PcArmorer:
|
|
case ESM::DialogueCondition::Function_PcMediumArmor:
|
|
case ESM::DialogueCondition::Function_PcHeavyArmor:
|
|
case ESM::DialogueCondition::Function_PcBluntWeapon:
|
|
case ESM::DialogueCondition::Function_PcLongBlade:
|
|
case ESM::DialogueCondition::Function_PcAxe:
|
|
case ESM::DialogueCondition::Function_PcSpear:
|
|
case ESM::DialogueCondition::Function_PcAthletics:
|
|
case ESM::DialogueCondition::Function_PcEnchant:
|
|
case ESM::DialogueCondition::Function_PcDestruction:
|
|
case ESM::DialogueCondition::Function_PcAlteration:
|
|
case ESM::DialogueCondition::Function_PcIllusion:
|
|
case ESM::DialogueCondition::Function_PcConjuration:
|
|
case ESM::DialogueCondition::Function_PcMysticism:
|
|
case ESM::DialogueCondition::Function_PcRestoration:
|
|
case ESM::DialogueCondition::Function_PcAlchemy:
|
|
case ESM::DialogueCondition::Function_PcUnarmored:
|
|
case ESM::DialogueCondition::Function_PcSecurity:
|
|
case ESM::DialogueCondition::Function_PcSneak:
|
|
case ESM::DialogueCondition::Function_PcAcrobatics:
|
|
case ESM::DialogueCondition::Function_PcLightArmor:
|
|
case ESM::DialogueCondition::Function_PcShortBlade:
|
|
case ESM::DialogueCondition::Function_PcMarksman:
|
|
case ESM::DialogueCondition::Function_PcMerchantile:
|
|
case ESM::DialogueCondition::Function_PcSpeechcraft:
|
|
case ESM::DialogueCondition::Function_PcHandToHand:
|
|
case ESM::DialogueCondition::Function_PcGender:
|
|
case ESM::DialogueCondition::Function_PcClothingModifier:
|
|
case ESM::DialogueCondition::Function_PcCrimeLevel:
|
|
case ESM::DialogueCondition::Function_FactionRankDifference:
|
|
case ESM::DialogueCondition::Function_Choice:
|
|
case ESM::DialogueCondition::Function_PcIntelligence:
|
|
case ESM::DialogueCondition::Function_PcWillpower:
|
|
case ESM::DialogueCondition::Function_PcAgility:
|
|
case ESM::DialogueCondition::Function_PcSpeed:
|
|
case ESM::DialogueCondition::Function_PcEndurance:
|
|
case ESM::DialogueCondition::Function_PcPersonality:
|
|
case ESM::DialogueCondition::Function_PcLuck:
|
|
case ESM::DialogueCondition::Function_Weather:
|
|
case ESM::DialogueCondition::Function_Level:
|
|
case ESM::DialogueCondition::Function_CreatureTarget:
|
|
case ESM::DialogueCondition::Function_FriendHit:
|
|
case ESM::DialogueCondition::Function_Fight:
|
|
case ESM::DialogueCondition::Function_Hello:
|
|
case ESM::DialogueCondition::Function_Alarm:
|
|
case ESM::DialogueCondition::Function_Flee:
|
|
case ESM::DialogueCondition::Function_PcWerewolfKills:
|
|
mComparisonType = Comparison_Integer;
|
|
break;
|
|
|
|
// Numeric
|
|
case ESM::DialogueCondition::Function_Global:
|
|
case ESM::DialogueCondition::Function_Local:
|
|
case ESM::DialogueCondition::Function_NotLocal:
|
|
|
|
case ESM::DialogueCondition::Function_Health_Percent:
|
|
case ESM::DialogueCondition::Function_PcHealthPercent:
|
|
case ESM::DialogueCondition::Function_PcMagicka:
|
|
case ESM::DialogueCondition::Function_PcFatigue:
|
|
case ESM::DialogueCondition::Function_PcHealth:
|
|
mComparisonType = Comparison_Numeric;
|
|
break;
|
|
|
|
default:
|
|
mComparisonType = Comparison_None;
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::pair<int, int> CSMWorld::ConstInfoSelectWrapper::getConditionIntRange() const
|
|
{
|
|
const int IntMax = std::numeric_limits<int>::max();
|
|
const int IntMin = std::numeric_limits<int>::min();
|
|
const std::pair<int, int> InvalidRange(IntMax, IntMin);
|
|
|
|
int value = std::get<int>(mConstSelect.mValue);
|
|
|
|
switch (getRelationType())
|
|
{
|
|
case ESM::DialogueCondition::Comp_Eq:
|
|
case ESM::DialogueCondition::Comp_Ne:
|
|
return std::pair<int, int>(value, value);
|
|
|
|
case ESM::DialogueCondition::Comp_Gt:
|
|
if (value == IntMax)
|
|
{
|
|
return InvalidRange;
|
|
}
|
|
else
|
|
{
|
|
return std::pair<int, int>(value + 1, IntMax);
|
|
}
|
|
break;
|
|
|
|
case ESM::DialogueCondition::Comp_Ge:
|
|
return std::pair<int, int>(value, IntMax);
|
|
|
|
case ESM::DialogueCondition::Comp_Ls:
|
|
if (value == IntMin)
|
|
{
|
|
return InvalidRange;
|
|
}
|
|
else
|
|
{
|
|
return std::pair<int, int>(IntMin, value - 1);
|
|
}
|
|
|
|
case ESM::DialogueCondition::Comp_Le:
|
|
return std::pair<int, int>(IntMin, value);
|
|
|
|
default:
|
|
throw std::logic_error("InfoSelectWrapper: relation does not have a range");
|
|
}
|
|
}
|
|
|
|
std::pair<float, float> CSMWorld::ConstInfoSelectWrapper::getConditionFloatRange() const
|
|
{
|
|
const float FloatMax = std::numeric_limits<float>::infinity();
|
|
const float FloatMin = -std::numeric_limits<float>::infinity();
|
|
const float Epsilon = std::numeric_limits<float>::epsilon();
|
|
|
|
float value = std::get<float>(mConstSelect.mValue);
|
|
|
|
switch (getRelationType())
|
|
{
|
|
case ESM::DialogueCondition::Comp_Eq:
|
|
case ESM::DialogueCondition::Comp_Ne:
|
|
return std::pair<float, float>(value, value);
|
|
|
|
case ESM::DialogueCondition::Comp_Gt:
|
|
return std::pair<float, float>(value + Epsilon, FloatMax);
|
|
|
|
case ESM::DialogueCondition::Comp_Ge:
|
|
return std::pair<float, float>(value, FloatMax);
|
|
|
|
case ESM::DialogueCondition::Comp_Ls:
|
|
return std::pair<float, float>(FloatMin, value - Epsilon);
|
|
|
|
case ESM::DialogueCondition::Comp_Le:
|
|
return std::pair<float, float>(FloatMin, value);
|
|
|
|
default:
|
|
throw std::logic_error("InfoSelectWrapper: given relation does not have a range");
|
|
}
|
|
}
|
|
|
|
std::pair<int, int> CSMWorld::ConstInfoSelectWrapper::getValidIntRange() const
|
|
{
|
|
const int IntMax = std::numeric_limits<int>::max();
|
|
const int IntMin = std::numeric_limits<int>::min();
|
|
|
|
switch (getFunctionName())
|
|
{
|
|
// Boolean
|
|
case ESM::DialogueCondition::Function_NotId:
|
|
case ESM::DialogueCondition::Function_NotFaction:
|
|
case ESM::DialogueCondition::Function_NotClass:
|
|
case ESM::DialogueCondition::Function_NotRace:
|
|
case ESM::DialogueCondition::Function_NotCell:
|
|
case ESM::DialogueCondition::Function_PcExpelled:
|
|
case ESM::DialogueCondition::Function_PcCommonDisease:
|
|
case ESM::DialogueCondition::Function_PcBlightDisease:
|
|
case ESM::DialogueCondition::Function_SameSex:
|
|
case ESM::DialogueCondition::Function_SameRace:
|
|
case ESM::DialogueCondition::Function_SameFaction:
|
|
case ESM::DialogueCondition::Function_Detected:
|
|
case ESM::DialogueCondition::Function_Alarmed:
|
|
case ESM::DialogueCondition::Function_PcCorprus:
|
|
case ESM::DialogueCondition::Function_PcVampire:
|
|
case ESM::DialogueCondition::Function_Attacked:
|
|
case ESM::DialogueCondition::Function_TalkedToPc:
|
|
case ESM::DialogueCondition::Function_ShouldAttack:
|
|
case ESM::DialogueCondition::Function_Werewolf:
|
|
return std::pair<int, int>(0, 1);
|
|
|
|
// Integer
|
|
case ESM::DialogueCondition::Function_FacReactionLowest:
|
|
case ESM::DialogueCondition::Function_FacReactionHighest:
|
|
case ESM::DialogueCondition::Function_Reputation:
|
|
case ESM::DialogueCondition::Function_PcReputation:
|
|
case ESM::DialogueCondition::Function_Journal:
|
|
return std::pair<int, int>(IntMin, IntMax);
|
|
|
|
case ESM::DialogueCondition::Function_Item:
|
|
case ESM::DialogueCondition::Function_Dead:
|
|
case ESM::DialogueCondition::Function_PcLevel:
|
|
case ESM::DialogueCondition::Function_PcStrength:
|
|
case ESM::DialogueCondition::Function_PcBlock:
|
|
case ESM::DialogueCondition::Function_PcArmorer:
|
|
case ESM::DialogueCondition::Function_PcMediumArmor:
|
|
case ESM::DialogueCondition::Function_PcHeavyArmor:
|
|
case ESM::DialogueCondition::Function_PcBluntWeapon:
|
|
case ESM::DialogueCondition::Function_PcLongBlade:
|
|
case ESM::DialogueCondition::Function_PcAxe:
|
|
case ESM::DialogueCondition::Function_PcSpear:
|
|
case ESM::DialogueCondition::Function_PcAthletics:
|
|
case ESM::DialogueCondition::Function_PcEnchant:
|
|
case ESM::DialogueCondition::Function_PcDestruction:
|
|
case ESM::DialogueCondition::Function_PcAlteration:
|
|
case ESM::DialogueCondition::Function_PcIllusion:
|
|
case ESM::DialogueCondition::Function_PcConjuration:
|
|
case ESM::DialogueCondition::Function_PcMysticism:
|
|
case ESM::DialogueCondition::Function_PcRestoration:
|
|
case ESM::DialogueCondition::Function_PcAlchemy:
|
|
case ESM::DialogueCondition::Function_PcUnarmored:
|
|
case ESM::DialogueCondition::Function_PcSecurity:
|
|
case ESM::DialogueCondition::Function_PcSneak:
|
|
case ESM::DialogueCondition::Function_PcAcrobatics:
|
|
case ESM::DialogueCondition::Function_PcLightArmor:
|
|
case ESM::DialogueCondition::Function_PcShortBlade:
|
|
case ESM::DialogueCondition::Function_PcMarksman:
|
|
case ESM::DialogueCondition::Function_PcMerchantile:
|
|
case ESM::DialogueCondition::Function_PcSpeechcraft:
|
|
case ESM::DialogueCondition::Function_PcHandToHand:
|
|
case ESM::DialogueCondition::Function_PcClothingModifier:
|
|
case ESM::DialogueCondition::Function_PcCrimeLevel:
|
|
case ESM::DialogueCondition::Function_Choice:
|
|
case ESM::DialogueCondition::Function_PcIntelligence:
|
|
case ESM::DialogueCondition::Function_PcWillpower:
|
|
case ESM::DialogueCondition::Function_PcAgility:
|
|
case ESM::DialogueCondition::Function_PcSpeed:
|
|
case ESM::DialogueCondition::Function_PcEndurance:
|
|
case ESM::DialogueCondition::Function_PcPersonality:
|
|
case ESM::DialogueCondition::Function_PcLuck:
|
|
case ESM::DialogueCondition::Function_Level:
|
|
case ESM::DialogueCondition::Function_PcWerewolfKills:
|
|
return std::pair<int, int>(0, IntMax);
|
|
|
|
case ESM::DialogueCondition::Function_Fight:
|
|
case ESM::DialogueCondition::Function_Hello:
|
|
case ESM::DialogueCondition::Function_Alarm:
|
|
case ESM::DialogueCondition::Function_Flee:
|
|
return std::pair<int, int>(0, 100);
|
|
|
|
case ESM::DialogueCondition::Function_Weather:
|
|
return std::pair<int, int>(0, 9);
|
|
|
|
case ESM::DialogueCondition::Function_FriendHit:
|
|
return std::pair<int, int>(0, 4);
|
|
|
|
case ESM::DialogueCondition::Function_RankRequirement:
|
|
return std::pair<int, int>(0, 3);
|
|
|
|
case ESM::DialogueCondition::Function_CreatureTarget:
|
|
return std::pair<int, int>(0, 2);
|
|
|
|
case ESM::DialogueCondition::Function_PcGender:
|
|
return std::pair<int, int>(0, 1);
|
|
|
|
case ESM::DialogueCondition::Function_FactionRankDifference:
|
|
return std::pair<int, int>(-9, 9);
|
|
|
|
// Numeric
|
|
case ESM::DialogueCondition::Function_Global:
|
|
case ESM::DialogueCondition::Function_Local:
|
|
case ESM::DialogueCondition::Function_NotLocal:
|
|
return std::pair<int, int>(IntMin, IntMax);
|
|
|
|
case ESM::DialogueCondition::Function_PcMagicka:
|
|
case ESM::DialogueCondition::Function_PcFatigue:
|
|
case ESM::DialogueCondition::Function_PcHealth:
|
|
return std::pair<int, int>(0, IntMax);
|
|
|
|
case ESM::DialogueCondition::Function_Health_Percent:
|
|
case ESM::DialogueCondition::Function_PcHealthPercent:
|
|
return std::pair<int, int>(0, 100);
|
|
|
|
default:
|
|
throw std::runtime_error("InfoSelectWrapper: function does not exist");
|
|
}
|
|
}
|
|
|
|
std::pair<float, float> CSMWorld::ConstInfoSelectWrapper::getValidFloatRange() const
|
|
{
|
|
const float FloatMax = std::numeric_limits<float>::infinity();
|
|
const float FloatMin = -std::numeric_limits<float>::infinity();
|
|
|
|
switch (getFunctionName())
|
|
{
|
|
// Numeric
|
|
case ESM::DialogueCondition::Function_Global:
|
|
case ESM::DialogueCondition::Function_Local:
|
|
case ESM::DialogueCondition::Function_NotLocal:
|
|
return std::pair<float, float>(FloatMin, FloatMax);
|
|
|
|
case ESM::DialogueCondition::Function_PcMagicka:
|
|
case ESM::DialogueCondition::Function_PcFatigue:
|
|
case ESM::DialogueCondition::Function_PcHealth:
|
|
return std::pair<float, float>(0, FloatMax);
|
|
|
|
case ESM::DialogueCondition::Function_Health_Percent:
|
|
case ESM::DialogueCondition::Function_PcHealthPercent:
|
|
return std::pair<float, float>(0, 100);
|
|
|
|
default:
|
|
throw std::runtime_error("InfoSelectWrapper: function does not exist or is not numeric");
|
|
}
|
|
}
|
|
|
|
template <typename T1, typename T2>
|
|
bool CSMWorld::ConstInfoSelectWrapper::rangeContains(T1 value, std::pair<T2, T2> range) const
|
|
{
|
|
return (value >= range.first && value <= range.second);
|
|
}
|
|
|
|
template <typename T1, typename T2>
|
|
bool CSMWorld::ConstInfoSelectWrapper::rangeFullyContains(
|
|
std::pair<T1, T1> containingRange, std::pair<T2, T2> testRange) const
|
|
{
|
|
return (containingRange.first <= testRange.first) && (testRange.second <= containingRange.second);
|
|
}
|
|
|
|
template <typename T1, typename T2>
|
|
bool CSMWorld::ConstInfoSelectWrapper::rangesOverlap(std::pair<T1, T1> range1, std::pair<T2, T2> range2) const
|
|
{
|
|
// One of the bounds of either range should fall within the other range
|
|
return (range1.first <= range2.first && range2.first <= range1.second)
|
|
|| (range1.first <= range2.second && range2.second <= range1.second)
|
|
|| (range2.first <= range1.first && range1.first <= range2.second)
|
|
|| (range2.first <= range1.second && range1.second <= range2.second);
|
|
}
|
|
|
|
template <typename T1, typename T2>
|
|
bool CSMWorld::ConstInfoSelectWrapper::rangesMatch(std::pair<T1, T1> range1, std::pair<T2, T2> range2) const
|
|
{
|
|
return (range1.first == range2.first && range1.second == range2.second);
|
|
}
|
|
|
|
template <typename T1, typename T2>
|
|
bool CSMWorld::ConstInfoSelectWrapper::conditionIsAlwaysTrue(
|
|
std::pair<T1, T1> conditionRange, std::pair<T2, T2> validRange) const
|
|
{
|
|
switch (getRelationType())
|
|
{
|
|
case ESM::DialogueCondition::Comp_Eq:
|
|
return false;
|
|
|
|
case ESM::DialogueCondition::Comp_Ne:
|
|
// If value is not within range, it will always be true
|
|
return !rangeContains(conditionRange.first, validRange);
|
|
|
|
case ESM::DialogueCondition::Comp_Gt:
|
|
case ESM::DialogueCondition::Comp_Ge:
|
|
case ESM::DialogueCondition::Comp_Ls:
|
|
case ESM::DialogueCondition::Comp_Le:
|
|
// If the valid range is completely within the condition range, it will always be true
|
|
return rangeFullyContains(conditionRange, validRange);
|
|
|
|
default:
|
|
throw std::logic_error("InfoCondition: operator can not be used to compare");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template <typename T1, typename T2>
|
|
bool CSMWorld::ConstInfoSelectWrapper::conditionIsNeverTrue(
|
|
std::pair<T1, T1> conditionRange, std::pair<T2, T2> validRange) const
|
|
{
|
|
switch (getRelationType())
|
|
{
|
|
case ESM::DialogueCondition::Comp_Eq:
|
|
return !rangeContains(conditionRange.first, validRange);
|
|
|
|
case ESM::DialogueCondition::Comp_Ne:
|
|
return false;
|
|
|
|
case ESM::DialogueCondition::Comp_Gt:
|
|
case ESM::DialogueCondition::Comp_Ge:
|
|
case ESM::DialogueCondition::Comp_Ls:
|
|
case ESM::DialogueCondition::Comp_Le:
|
|
// If ranges do not overlap, it will never be true
|
|
return !rangesOverlap(conditionRange, validRange);
|
|
|
|
default:
|
|
throw std::logic_error("InfoCondition: operator can not be used to compare");
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
QVariant CSMWorld::ConstInfoSelectWrapper::getValue() const
|
|
{
|
|
return std::visit([](auto value) { return QVariant(value); }, mConstSelect.mValue);
|
|
}
|
|
|
|
// InfoSelectWrapper
|
|
|
|
CSMWorld::InfoSelectWrapper::InfoSelectWrapper(ESM::DialogueCondition& select)
|
|
: CSMWorld::ConstInfoSelectWrapper(select)
|
|
, mSelect(select)
|
|
{
|
|
}
|
|
|
|
void CSMWorld::InfoSelectWrapper::setFunctionName(ESM::DialogueCondition::Function name)
|
|
{
|
|
mSelect.mFunction = name;
|
|
updateHasVariable();
|
|
updateComparisonType();
|
|
if (getComparisonType() != ConstInfoSelectWrapper::Comparison_Numeric
|
|
&& std::holds_alternative<float>(mSelect.mValue))
|
|
{
|
|
mSelect.mValue = std::visit([](auto value) { return static_cast<int>(value); }, mSelect.mValue);
|
|
}
|
|
}
|
|
|
|
void CSMWorld::InfoSelectWrapper::setRelationType(ESM::DialogueCondition::Comparison type)
|
|
{
|
|
mSelect.mComparison = type;
|
|
}
|
|
|
|
void CSMWorld::InfoSelectWrapper::setVariableName(const std::string& name)
|
|
{
|
|
mSelect.mVariable = name;
|
|
}
|
|
|
|
void CSMWorld::InfoSelectWrapper::setValue(int value)
|
|
{
|
|
mSelect.mValue = value;
|
|
}
|
|
|
|
void CSMWorld::InfoSelectWrapper::setValue(float value)
|
|
{
|
|
mSelect.mValue = value;
|
|
}
|