From d3bc79e9b22bfd7df8fbd040f09e79c1a6ac1298 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 1 Feb 2023 21:57:50 +0100 Subject: [PATCH] Reduce code duplication --- components/interpreter/defines.cpp | 255 ++++++++++------------------- 1 file changed, 86 insertions(+), 169 deletions(-) diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp index 4f1011c6c8..5b8db5c33e 100644 --- a/components/interpreter/defines.cpp +++ b/components/interpreter/defines.cpp @@ -4,12 +4,14 @@ #include #include #include +#include +#include #include #include #include -namespace Interpreter +namespace { bool check(std::string_view str, std::string_view escword, size_t& i, size_t& start) @@ -24,13 +26,89 @@ namespace Interpreter } std::vector globals; + const std::initializer_list> sActionBindings{ + { "actionslideright", "#{sRight}" }, + { "actionreadymagic", "#{sReady_Magic}" }, + { "actionprevweapon", "#{sPrevWeapon}" }, + { "actionnextweapon", "#{sNextWeapon}" }, + { "actiontogglerun", "#{sAuto_Run}" }, + { "actionslideleft", "#{sLeft}" }, + { "actionreadyitem", "#{sReady_Weapon}" }, + { "actionprevspell", "#{sPrevSpell}" }, + { "actionnextspell", "#{sNextSpell}" }, + { "actionrestmenu", "#{sRestKey}" }, + { "actionmenumode", "#{sInventory}" }, + { "actionactivate", "#{sActivate}" }, + { "actionjournal", "#{sJournal}" }, + { "actionforward", "#{sForward}" }, + { "actioncrouch", "#{sCrouch_Sneak}" }, + { "actionjump", "#{sJump}" }, + { "actionback", "#{sBack}" }, + { "actionuse", "#{sUse}" }, + { "actionrun", "#{sRun}" }, + }; + template + using ContextMethod = T (Interpreter::Context::*)() const; + const std::initializer_list< + std::tuple, ContextMethod>>> + sContextMethods{ + { "pccrimelevel", &Interpreter::Context::getPCBounty }, + { "pcclass", &Interpreter::Context::getPCClass }, + { "pcrace", &Interpreter::Context::getPCRace }, + { "pcname", &Interpreter::Context::getPCName }, + { "cell", &Interpreter::Context::getCurrentCellName }, + }; + const std::initializer_list< + std::tuple, ContextMethod>>> + sVariableContextMethods{ + { "faction", { &Interpreter::Context::getNPCFaction, nullptr } }, + { "nextpcrank", { &Interpreter::Context::getPCNextRank, nullptr } }, + { "pcnextrank", { &Interpreter::Context::getPCNextRank, nullptr } }, + { "pcrank", { &Interpreter::Context::getPCRank, nullptr } }, + { "rank", { &Interpreter::Context::getNPCRank, nullptr } }, + { "class", { &Interpreter::Context::getNPCClass, &Interpreter::Context::getPCClass } }, + { "race", { &Interpreter::Context::getNPCRace, &Interpreter::Context::getPCRace } }, + { "name", { &Interpreter::Context::getActorName, &Interpreter::Context::getPCName } }, + }; bool longerStr(std::string_view a, std::string_view b) { return a.length() > b.length(); } - static std::string fixDefinesReal(std::string_view text, bool dialogue, Context& context) + bool findReplacement(std::string_view temp, size_t& i, size_t& start, Interpreter::Context& context, + std::ostringstream& retval, bool dialogue) + { + for (const auto& [name, binding] : sActionBindings) + { + if (check(temp, name, i, start)) + { + retval << context.getActionBinding(binding); + return true; + } + } + for (const auto& [name, variant] : sContextMethods) + { + if (check(temp, name, i, start)) + { + std::visit([&](auto&& method) { retval << (context.*method)(); }, variant); + return true; + } + } + for (const auto& [name, methods] : sVariableContextMethods) + { + const auto& method = dialogue ? methods.first : methods.second; + if (check(temp, name, i, start)) + { + if (method) // Not all variables are available outside of dialogue + retval << (context.*method)(); + return true; + } + } + return false; + } + + std::string fixDefinesReal(std::string_view text, bool dialogue, Interpreter::Context& context) { size_t start = 0; std::ostringstream retval; @@ -40,174 +118,12 @@ namespace Interpreter if (eschar == '%' || eschar == '^') { retval << text.substr(start, i - start); - std::string_view temp = text.substr(i + 1, 100); + std::string_view temp = text.substr(i + 1); bool found = false; try { - if ((found = check(temp, "actionslideright", i, start))) - { - retval << context.getActionBinding("#{sRight}"); - } - else if ((found = check(temp, "actionreadymagic", i, start))) - { - retval << context.getActionBinding("#{sReady_Magic}"); - } - else if ((found = check(temp, "actionprevweapon", i, start))) - { - retval << context.getActionBinding("#{sPrevWeapon}"); - } - else if ((found = check(temp, "actionnextweapon", i, start))) - { - retval << context.getActionBinding("#{sNextWeapon}"); - } - else if ((found = check(temp, "actiontogglerun", i, start))) - { - retval << context.getActionBinding("#{sAuto_Run}"); - } - else if ((found = check(temp, "actionslideleft", i, start))) - { - retval << context.getActionBinding("#{sLeft}"); - } - else if ((found = check(temp, "actionreadyitem", i, start))) - { - retval << context.getActionBinding("#{sReady_Weapon}"); - } - else if ((found = check(temp, "actionprevspell", i, start))) - { - retval << context.getActionBinding("#{sPrevSpell}"); - } - else if ((found = check(temp, "actionnextspell", i, start))) - { - retval << context.getActionBinding("#{sNextSpell}"); - } - else if ((found = check(temp, "actionrestmenu", i, start))) - { - retval << context.getActionBinding("#{sRestKey}"); - } - else if ((found = check(temp, "actionmenumode", i, start))) - { - retval << context.getActionBinding("#{sInventory}"); - } - else if ((found = check(temp, "actionactivate", i, start))) - { - retval << context.getActionBinding("#{sActivate}"); - } - else if ((found = check(temp, "actionjournal", i, start))) - { - retval << context.getActionBinding("#{sJournal}"); - } - else if ((found = check(temp, "actionforward", i, start))) - { - retval << context.getActionBinding("#{sForward}"); - } - else if ((found = check(temp, "pccrimelevel", i, start))) - { - retval << context.getPCBounty(); - } - else if ((found = check(temp, "actioncrouch", i, start))) - { - retval << context.getActionBinding("#{sCrouch_Sneak}"); - } - else if ((found = check(temp, "actionjump", i, start))) - { - retval << context.getActionBinding("#{sJump}"); - } - else if ((found = check(temp, "actionback", i, start))) - { - retval << context.getActionBinding("#{sBack}"); - } - else if ((found = check(temp, "actionuse", i, start))) - { - retval << context.getActionBinding("#{sUse}"); - } - else if ((found = check(temp, "actionrun", i, start))) - { - retval << context.getActionBinding("#{sRun}"); - } - else if ((found = check(temp, "pcclass", i, start))) - { - retval << context.getPCClass(); - } - else if ((found = check(temp, "pcrace", i, start))) - { - retval << context.getPCRace(); - } - else if ((found = check(temp, "pcname", i, start))) - { - retval << context.getPCName(); - } - else if ((found = check(temp, "cell", i, start))) - { - retval << context.getCurrentCellName(); - } - - else if (dialogue) - { // In Dialogue, not messagebox - if ((found = check(temp, "faction", i, start))) - { - retval << context.getNPCFaction(); - } - else if ((found = check(temp, "nextpcrank", i, start))) - { - retval << context.getPCNextRank(); - } - else if ((found = check(temp, "pcnextrank", i, start))) - { - retval << context.getPCNextRank(); - } - else if ((found = check(temp, "pcrank", i, start))) - { - retval << context.getPCRank(); - } - else if ((found = check(temp, "rank", i, start))) - { - retval << context.getNPCRank(); - } - - else if ((found = check(temp, "class", i, start))) - { - retval << context.getNPCClass(); - } - else if ((found = check(temp, "race", i, start))) - { - retval << context.getNPCRace(); - } - else if ((found = check(temp, "name", i, start))) - { - retval << context.getActorName(); - } - } - else - { // In messagebox or book, not dialogue - - /* empty outside dialogue */ - if ((found = check(temp, "faction", i, start))) - ; - else if ((found = check(temp, "nextpcrank", i, start))) - ; - else if ((found = check(temp, "pcnextrank", i, start))) - ; - else if ((found = check(temp, "pcrank", i, start))) - ; - else if ((found = check(temp, "rank", i, start))) - ; - - /* uses pc in messageboxes */ - else if ((found = check(temp, "class", i, start))) - { - retval << context.getPCClass(); - } - else if ((found = check(temp, "race", i, start))) - { - retval << context.getPCRace(); - } - else if ((found = check(temp, "name", i, start))) - { - retval << context.getPCName(); - } - } - + found = findReplacement(temp, i, start, context, retval, dialogue); /* Not a builtin, try global variables */ if (!found) { @@ -220,9 +136,6 @@ namespace Interpreter for (const std::string& global : globals) { - if (global.length() > temp.length()) // Just in case there's a global with a huuuge name - temp = text.substr(i + 1, global.length()); - found = check(temp, global, i, start); if (found) { @@ -266,6 +179,10 @@ namespace Interpreter return retval.str(); } +} + +namespace Interpreter +{ std::string fixDefinesDialog(const std::string& text, Context& context) { return fixDefinesReal(text, true, context);