refactor: Validate arguments in ScriptExecution, not RoutineManager
This commit is contained in:
parent
72bba03898
commit
b6ac854861
4 changed files with 28 additions and 104 deletions
|
@ -36,12 +36,10 @@ namespace reone {
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
Variable RoutineManager::random(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::random(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Int);
|
|
||||||
return reone::random(0, args[0].intValue - 1);
|
return reone::random(0, args[0].intValue - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::intToFloat(const vector<Variable> & args, ExecutionContext & ctx) {
|
Variable RoutineManager::intToFloat(const vector<Variable> & args, ExecutionContext & ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Int);
|
|
||||||
return static_cast<float>(args[0].intValue);
|
return static_cast<float>(args[0].intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,14 +50,11 @@ Variable RoutineManager::getEnteringObject(const vector<Variable> &args, Executi
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getIsPC(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getIsPC(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Object);
|
|
||||||
shared_ptr<Object> player(_game->module()->area()->player());
|
shared_ptr<Object> player(_game->module()->area()->player());
|
||||||
|
|
||||||
return Variable(args[0].objectId == player->id());
|
return Variable(args[0].objectId == player->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getIsObjectValid(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getIsObjectValid(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Object);
|
|
||||||
return Variable(args[0].objectId != kObjectInvalid);
|
return Variable(args[0].objectId != kObjectInvalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,11 +68,6 @@ Variable RoutineManager::getFirstPC(const vector<Variable> &args, ExecutionConte
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getObjectByTag(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getObjectByTag(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
!args.empty() &&
|
|
||||||
args[0].type == VariableType::String &&
|
|
||||||
(args.size() < 2 || args[1].type == VariableType::Int));
|
|
||||||
|
|
||||||
string tag(args[0].strValue);
|
string tag(args[0].strValue);
|
||||||
if (tag.empty()) {
|
if (tag.empty()) {
|
||||||
tag = "party-leader";
|
tag = "party-leader";
|
||||||
|
@ -92,7 +82,6 @@ Variable RoutineManager::getObjectByTag(const vector<Variable> &args, ExecutionC
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getWaypointByTag(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getWaypointByTag(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::String);
|
|
||||||
shared_ptr<Object> object(_game->module()->area()->find(args[0].strValue));
|
shared_ptr<Object> object(_game->module()->area()->find(args[0].strValue));
|
||||||
|
|
||||||
Variable result(VariableType::Object);
|
Variable result(VariableType::Object);
|
||||||
|
@ -102,11 +91,6 @@ Variable RoutineManager::getWaypointByTag(const vector<Variable> &args, Executio
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getLevelByClass(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getLevelByClass(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
!args.empty() &&
|
|
||||||
args[0].type == VariableType::Int &&
|
|
||||||
args[1].type == VariableType::Object);
|
|
||||||
|
|
||||||
ClassType clazz = static_cast<ClassType>(args[0].intValue);
|
ClassType clazz = static_cast<ClassType>(args[0].intValue);
|
||||||
|
|
||||||
int objectId = args.size() < 2 ? kObjectSelf : args[1].objectId;
|
int objectId = args.size() < 2 ? kObjectSelf : args[1].objectId;
|
||||||
|
@ -122,8 +106,6 @@ Variable RoutineManager::getLevelByClass(const vector<Variable> &args, Execution
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getGender(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getGender(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Object);
|
|
||||||
|
|
||||||
int objectId = args[0].objectId;
|
int objectId = args[0].objectId;
|
||||||
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
||||||
Creature &creature = static_cast<Creature &>(*object);
|
Creature &creature = static_cast<Creature &>(*object);
|
||||||
|
@ -132,8 +114,6 @@ Variable RoutineManager::getGender(const vector<Variable> &args, ExecutionContex
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getArea(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getArea(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Object);
|
|
||||||
|
|
||||||
Variable result(VariableType::Object);
|
Variable result(VariableType::Object);
|
||||||
result.objectId = _game->module()->area()->id();
|
result.objectId = _game->module()->area()->id();
|
||||||
|
|
||||||
|
@ -141,8 +121,6 @@ Variable RoutineManager::getArea(const vector<Variable> &args, ExecutionContext
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getItemInSlot(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getItemInSlot(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Int);
|
|
||||||
|
|
||||||
uint32_t objectId(args.size() > 1 ? args[1].objectId : kObjectSelf);
|
uint32_t objectId(args.size() > 1 ? args[1].objectId : kObjectSelf);
|
||||||
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
||||||
shared_ptr<Object> item;
|
shared_ptr<Object> item;
|
||||||
|
@ -158,85 +136,42 @@ Variable RoutineManager::getItemInSlot(const vector<Variable> &args, ExecutionCo
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getGlobalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getGlobalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::String);
|
|
||||||
return _game->getGlobalBoolean(args[0].strValue);
|
return _game->getGlobalBoolean(args[0].strValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getGlobalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getGlobalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::String);
|
|
||||||
return _game->getGlobalNumber(args[0].strValue);
|
return _game->getGlobalNumber(args[0].strValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getLocalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getLocalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 2 &&
|
|
||||||
args[0].type == VariableType::Object &&
|
|
||||||
args[1].type == VariableType::Int);
|
|
||||||
|
|
||||||
return _game->getLocalBoolean(args[0].objectId, args[1].intValue);
|
return _game->getLocalBoolean(args[0].objectId, args[1].intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getLocalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getLocalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 2 &&
|
|
||||||
args[0].type == VariableType::Object &&
|
|
||||||
args[1].type == VariableType::Int);
|
|
||||||
|
|
||||||
return _game->getLocalNumber(args[0].objectId, args[1].intValue);
|
return _game->getLocalNumber(args[0].objectId, args[1].intValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::setGlobalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::setGlobalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 2 &&
|
|
||||||
args[0].type == VariableType::String &&
|
|
||||||
args[1].type == VariableType::Int);
|
|
||||||
|
|
||||||
_game->setGlobalBoolean(args[0].strValue, args[1].intValue);
|
_game->setGlobalBoolean(args[0].strValue, args[1].intValue);
|
||||||
|
|
||||||
return Variable();
|
return Variable();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::setGlobalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::setGlobalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 2 &&
|
|
||||||
args[0].type == VariableType::String &&
|
|
||||||
args[1].type == VariableType::Int);
|
|
||||||
|
|
||||||
_game->setGlobalNumber(args[0].strValue, args[1].intValue);
|
_game->setGlobalNumber(args[0].strValue, args[1].intValue);
|
||||||
|
|
||||||
return Variable();
|
return Variable();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::setLocalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::setLocalBoolean(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 3 &&
|
|
||||||
args[0].type == VariableType::Object &&
|
|
||||||
args[1].type == VariableType::Int && args[1].intValue >= 0 && args[1].intValue <= 63 &&
|
|
||||||
args[2].type == VariableType::Int);
|
|
||||||
|
|
||||||
_game->setLocalBoolean(args[0].objectId, args[1].intValue, args[2].intValue);
|
_game->setLocalBoolean(args[0].objectId, args[1].intValue, args[2].intValue);
|
||||||
|
|
||||||
return Variable();
|
return Variable();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::setLocalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::setLocalNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 3 &&
|
|
||||||
args[0].type == VariableType::Object &&
|
|
||||||
args[1].type == VariableType::Int &&
|
|
||||||
args[2].type == VariableType::Int);
|
|
||||||
|
|
||||||
_game->setLocalNumber(args[0].objectId, args[1].intValue, args[2].intValue);
|
_game->setLocalNumber(args[0].objectId, args[1].intValue, args[2].intValue);
|
||||||
|
|
||||||
return Variable();
|
return Variable();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::delayCommand(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::delayCommand(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 2 &&
|
|
||||||
args[0].type == VariableType::Float &&
|
|
||||||
args[1].type == VariableType::Action);
|
|
||||||
|
|
||||||
uint32_t timestamp = SDL_GetTicks() + static_cast<int>(args[0].floatValue * 1000.0f);
|
uint32_t timestamp = SDL_GetTicks() + static_cast<int>(args[0].floatValue * 1000.0f);
|
||||||
_game->module()->area()->delayCommand(timestamp, args[1].context);
|
_game->module()->area()->delayCommand(timestamp, args[1].context);
|
||||||
|
|
||||||
|
@ -244,11 +179,6 @@ Variable RoutineManager::delayCommand(const vector<Variable> &args, ExecutionCon
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::assignCommand(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::assignCommand(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 2 &&
|
|
||||||
args[0].type == VariableType::Object &&
|
|
||||||
args[1].type == VariableType::Action);
|
|
||||||
|
|
||||||
ExecutionContext newCtx(args[1].context);
|
ExecutionContext newCtx(args[1].context);
|
||||||
newCtx.callerId = args[0].objectId;
|
newCtx.callerId = args[0].objectId;
|
||||||
newCtx.triggererId = kObjectInvalid;
|
newCtx.triggererId = kObjectInvalid;
|
||||||
|
@ -259,8 +189,6 @@ Variable RoutineManager::assignCommand(const vector<Variable> &args, ExecutionCo
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::eventUserDefined(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::eventUserDefined(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Int);
|
|
||||||
|
|
||||||
Variable result(VariableType::Event);
|
Variable result(VariableType::Event);
|
||||||
result.engineTypeId = _game->module()->area()->eventUserDefined(args[0].intValue);
|
result.engineTypeId = _game->module()->area()->eventUserDefined(args[0].intValue);
|
||||||
|
|
||||||
|
@ -268,11 +196,6 @@ Variable RoutineManager::eventUserDefined(const vector<Variable> &args, Executio
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::signalEvent(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::signalEvent(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
args.size() == 2 &&
|
|
||||||
args[0].type == VariableType::Object &&
|
|
||||||
args[1].type == VariableType::Event);
|
|
||||||
|
|
||||||
shared_ptr<Object> subject(getObjectById(args[0].objectId, ctx));
|
shared_ptr<Object> subject(getObjectById(args[0].objectId, ctx));
|
||||||
if (subject) {
|
if (subject) {
|
||||||
if (subject->type() == ObjectType::Area) {
|
if (subject->type() == ObjectType::Area) {
|
||||||
|
@ -288,13 +211,10 @@ Variable RoutineManager::signalEvent(const vector<Variable> &args, ExecutionCont
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::getUserDefinedEventNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::getUserDefinedEventNumber(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(args.empty());
|
|
||||||
return ctx.userDefinedEventNumber;
|
return ctx.userDefinedEventNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::actionDoCommand(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::actionDoCommand(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Action);
|
|
||||||
|
|
||||||
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
||||||
Creature *creature = dynamic_cast<Creature *>(subject.get());
|
Creature *creature = dynamic_cast<Creature *>(subject.get());
|
||||||
if (creature) {
|
if (creature) {
|
||||||
|
@ -306,16 +226,12 @@ Variable RoutineManager::actionDoCommand(const vector<Variable> &args, Execution
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::actionMoveToObject(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::actionMoveToObject(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(
|
|
||||||
!args.empty() && args[0].type == VariableType::Object &&
|
|
||||||
(args.size() < 2 || args[1].type == VariableType::Int) &&
|
|
||||||
(args.size() < 3 || args[2].type == VariableType::Float));
|
|
||||||
|
|
||||||
int objectId = args[0].objectId;
|
int objectId = args[0].objectId;
|
||||||
float distance = args.size() >= 2 ? args[2].floatValue : 1.0f;
|
float distance = args.size() >= 2 ? args[2].floatValue : 1.0f;
|
||||||
|
|
||||||
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
||||||
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
||||||
|
|
||||||
if (subject) {
|
if (subject) {
|
||||||
Creature &creature = static_cast<Creature &>(*subject);
|
Creature &creature = static_cast<Creature &>(*subject);
|
||||||
Creature::Action action(Creature::ActionType::MoveToPoint, object, distance);
|
Creature::Action action(Creature::ActionType::MoveToPoint, object, distance);
|
||||||
|
@ -328,8 +244,6 @@ Variable RoutineManager::actionMoveToObject(const vector<Variable> &args, Execut
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::actionStartConversation(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::actionStartConversation(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Object);
|
|
||||||
|
|
||||||
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
||||||
Creature *creature = dynamic_cast<Creature *>(subject ? subject.get() : nullptr);
|
Creature *creature = dynamic_cast<Creature *>(subject ? subject.get() : nullptr);
|
||||||
|
|
||||||
|
@ -351,8 +265,6 @@ Variable RoutineManager::actionStartConversation(const vector<Variable> &args, E
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::actionPauseConversation(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::actionPauseConversation(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(args.empty());
|
|
||||||
|
|
||||||
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
||||||
Creature *creature = dynamic_cast<Creature *>(subject ? subject.get() : nullptr);
|
Creature *creature = dynamic_cast<Creature *>(subject ? subject.get() : nullptr);
|
||||||
|
|
||||||
|
@ -367,8 +279,6 @@ Variable RoutineManager::actionPauseConversation(const vector<Variable> &args, E
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::actionResumeConversation(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::actionResumeConversation(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(args.empty());
|
|
||||||
|
|
||||||
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
||||||
Creature *creature = dynamic_cast<Creature *>(subject ? subject.get() : nullptr);
|
Creature *creature = dynamic_cast<Creature *>(subject ? subject.get() : nullptr);
|
||||||
|
|
||||||
|
@ -383,11 +293,10 @@ Variable RoutineManager::actionResumeConversation(const vector<Variable> &args,
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::actionOpenDoor(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::actionOpenDoor(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Object);
|
|
||||||
|
|
||||||
int objectId = args[0].objectId;
|
int objectId = args[0].objectId;
|
||||||
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
||||||
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
||||||
|
|
||||||
if (subject) {
|
if (subject) {
|
||||||
Creature *creature = dynamic_cast<Creature *>(subject.get());
|
Creature *creature = dynamic_cast<Creature *>(subject.get());
|
||||||
if (creature) {
|
if (creature) {
|
||||||
|
@ -406,11 +315,10 @@ Variable RoutineManager::actionOpenDoor(const vector<Variable> &args, ExecutionC
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable RoutineManager::actionCloseDoor(const vector<Variable> &args, ExecutionContext &ctx) {
|
Variable RoutineManager::actionCloseDoor(const vector<Variable> &args, ExecutionContext &ctx) {
|
||||||
assert(!args.empty() && args[0].type == VariableType::Object);
|
|
||||||
|
|
||||||
int objectId = args[0].objectId;
|
int objectId = args[0].objectId;
|
||||||
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
shared_ptr<Object> subject(getObjectById(ctx.callerId, ctx));
|
||||||
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
shared_ptr<Object> object(getObjectById(objectId, ctx));
|
||||||
|
|
||||||
if (subject) {
|
if (subject) {
|
||||||
Creature *creature = dynamic_cast<Creature *>(subject.get());
|
Creature *creature = dynamic_cast<Creature *>(subject.get());
|
||||||
if (creature) {
|
if (creature) {
|
||||||
|
|
|
@ -101,6 +101,7 @@ int ScriptExecution::run() {
|
||||||
while (insOff < _program->length()) {
|
while (insOff < _program->length()) {
|
||||||
const Instruction &ins = _program->getInstruction(insOff);
|
const Instruction &ins = _program->getInstruction(insOff);
|
||||||
auto handler = _handlers.find(ins.byteCode);
|
auto handler = _handlers.find(ins.byteCode);
|
||||||
|
|
||||||
if (handler == _handlers.end()) {
|
if (handler == _handlers.end()) {
|
||||||
warn("Script: not implemented: " + describeByteCode(ins.byteCode));
|
warn("Script: not implemented: " + describeByteCode(ins.byteCode));
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -170,8 +171,6 @@ void ScriptExecution::executeReserve(const Instruction &ins) {
|
||||||
|
|
||||||
void ScriptExecution::executeCopyTopSP(const Instruction &ins) {
|
void ScriptExecution::executeCopyTopSP(const Instruction &ins) {
|
||||||
int count = ins.size / 4;
|
int count = ins.size / 4;
|
||||||
assert(count == 1);
|
|
||||||
|
|
||||||
int srcIdx = static_cast<int>(_stack.size()) + ins.stackOffset / 4;
|
int srcIdx = static_cast<int>(_stack.size()) + ins.stackOffset / 4;
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
|
@ -197,16 +196,22 @@ void ScriptExecution::executePushConstant(const Instruction &ins) {
|
||||||
_stack.push_back(ins.strValue);
|
_stack.push_back(ins.strValue);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw logic_error("Invalid instruction type: " + to_string(static_cast<int>(ins.type)));
|
throw invalid_argument("Script: invalid instruction type: " + to_string(static_cast<int>(ins.type)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptExecution::executeCallRoutine(const Instruction &ins) {
|
void ScriptExecution::executeCallRoutine(const Instruction &ins) {
|
||||||
const Routine &routine = _context.routines->get(ins.routine);
|
const Routine &routine = _context.routines->get(ins.routine);
|
||||||
|
|
||||||
|
if (ins.argCount > routine.argumentCount()) {
|
||||||
|
throw runtime_error("Script: too many routine arguments");
|
||||||
|
}
|
||||||
vector<Variable> args;
|
vector<Variable> args;
|
||||||
|
|
||||||
for (int i = 0; i < ins.argCount; ++i) {
|
for (int i = 0; i < ins.argCount; ++i) {
|
||||||
switch (routine.argumentType(i)) {
|
VariableType type = routine.argumentType(i);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
case VariableType::Vector:
|
case VariableType::Vector:
|
||||||
args.push_back(getVectorFromStack());
|
args.push_back(getVectorFromStack());
|
||||||
break;
|
break;
|
||||||
|
@ -217,19 +222,22 @@ void ScriptExecution::executeCallRoutine(const Instruction &ins) {
|
||||||
args.push_back(ctx);
|
args.push_back(ctx);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
args.push_back(_stack.back());
|
Variable var(_stack.back());
|
||||||
|
|
||||||
|
if (var.type != type) {
|
||||||
|
throw runtime_error("Script: invalid argument variable type");
|
||||||
|
}
|
||||||
|
args.push_back(move(var));
|
||||||
_stack.pop_back();
|
_stack.pop_back();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable retValue = routine.invoke(args, _context);
|
Variable retValue = routine.invoke(args, _context);
|
||||||
|
|
||||||
if (getDebugLevel() >= 2) {
|
if (getDebugLevel() >= 2) {
|
||||||
debug(boost::format("Script: %s -> %s") % routine.name() % retValue.toString(), 2);
|
debug(boost::format("Script: %s -> %s") % routine.name() % retValue.toString(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (routine.returnType()) {
|
switch (routine.returnType()) {
|
||||||
case VariableType::Void:
|
case VariableType::Void:
|
||||||
break;
|
break;
|
||||||
|
@ -254,7 +262,10 @@ Variable ScriptExecution::getVectorFromStack() {
|
||||||
|
|
||||||
Variable ScriptExecution::getFloatFromStack() {
|
Variable ScriptExecution::getFloatFromStack() {
|
||||||
Variable var(_stack.back());
|
Variable var(_stack.back());
|
||||||
assert(var.type == VariableType::Float);
|
|
||||||
|
if (var.type != VariableType::Float) {
|
||||||
|
throw runtime_error("Script: invalid variable type for a vector component");
|
||||||
|
}
|
||||||
_stack.pop_back();
|
_stack.pop_back();
|
||||||
|
|
||||||
return move(var);
|
return move(var);
|
||||||
|
|
|
@ -61,6 +61,10 @@ VariableType Routine::returnType() const {
|
||||||
return _returnType;
|
return _returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Routine::argumentCount() const {
|
||||||
|
return static_cast<int>(_argumentTypes.size());
|
||||||
|
}
|
||||||
|
|
||||||
VariableType Routine::argumentType(int index) const {
|
VariableType Routine::argumentType(int index) const {
|
||||||
assert(index >= 0 && index < _argumentTypes.size());
|
assert(index >= 0 && index < _argumentTypes.size());
|
||||||
return _argumentTypes[index];
|
return _argumentTypes[index];
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
|
|
||||||
const std::string &name() const;
|
const std::string &name() const;
|
||||||
VariableType returnType() const;
|
VariableType returnType() const;
|
||||||
|
int argumentCount() const;
|
||||||
VariableType argumentType(int index) const;
|
VariableType argumentType(int index) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue