1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-09 21:42:13 +00:00
OpenMW/apps/openmw/mwdialogue/selectwrapper.cpp
2023-03-18 09:30:48 +00:00

459 lines
11 KiB
C++

#include "selectwrapper.hpp"
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <components/misc/strings/conversion.hpp>
#include <components/misc/strings/lower.hpp>
namespace
{
template <typename T1, typename T2>
bool selectCompareImp(char comp, T1 value1, T2 value2)
{
switch (comp)
{
case '0':
return value1 == value2;
case '1':
return value1 != value2;
case '2':
return value1 > value2;
case '3':
return value1 >= value2;
case '4':
return value1 < value2;
case '5':
return value1 <= value2;
}
throw std::runtime_error("unknown compare type in dialogue info select");
}
template <typename T>
bool selectCompareImp(const ESM::DialInfo::SelectStruct& select, T value1)
{
if (select.mValue.getType() == ESM::VT_Int)
{
return selectCompareImp(select.mSelectRule[4], value1, select.mValue.getInteger());
}
else if (select.mValue.getType() == ESM::VT_Float)
{
return selectCompareImp(select.mSelectRule[4], value1, select.mValue.getFloat());
}
else
throw std::runtime_error("unsupported variable type in dialogue info select");
}
}
MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::decodeFunction() const
{
const int index = Misc::StringUtils::toNumeric<int>(mSelect.mSelectRule.substr(2, 2), 0);
switch (index)
{
case 0:
return Function_RankLow;
case 1:
return Function_RankHigh;
case 2:
return Function_RankRequirement;
case 3:
return Function_Reputation;
case 4:
return Function_HealthPercent;
case 5:
return Function_PCReputation;
case 6:
return Function_PcLevel;
case 7:
return Function_PcHealthPercent;
case 8:
case 9:
return Function_PcDynamicStat;
case 10:
return Function_PcAttribute;
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
return Function_PcSkill;
case 38:
return Function_PcGender;
case 39:
return Function_PcExpelled;
case 40:
return Function_PcCommonDisease;
case 41:
return Function_PcBlightDisease;
case 42:
return Function_PcClothingModifier;
case 43:
return Function_PcCrimeLevel;
case 44:
return Function_SameGender;
case 45:
return Function_SameRace;
case 46:
return Function_SameFaction;
case 47:
return Function_FactionRankDiff;
case 48:
return Function_Detected;
case 49:
return Function_Alarmed;
case 50:
return Function_Choice;
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
return Function_PcAttribute;
case 58:
return Function_PcCorprus;
case 59:
return Function_Weather;
case 60:
return Function_PcVampire;
case 61:
return Function_Level;
case 62:
return Function_Attacked;
case 63:
return Function_TalkedToPc;
case 64:
return Function_PcDynamicStat;
case 65:
return Function_CreatureTargetted;
case 66:
return Function_FriendlyHit;
case 67:
case 68:
case 69:
case 70:
return Function_AiSetting;
case 71:
return Function_ShouldAttack;
case 72:
return Function_Werewolf;
case 73:
return Function_WerewolfKills;
}
return Function_False;
}
MWDialogue::SelectWrapper::SelectWrapper(const ESM::DialInfo::SelectStruct& select)
: mSelect(select)
{
}
MWDialogue::SelectWrapper::Function MWDialogue::SelectWrapper::getFunction() const
{
char type = mSelect.mSelectRule[1];
switch (type)
{
case '1':
return decodeFunction();
case '2':
return Function_Global;
case '3':
return Function_Local;
case '4':
return Function_Journal;
case '5':
return Function_Item;
case '6':
return Function_Dead;
case '7':
return Function_NotId;
case '8':
return Function_NotFaction;
case '9':
return Function_NotClass;
case 'A':
return Function_NotRace;
case 'B':
return Function_NotCell;
case 'C':
return Function_NotLocal;
}
return Function_None;
}
int MWDialogue::SelectWrapper::getArgument() const
{
if (mSelect.mSelectRule[1] != '1')
return 0;
int index = 0;
std::istringstream(mSelect.mSelectRule.substr(2, 2)) >> index;
switch (index)
{
// AI settings
case 67:
return 1;
case 68:
return 0;
case 69:
return 3;
case 70:
return 2;
// attributes
case 10:
return 0;
case 51:
return 1;
case 52:
return 2;
case 53:
return 3;
case 54:
return 4;
case 55:
return 5;
case 56:
return 6;
case 57:
return 7;
// skills
case 11:
return 0;
case 12:
return 1;
case 13:
return 2;
case 14:
return 3;
case 15:
return 4;
case 16:
return 5;
case 17:
return 6;
case 18:
return 7;
case 19:
return 8;
case 20:
return 9;
case 21:
return 10;
case 22:
return 11;
case 23:
return 12;
case 24:
return 13;
case 25:
return 14;
case 26:
return 15;
case 27:
return 16;
case 28:
return 17;
case 29:
return 18;
case 30:
return 19;
case 31:
return 20;
case 32:
return 21;
case 33:
return 22;
case 34:
return 23;
case 35:
return 24;
case 36:
return 25;
case 37:
return 26;
// dynamic stats
case 8:
return 1;
case 9:
return 2;
case 64:
return 0;
}
return 0;
}
MWDialogue::SelectWrapper::Type MWDialogue::SelectWrapper::getType() const
{
static const Function integerFunctions[] = {
Function_Journal,
Function_Item,
Function_Dead,
Function_Choice,
Function_AiSetting,
Function_PcAttribute,
Function_PcSkill,
Function_FriendlyHit,
Function_PcLevel,
Function_PcGender,
Function_PcClothingModifier,
Function_PcCrimeLevel,
Function_RankRequirement,
Function_Level,
Function_PCReputation,
Function_Weather,
Function_Reputation,
Function_FactionRankDiff,
Function_WerewolfKills,
Function_RankLow,
Function_RankHigh,
Function_CreatureTargetted,
// end marker
Function_None,
};
static const Function numericFunctions[] = {
Function_Global,
Function_Local,
Function_NotLocal,
Function_PcDynamicStat,
Function_PcHealthPercent,
Function_HealthPercent,
// end marker
Function_None,
};
static const Function booleanFunctions[] = {
Function_False,
Function_SameGender,
Function_SameRace,
Function_SameFaction,
Function_PcCommonDisease,
Function_PcBlightDisease,
Function_PcCorprus,
Function_PcExpelled,
Function_PcVampire,
Function_TalkedToPc,
Function_Alarmed,
Function_Detected,
Function_Attacked,
Function_ShouldAttack,
Function_Werewolf,
// end marker
Function_None,
};
static const Function invertedBooleanFunctions[] = {
Function_NotId,
Function_NotFaction,
Function_NotClass,
Function_NotRace,
Function_NotCell,
// end marker
Function_None,
};
Function function = getFunction();
for (int i = 0; integerFunctions[i] != Function_None; ++i)
if (integerFunctions[i] == function)
return Type_Integer;
for (int i = 0; numericFunctions[i] != Function_None; ++i)
if (numericFunctions[i] == function)
return Type_Numeric;
for (int i = 0; booleanFunctions[i] != Function_None; ++i)
if (booleanFunctions[i] == function)
return Type_Boolean;
for (int i = 0; invertedBooleanFunctions[i] != Function_None; ++i)
if (invertedBooleanFunctions[i] == function)
return Type_Inverted;
return Type_None;
}
bool MWDialogue::SelectWrapper::isNpcOnly() const
{
static const Function functions[] = {
Function_NotFaction,
Function_NotClass,
Function_NotRace,
Function_SameGender,
Function_SameRace,
Function_SameFaction,
Function_RankRequirement,
Function_Reputation,
Function_FactionRankDiff,
Function_Werewolf,
Function_WerewolfKills,
Function_RankLow,
Function_RankHigh,
// end marker
Function_None,
};
Function function = getFunction();
for (int i = 0; functions[i] != Function_None; ++i)
if (functions[i] == function)
return true;
return false;
}
bool MWDialogue::SelectWrapper::selectCompare(int value) const
{
return selectCompareImp(mSelect, value);
}
bool MWDialogue::SelectWrapper::selectCompare(float value) const
{
return selectCompareImp(mSelect, value);
}
bool MWDialogue::SelectWrapper::selectCompare(bool value) const
{
return selectCompareImp(mSelect, static_cast<int>(value));
}
std::string MWDialogue::SelectWrapper::getName() const
{
return Misc::StringUtils::lowerCase(std::string_view(mSelect.mSelectRule).substr(5));
}