mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-15 20:03:15 +02:00
* partially done OB receiver
* minor structure imprevements
This commit is contained in:
@@ -569,31 +569,86 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
|
|||||||
//code execution
|
//code execution
|
||||||
|
|
||||||
struct VRPerformer;
|
struct VRPerformer;
|
||||||
struct VR_SPerformer : boost::static_visitor<>
|
|
||||||
{
|
|
||||||
VRPerformer & owner;
|
|
||||||
explicit VR_SPerformer(VRPerformer & _owner);
|
|
||||||
|
|
||||||
void operator()(TVarConcatString const& cmp) const;
|
template<typename OwnerType>
|
||||||
void operator()(TStringConstant const& cmp) const;
|
struct StandardBodyOptionItemVisitor : boost::static_visitor<>
|
||||||
void operator()(TCurriedString const& cmp) const;
|
{
|
||||||
void operator()(TSemiCompare const& cmp) const;
|
OwnerType & owner;
|
||||||
void operator()(TMacroUsage const& cmp) const;
|
explicit StandardBodyOptionItemVisitor(OwnerType & _owner) : owner(_owner)
|
||||||
void operator()(TMacroDef const& cmp) const;
|
{}
|
||||||
void operator()(TIexp const& cmp) const;
|
virtual void operator()(TVarConcatString const& cmp) const
|
||||||
void operator()(TVarpExp const& cmp) const;
|
{
|
||||||
void operator()(spirit::unused_type const& cmp) const;
|
throw EScriptExecError("String concatenation not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(TStringConstant const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("String constant not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(TCurriedString const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("Curried string not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(TSemiCompare const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("Semi comparison not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(TMacroUsage const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("Macro usage not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(TMacroDef const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("Macro definition not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(TIexp const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("i-expression not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(TVarpExp const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("Varp expression not allowed in this receiver");
|
||||||
|
}
|
||||||
|
virtual void operator()(spirit::unused_type const& cmp) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("\'Nothing\' not allowed in this receiver");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
struct VRPerformer : boost::static_visitor<>
|
struct StandardReceiverVisitor : boost::static_visitor<>
|
||||||
{
|
{
|
||||||
ERMInterpreter * interp;
|
ERMInterpreter * interp;
|
||||||
IexpValStr identifier;
|
T identifier;
|
||||||
VRPerformer(ERMInterpreter * _interpr, IexpValStr ident) : interp(_interpr), identifier(ident)
|
StandardReceiverVisitor(ERMInterpreter * _interpr, T ident) : interp(_interpr), identifier(ident)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(TVRLogic const& trig) const
|
virtual void operator()(TVRLogic const& trig) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("VR logic not allowed in this receiver!");
|
||||||
|
}
|
||||||
|
virtual void operator()(TVRArithmetic const& trig) const
|
||||||
|
{
|
||||||
|
throw EScriptExecError("VR arithmetic not allowed in this receiver!");
|
||||||
|
}
|
||||||
|
virtual void operator()(TNormalBodyOption const& trig) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VR_SPerformer : StandardBodyOptionItemVisitor<VRPerformer>
|
||||||
|
{
|
||||||
|
explicit VR_SPerformer(VRPerformer & _owner);
|
||||||
|
using StandardBodyOptionItemVisitor<VRPerformer>::operator();
|
||||||
|
|
||||||
|
void operator()(TStringConstant const& cmp) const OVERRIDE;
|
||||||
|
void operator()(TMacroUsage const& cmp) const OVERRIDE;
|
||||||
|
void operator()(TIexp const& cmp) const OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VRPerformer : StandardReceiverVisitor<IexpValStr>
|
||||||
|
{
|
||||||
|
VRPerformer(ERMInterpreter * _interpr, IexpValStr ident) : StandardReceiverVisitor(_interpr, ident)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator()(TVRLogic const& trig) const OVERRIDE
|
||||||
{
|
{
|
||||||
int valr = interp->getIexp(trig.var).getInt();
|
int valr = interp->getIexp(trig.var).getInt();
|
||||||
switch (trig.opcode)
|
switch (trig.opcode)
|
||||||
@@ -612,7 +667,7 @@ struct VRPerformer : boost::static_visitor<>
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void operator()(TVRArithmetic const& trig) const
|
void operator()(TVRArithmetic const& trig) const OVERRIDE
|
||||||
{
|
{
|
||||||
IexpValStr rhs = interp->getIexp(trig.rhs);
|
IexpValStr rhs = interp->getIexp(trig.rhs);
|
||||||
switch (trig.opcode)
|
switch (trig.opcode)
|
||||||
@@ -641,6 +696,26 @@ struct VRPerformer : boost::static_visitor<>
|
|||||||
{
|
{
|
||||||
switch(trig.optionCode)
|
switch(trig.optionCode)
|
||||||
{
|
{
|
||||||
|
case 'C': //setting/checking v vars
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'H': //checking if string is empty
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'M': //string operations
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'R': //random variables
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'S': //setting variable
|
case 'S': //setting variable
|
||||||
{
|
{
|
||||||
if(trig.params.size() == 1)
|
if(trig.params.size() == 1)
|
||||||
@@ -652,57 +727,113 @@ struct VRPerformer : boost::static_visitor<>
|
|||||||
throw EScriptExecError("VR receiver S option takes exactly 1 parameter!");
|
throw EScriptExecError("VR receiver S option takes exactly 1 parameter!");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'T': //random variables
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'U': //search for a substring
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'V': //convert string to value
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
//not supported or not allowed
|
throw EScriptExecError("Wrong VR receiver option!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
VR_SPerformer::VR_SPerformer(VRPerformer & _owner) : owner(_owner)
|
VR_SPerformer::VR_SPerformer(VRPerformer & _owner) : StandardBodyOptionItemVisitor(_owner)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void VR_SPerformer::operator()(ERM::TIexp const& trig) const
|
void VR_SPerformer::operator()(ERM::TIexp const& trig) const
|
||||||
{
|
{
|
||||||
owner.identifier.setTo(owner.interp->getIexp(trig));
|
owner.identifier.setTo(owner.interp->getIexp(trig));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VR_SPerformer::operator()(TVarConcatString const& cmp) const
|
|
||||||
{
|
|
||||||
throw EScriptExecError("String concatenation not allowed in VR S");
|
|
||||||
}
|
|
||||||
void VR_SPerformer::operator()(TStringConstant const& cmp) const
|
void VR_SPerformer::operator()(TStringConstant const& cmp) const
|
||||||
{
|
{
|
||||||
owner.identifier.setTo(cmp.str);
|
owner.identifier.setTo(cmp.str);
|
||||||
}
|
}
|
||||||
void VR_SPerformer::operator()(TCurriedString const& cmp) const
|
|
||||||
{
|
|
||||||
throw EScriptExecError("Curried string not allowed in VR S");
|
|
||||||
}
|
|
||||||
void VR_SPerformer::operator()(TSemiCompare const& cmp) const
|
|
||||||
{
|
|
||||||
throw EScriptExecError("Incomplete comparison not allowed in VR S");
|
|
||||||
}
|
|
||||||
void VR_SPerformer::operator()(TMacroUsage const& cmp) const
|
void VR_SPerformer::operator()(TMacroUsage const& cmp) const
|
||||||
{
|
{
|
||||||
owner.identifier.setTo(owner.interp->getIexp(cmp));
|
owner.identifier.setTo(owner.interp->getIexp(cmp));
|
||||||
}
|
}
|
||||||
void VR_SPerformer::operator()(TMacroDef const& cmp) const
|
|
||||||
{
|
|
||||||
throw EScriptExecError("Macro definition not allowed in VR S");
|
|
||||||
}
|
|
||||||
void VR_SPerformer::operator()(TVarpExp const& cmp) const
|
|
||||||
{
|
|
||||||
throw EScriptExecError("Write-only variable expression not allowed in VR S");
|
|
||||||
}
|
|
||||||
void VR_SPerformer::operator()(spirit::unused_type const& cmp) const
|
|
||||||
{
|
|
||||||
throw EScriptExecError("Expression not allowed in VR S");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ConditionDisemboweler;
|
struct ConditionDisemboweler;
|
||||||
|
|
||||||
|
struct OBPerformer : StandardReceiverVisitor<int3>
|
||||||
|
{
|
||||||
|
OBPerformer(ERMInterpreter * _interpr, int3 objPos) : StandardReceiverVisitor(_interpr, objPos)
|
||||||
|
{}
|
||||||
|
using StandardReceiverVisitor<int3>::operator(); //it removes compilation error... not sure why it *must* be here
|
||||||
|
void operator()(TNormalBodyOption const& trig) const
|
||||||
|
{
|
||||||
|
switch(trig.optionCode)
|
||||||
|
{
|
||||||
|
case 'B': //removes description hint
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'C': //sgc of control word of object
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'D': //disable gamer to use object
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'E': //enable gamer to use object
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'H': //replace hint for object
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'M': //disabling messages and questions
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'R': //eable all gamers to use object
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'S': //disable all gamers to use object
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'T': //sgc of obj type
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'U': //sgc of obj subtype
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw EScriptExecError("Wrong OB receiver option!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ERMExpDispatch : boost::static_visitor<>
|
struct ERMExpDispatch : boost::static_visitor<>
|
||||||
{
|
{
|
||||||
@@ -781,6 +912,46 @@ struct ERMExpDispatch : boost::static_visitor<>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(trig.name == "OB")
|
||||||
|
{
|
||||||
|
int3 objPos;
|
||||||
|
if(trig.identifier.is_initialized())
|
||||||
|
{
|
||||||
|
ERM::Tidentifier tid = trig.identifier.get();
|
||||||
|
switch(tid.size())
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
int num = owner->getIexp(tid[0]).getInt();
|
||||||
|
objPos = int3(owner->ermGlobalEnv->getStandardVar(num),
|
||||||
|
owner->ermGlobalEnv->getStandardVar(num+1),
|
||||||
|
owner->ermGlobalEnv->getStandardVar(num+2));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
objPos = int3(owner->getIexp(tid[0]).getInt(),
|
||||||
|
owner->getIexp(tid[1]).getInt(),
|
||||||
|
owner->getIexp(tid[2]).getInt());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw EScriptExecError("OB receiver takes 1 or 3 items in identifier!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//execute body
|
||||||
|
if(trig.body.is_initialized())
|
||||||
|
{
|
||||||
|
ERM::Tbody bo = trig.body.get();
|
||||||
|
for(int g=0; g<bo.size(); ++g)
|
||||||
|
{
|
||||||
|
boost::apply_visitor(OBPerformer(owner, objPos), bo[g]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw EScriptExecError("OB receiver must have body!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw EScriptExecError("OB receiver must have an identifier!");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//unsupported or invalid trigger
|
//unsupported or invalid trigger
|
||||||
@@ -1307,6 +1478,13 @@ int ERMInterpreter::getRealLine(int lineNum)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ERMInterpreter::setCurrentlyVisitedObj( int3 pos )
|
||||||
|
{
|
||||||
|
ermGlobalEnv->getStandardVar(998) = pos.x;
|
||||||
|
ermGlobalEnv->getStandardVar(999) = pos.y;
|
||||||
|
ermGlobalEnv->getStandardVar(1000) = pos.z;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string ERMInterpreter::triggerSymbol = "trigger";
|
const std::string ERMInterpreter::triggerSymbol = "trigger";
|
||||||
const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
|
const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
|
||||||
const std::string ERMInterpreter::defunSymbol = "defun";
|
const std::string ERMInterpreter::defunSymbol = "defun";
|
||||||
|
@@ -160,7 +160,7 @@ namespace VERMInterpreter
|
|||||||
{
|
{
|
||||||
ERMEnvironment();
|
ERMEnvironment();
|
||||||
static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
|
static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
|
||||||
int & getQuickVar(const char letter);
|
int & getQuickVar(const char letter); //'f' - 't' variables
|
||||||
int & getStandardVar(int num); //get v-variable
|
int & getStandardVar(int num); //get v-variable
|
||||||
std::string & getZVar(int num);
|
std::string & getZVar(int num);
|
||||||
bool & getFlag(int num);
|
bool & getFlag(int num);
|
||||||
@@ -515,6 +515,7 @@ public:
|
|||||||
void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams=std::vector<int>()); //use this to run triggers
|
void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams=std::vector<int>()); //use this to run triggers
|
||||||
void executeTriggerType(const char *trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
|
void executeTriggerType(const char *trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
|
||||||
void executeTriggerType(const char *trigger); //convenience version of above, for pre-trigger when there are no args
|
void executeTriggerType(const char *trigger); //convenience version of above, for pre-trigger when there are no args
|
||||||
|
void setCurrentlyVisitedObj(int3 pos); //sets v998 - v1000 to given value
|
||||||
void init(); //sets up environment etc.
|
void init(); //sets up environment etc.
|
||||||
void scanForScripts();
|
void scanForScripts();
|
||||||
|
|
||||||
|
@@ -35,7 +35,7 @@ void CERMScriptModule::heroVisit(const CGHeroInstance *visitor, const CGObjectIn
|
|||||||
{
|
{
|
||||||
if(!visitedObj)
|
if(!visitedObj)
|
||||||
return;
|
return;
|
||||||
|
interpreter->setCurrentlyVisitedObj(visitedObj->pos);
|
||||||
ERMInterpreter::TIDPattern tip;
|
ERMInterpreter::TIDPattern tip;
|
||||||
tip[1] = list_of(visitedObj->ID);
|
tip[1] = list_of(visitedObj->ID);
|
||||||
tip[2] = list_of(visitedObj->ID)(visitedObj->subID);
|
tip[2] = list_of(visitedObj->ID)(visitedObj->subID);
|
||||||
|
Reference in New Issue
Block a user