diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index 52021839d..d8d13a921 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -311,6 +311,9 @@ namespace MWScript std::string InterpreterContext::getNPCRank() const { + if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty()) + throw std::runtime_error("getNPCRank(): NPC is not in a faction"); + const std::map& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks(); std::map::const_iterator it = ranks.begin(); @@ -347,6 +350,9 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); + if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty()) + throw std::runtime_error("getPCRank(): NPC is not in a faction"); + std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first; const std::map& ranks = player.getClass().getNpcStats (player).getFactionRanks(); @@ -374,6 +380,9 @@ namespace MWScript MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); + if (getReferenceImp().getClass().getNpcStats(getReferenceImp()).getFactionRanks().empty()) + throw std::runtime_error("getPCNextRank(): NPC is not in a faction"); + std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first; const std::map& ranks = player.getClass().getNpcStats (player).getFactionRanks(); diff --git a/components/interpreter/defines.cpp b/components/interpreter/defines.cpp index 6f3b5bb5a..94916ee85 100644 --- a/components/interpreter/defines.cpp +++ b/components/interpreter/defines.cpp @@ -4,10 +4,12 @@ #include #include #include +#include namespace Interpreter{ - bool Check(const std::string& str, const std::string& escword, unsigned int* i, unsigned int* start){ + bool check(const std::string& str, const std::string& escword, unsigned int* i, unsigned int* start) + { bool retval = str.find(escword) == 0; if(retval){ (*i) += escword.length(); @@ -18,170 +20,181 @@ namespace Interpreter{ std::vector globals; - bool longerStr(const std::string& a, const std::string& b){ + bool longerStr(const std::string& a, const std::string& b) + { return a.length() > b.length(); } - std::string fixDefinesReal(std::string text, char eschar, bool isBook, Context& context){ + std::string fixDefinesReal(std::string text, char eschar, bool isBook, Context& context) + { unsigned int start = 0; std::ostringstream retval; - for(unsigned int i = 0; i < text.length(); i++){ - if(text[i] == eschar){ + for(unsigned int i = 0; i < text.length(); i++) + { + if(text[i] == eschar) + { retval << text.substr(start, i - start); std::string temp = text.substr(i+1, 100); transform(temp.begin(), temp.end(), temp.begin(), ::tolower); - bool found; - - 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 << "PLACEHOLDER_ACTION_PREV_WEAPON"; - } - else if((found = Check(temp, "actionnextweapon", &i, &start))){ - retval << "PLACEHOLDER_ACTION_PREV_WEAPON"; - } - 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 << "PLACEHOLDER_ACTION_PREV_SPELL"; - } - else if((found = Check(temp, "actionnextspell", &i, &start))){ - retval << "PLACEHOLDER_ACTION_NEXT_SPELL"; - } - 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(eschar == '%' && !isBook) { // In Dialogue, not messagebox - if( (found = Check(temp, "faction", &i, &start))){ - retval << context.getNPCFaction(); + bool found = false; + try + { + if( (found = check(temp, "actionslideright", &i, &start))){ + retval << context.getActionBinding("#{sRight}"); } - else if((found = Check(temp, "nextpcrank", &i, &start))){ - retval << context.getPCNextRank(); + else if((found = check(temp, "actionreadymagic", &i, &start))){ + retval << context.getActionBinding("#{sReady_Magic}"); } - else if((found = Check(temp, "pcnextrank", &i, &start))){ - retval << context.getPCNextRank(); + else if((found = check(temp, "actionprevweapon", &i, &start))){ + retval << "PLACEHOLDER_ACTION_PREV_WEAPON"; } - else if((found = Check(temp, "pcrank", &i, &start))){ - retval << context.getPCRank(); + else if((found = check(temp, "actionnextweapon", &i, &start))){ + retval << "PLACEHOLDER_ACTION_PREV_WEAPON"; } - else if((found = Check(temp, "rank", &i, &start))){ - retval << context.getNPCRank(); + else if((found = check(temp, "actiontogglerun", &i, &start))){ + retval << context.getActionBinding("#{sAuto_Run}"); } - - else if((found = Check(temp, "class", &i, &start))){ - retval << context.getNPCClass(); + else if((found = check(temp, "actionslideleft", &i, &start))){ + retval << context.getActionBinding("#{sLeft}"); } - else if((found = Check(temp, "race", &i, &start))){ - retval << context.getNPCRace(); + else if((found = check(temp, "actionreadyitem", &i, &start))){ + retval << context.getActionBinding("#{sReady_Weapon}"); } - else if((found = Check(temp, "name", &i, &start))){ - retval << context.getNPCName(); + else if((found = check(temp, "actionprevspell", &i, &start))){ + retval << "PLACEHOLDER_ACTION_PREV_SPELL"; } - } - 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))){ + else if((found = check(temp, "actionnextspell", &i, &start))){ + retval << "PLACEHOLDER_ACTION_NEXT_SPELL"; + } + 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, "race", &i, &start))){ + else if((found = check(temp, "pcrace", &i, &start))){ retval << context.getPCRace(); } - else if((found = Check(temp, "name", &i, &start))){ + else if((found = check(temp, "pcname", &i, &start))){ retval << context.getPCName(); } - } - - /* Not a builtin, try global variables */ - if(!found){ - /* if list of globals is empty, grab it and sort it by descending string length */ - if(globals.empty()){ - globals = context.getGlobals(); - sort(globals.begin(), globals.end(), longerStr); + else if((found = check(temp, "cell", &i, &start))){ + retval << context.getCurrentCellName(); } - for(unsigned int j = 0; j < globals.size(); j++){ - if(globals[j].length() > temp.length()){ // Just in case there's a global with a huuuge name - std::string temp = text.substr(i+1, globals[j].length()); - transform(temp.begin(), temp.end(), temp.begin(), ::tolower); + else if(eschar == '%' && !isBook) { // 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(); } - if((found = Check(temp, globals[j], &i, &start))){ - char type = context.getGlobalType(globals[j]); + 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.getNPCName(); + } + } + 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(); + } + } - switch(type){ - case 's': retval << context.getGlobalShort(globals[j]); break; - case 'l': retval << context.getGlobalLong(globals[j]); break; - case 'f': retval << context.getGlobalFloat(globals[j]); break; + /* Not a builtin, try global variables */ + if(!found){ + /* if list of globals is empty, grab it and sort it by descending string length */ + if(globals.empty()){ + globals = context.getGlobals(); + sort(globals.begin(), globals.end(), longerStr); + } + + for(unsigned int j = 0; j < globals.size(); j++){ + if(globals[j].length() > temp.length()){ // Just in case there's a global with a huuuge name + std::string temp = text.substr(i+1, globals[j].length()); + transform(temp.begin(), temp.end(), temp.begin(), ::tolower); + } + + if((found = check(temp, globals[j], &i, &start))){ + char type = context.getGlobalType(globals[j]); + + switch(type){ + case 's': retval << context.getGlobalShort(globals[j]); break; + case 'l': retval << context.getGlobalLong(globals[j]); break; + case 'f': retval << context.getGlobalFloat(globals[j]); break; + } + break; } - break; } } } - - /* Not found */ + catch (std::exception& e) + { + std::cerr << "Failed to replace escape character, with the following error: " << e.what() << std::endl; + std::cerr << "Full text below: " << std::endl << text << std::endl; + } + + // Not found, or error if(!found){ /* leave unmodified */ i += 1;