diff --git a/lib/ERMInterpreter.cpp b/lib/ERMInterpreter.cpp index 63c4404f9..c74349d31 100644 --- a/lib/ERMInterpreter.cpp +++ b/lib/ERMInterpreter.cpp @@ -21,6 +21,8 @@ namespace spirit = boost::spirit; using namespace VERMInterpreter; using namespace boost::assign; +typedef int TUnusedType; + namespace ERMPrinter { //console printer @@ -474,6 +476,8 @@ void ERMInterpreter::executeTrigger( VERMInterpreter::Trigger & trig, int funNum curFunc->getParam(g) = g-1 < funParams.size() ? funParams[g-1] : 0; } } + else + curFunc = getFuncVars(0); //skip the first line LinePointer lp = trig.line; @@ -690,7 +694,7 @@ struct VRPerformer : StandardReceiverVisitor break; } } - void operator()(TNormalBodyOption const& trig) const + void operator()(TNormalBodyOption const& trig) const OVERRIDE { switch(trig.optionCode) { @@ -760,6 +764,32 @@ void VR_SPerformer::operator()(TStringConstant const& cmp) const owner.identifier.setTo(cmp.str); } +struct MAPerformer : StandardReceiverVisitor +{ + MAPerformer(ERMInterpreter * _interpr) : StandardReceiverVisitor(_interpr, 0) + {} + using StandardReceiverVisitor::operator(); + + void operator()(TNormalBodyOption const& trig) const OVERRIDE + { + switch(trig.optionCode) + { + case 'A': //sgc monster attack + break; + case 'B': //spell? + break; + case 'P': //hit points + { + //TODO + } + break; + default: + break; + } + } + +}; + struct ConditionDisemboweler; struct OBPerformer; @@ -858,6 +888,52 @@ struct ERMExpDispatch : boost::static_visitor<> ERMExpDispatch(ERMInterpreter * _owner) : owner(_owner) {} + struct HLP + { + ERMInterpreter * ei; + HLP(ERMInterpreter * interp) : ei(interp) + {} + + int3 getPosFromIdentifier(ERM::Tidentifier tid, bool allowDummyFourth) + { + switch(tid.size()) + { + case 1: + { + int num = ei->getIexp(tid[0]).getInt(); + return int3(ei->ermGlobalEnv->getStandardVar(num), + ei->ermGlobalEnv->getStandardVar(num+1), + ei->ermGlobalEnv->getStandardVar(num+2)); + } + break; + case 3: + case 4: + if(tid.size() == 4 && !allowDummyFourth) + throw EScriptExecError("4 items in identifier are not allowed for this receiver!"); + + return int3(ei->getIexp(tid[0]).getInt(), + ei->getIexp(tid[1]).getInt(), + ei->getIexp(tid[2]).getInt()); + break; + default: + throw EScriptExecError("This receiver takes 1 or 3 items in identifier!"); + break; + } + } + template + void performBody(const boost::optional & body, const Visitor& visitor) + { + if(body.is_initialized()) + { + ERM::Tbody bo = body.get(); + for(int g=0; g } void operator()(Treceiver const& trig) const { - struct HLP - { - ERMInterpreter * ei; - HLP(ERMInterpreter * interp) : ei(interp) - {} - - int3 getPosFromIdentifier(ERM::Tidentifier tid, bool allowDummyFourth) - { - switch(tid.size()) - { - case 1: - { - int num = ei->getIexp(tid[0]).getInt(); - return int3(ei->ermGlobalEnv->getStandardVar(num), - ei->ermGlobalEnv->getStandardVar(num+1), - ei->ermGlobalEnv->getStandardVar(num+2)); - } - break; - case 3: - case 4: - if(tid.size() == 4 && !allowDummyFourth) - throw EScriptExecError("4 items in identifirer are not allowed for this receiver!"); - - return int3(ei->getIexp(tid[0]).getInt(), - ei->getIexp(tid[1]).getInt(), - ei->getIexp(tid[2]).getInt()); - break; - default: - throw EScriptExecError("This receiver takes 1 or 3 items in identifier!"); - break; - } - } - }; + HLP helper(owner); if(trig.name == "VR") { //check condition @@ -918,14 +962,7 @@ struct ERMExpDispatch : boost::static_visitor<> IexpValStr ievs = owner->getIexp(ident[0]); //see body - if(trig.body.is_initialized()) - { - ERM::Tbody bo = trig.body.get(); - for(int g=0; g } } } + else if(trig.name == "MA") + { + if(trig.identifier.is_initialized()) + { + throw EScriptExecError("MA receiver doesn't take the identifier!"); + } + helper.performBody(trig.body, MAPerformer(owner)); + } else if(trig.name == "MO") { int3 objPos; @@ -981,17 +1026,7 @@ struct ERMExpDispatch : boost::static_visitor<> ERM::Tidentifier tid = trig.identifier.get(); objPos = HLP(owner).getPosFromIdentifier(tid, false); - //execute body - if(trig.body.is_initialized()) - { - ERM::Tbody bo = trig.body.get(); - for(int g=0; g(tcm.cmd); } + else if(tcm.cmd.which() == 3) + { + return boost::get(tcm.cmd); + } throw ELineProblem("Given line is not a trigger!"); } throw ELineProblem("Given line is not a command!"); @@ -1534,6 +1573,54 @@ void ERMInterpreter::setCurrentlyVisitedObj( int3 pos ) ermGlobalEnv->getStandardVar(1000) = pos.z; } +struct StringProcessHLP +{ + int extractNumber(const std::string & token) + { + return atoi(token.substr(1).c_str()); + } + template + void replaceToken(std::string ret, int tokenBegin, int tokenEnd, T val) + { + ret.replace(tokenBegin, tokenEnd, boost::lexical_cast(val)); + } +}; + +std::string ERMInterpreter::processERMString( std::string ermstring ) +{ + StringProcessHLP hlp; + std::string ret = ermstring; + int curPos = 0; + while((curPos = ret.find('%', curPos)) != std::string::npos) + { + curPos++; + int tokenEnd = ret.find(' ', curPos); + std::string token = ret.substr(curPos, tokenEnd - curPos); + if(token.size() == 0) + { + throw EScriptExecError("Empty token not allowed!"); + } + + switch(token[0]) + { + case '%': + ret.erase(curPos); + break; + case 'F': + hlp.replaceToken(ret, curPos, tokenEnd, ermGlobalEnv->getFlag(hlp.extractNumber(token))); + break; + case 'V': + hlp.replaceToken(ret, curPos, tokenEnd, ermGlobalEnv->getStandardVar(hlp.extractNumber(token))); + break; + default: + throw EScriptExecError("Unrecognized token in string"); + break; + } + + } + return ret; +} + const std::string ERMInterpreter::triggerSymbol = "trigger"; const std::string ERMInterpreter::postTriggerSymbol = "postTrigger"; const std::string ERMInterpreter::defunSymbol = "defun"; @@ -1573,7 +1660,7 @@ bool TriggerIdentifierMatch::tryMatch( Trigger * interptrig ) const { bool ret = true; - const ERM::Ttrigger & trig = ERMInterpreter::retrieveTrigger(ermEnv->retrieveLine(interptrig->line)); + const ERM::TTriggerBase & trig = ERMInterpreter::retrieveTrigger(ermEnv->retrieveLine(interptrig->line)); if(trig.identifier.is_initialized()) { diff --git a/lib/ERMInterpreter.h b/lib/ERMInterpreter.h index 44eb7ed3a..a261d55b5 100644 --- a/lib/ERMInterpreter.h +++ b/lib/ERMInterpreter.h @@ -486,7 +486,7 @@ class ERMInterpreter std::map scripts; std::map lexicalEnvs; ERM::TLine retrieveLine(VERMInterpreter::LinePointer linePtr) const; - static ERM::Ttrigger retrieveTrigger(ERM::TLine line); + static ERM::TTriggerBase & retrieveTrigger(ERM::TLine line); VERMInterpreter::Environment * globalEnv; VERMInterpreter::ERMEnvironment * ermGlobalEnv; @@ -512,6 +512,7 @@ class ERMInterpreter static ERM::EVOtions getExpType(const ERM::TVOption & opt); IexpValStr getVar(std::string toFollow, boost::optional initVal) const; + std::string processERMString(std::string ermstring); public: typedef std::map< int, std::vector > TIDPattern;