Add error handling for getPcRank and similar defines (Fixes #2071)

loadfix
scrawl 10 years ago
parent f57ddec6a2
commit f7ba1dbfc8

@ -311,6 +311,9 @@ namespace MWScript
std::string InterpreterContext::getNPCRank() const 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<std::string, int>& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks(); const std::map<std::string, int>& ranks = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks();
std::map<std::string, int>::const_iterator it = ranks.begin(); std::map<std::string, int>::const_iterator it = ranks.begin();
@ -347,6 +350,9 @@ namespace MWScript
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr(); 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; std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks(); const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();
@ -374,6 +380,9 @@ namespace MWScript
MWBase::World *world = MWBase::Environment::get().getWorld(); MWBase::World *world = MWBase::Environment::get().getWorld();
MWWorld::Ptr player = world->getPlayerPtr(); 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; std::string factionId = getReferenceImp().getClass().getNpcStats (getReferenceImp()).getFactionRanks().begin()->first;
const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks(); const std::map<std::string, int>& ranks = player.getClass().getNpcStats (player).getFactionRanks();

@ -4,10 +4,12 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <iostream>
namespace Interpreter{ 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; bool retval = str.find(escword) == 0;
if(retval){ if(retval){
(*i) += escword.length(); (*i) += escword.length();
@ -18,170 +20,181 @@ namespace Interpreter{
std::vector<std::string> globals; std::vector<std::string> 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(); 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; unsigned int start = 0;
std::ostringstream retval; std::ostringstream retval;
for(unsigned int i = 0; i < text.length(); i++){ for(unsigned int i = 0; i < text.length(); i++)
if(text[i] == eschar){ {
if(text[i] == eschar)
{
retval << text.substr(start, i - start); retval << text.substr(start, i - start);
std::string temp = text.substr(i+1, 100); std::string temp = text.substr(i+1, 100);
transform(temp.begin(), temp.end(), temp.begin(), ::tolower); transform(temp.begin(), temp.end(), temp.begin(), ::tolower);
bool found; bool found = false;
try
if( (found = Check(temp, "actionslideright", &i, &start))){ {
retval << context.getActionBinding("#{sRight}"); 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();
} }
else if((found = Check(temp, "nextpcrank", &i, &start))){ else if((found = check(temp, "actionreadymagic", &i, &start))){
retval << context.getPCNextRank(); retval << context.getActionBinding("#{sReady_Magic}");
} }
else if((found = Check(temp, "pcnextrank", &i, &start))){ else if((found = check(temp, "actionprevweapon", &i, &start))){
retval << context.getPCNextRank(); retval << "PLACEHOLDER_ACTION_PREV_WEAPON";
} }
else if((found = Check(temp, "pcrank", &i, &start))){ else if((found = check(temp, "actionnextweapon", &i, &start))){
retval << context.getPCRank(); retval << "PLACEHOLDER_ACTION_PREV_WEAPON";
} }
else if((found = Check(temp, "rank", &i, &start))){ else if((found = check(temp, "actiontogglerun", &i, &start))){
retval << context.getNPCRank(); retval << context.getActionBinding("#{sAuto_Run}");
} }
else if((found = check(temp, "actionslideleft", &i, &start))){
else if((found = Check(temp, "class", &i, &start))){ retval << context.getActionBinding("#{sLeft}");
retval << context.getNPCClass();
} }
else if((found = Check(temp, "race", &i, &start))){ else if((found = check(temp, "actionreadyitem", &i, &start))){
retval << context.getNPCRace(); retval << context.getActionBinding("#{sReady_Weapon}");
} }
else if((found = Check(temp, "name", &i, &start))){ else if((found = check(temp, "actionprevspell", &i, &start))){
retval << context.getNPCName(); retval << "PLACEHOLDER_ACTION_PREV_SPELL";
} }
} else if((found = check(temp, "actionnextspell", &i, &start))){
else { // In messagebox or book, not dialogue retval << "PLACEHOLDER_ACTION_NEXT_SPELL";
}
/* empty outside dialogue */ else if((found = check(temp, "actionrestmenu", &i, &start))){
if( (found = Check(temp, "faction", &i, &start))); retval << context.getActionBinding("#{sRestKey}");
else if((found = Check(temp, "nextpcrank", &i, &start))); }
else if((found = Check(temp, "pcnextrank", &i, &start))); else if((found = check(temp, "actionmenumode", &i, &start))){
else if((found = Check(temp, "pcrank", &i, &start))); retval << context.getActionBinding("#{sInventory}");
else if((found = Check(temp, "rank", &i, &start))); }
else if((found = check(temp, "actionactivate", &i, &start))){
/* uses pc in messageboxes */ retval << context.getActionBinding("#{sActivate}");
else if((found = Check(temp, "class", &i, &start))){ }
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(); retval << context.getPCClass();
} }
else if((found = Check(temp, "race", &i, &start))){ else if((found = check(temp, "pcrace", &i, &start))){
retval << context.getPCRace(); retval << context.getPCRace();
} }
else if((found = Check(temp, "name", &i, &start))){ else if((found = check(temp, "pcname", &i, &start))){
retval << context.getPCName(); retval << context.getPCName();
} }
} else if((found = check(temp, "cell", &i, &start))){
retval << context.getCurrentCellName();
/* 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++){ else if(eschar == '%' && !isBook) { // In Dialogue, not messagebox
if(globals[j].length() > temp.length()){ // Just in case there's a global with a huuuge name if( (found = check(temp, "faction", &i, &start))){
std::string temp = text.substr(i+1, globals[j].length()); retval << context.getNPCFaction();
transform(temp.begin(), temp.end(), temp.begin(), ::tolower); }
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))){ else if((found = check(temp, "class", &i, &start))){
char type = context.getGlobalType(globals[j]); 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){ /* Not a builtin, try global variables */
case 's': retval << context.getGlobalShort(globals[j]); break; if(!found){
case 'l': retval << context.getGlobalLong(globals[j]); break; /* if list of globals is empty, grab it and sort it by descending string length */
case 'f': retval << context.getGlobalFloat(globals[j]); break; 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;
} }
} }
} }
catch (std::exception& e)
/* Not found */ {
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){ if(!found){
/* leave unmodified */ /* leave unmodified */
i += 1; i += 1;

Loading…
Cancel
Save