2016-11-01 03:53:07 +07:00
|
|
|
/*
|
|
|
|
|
* sfall
|
2016-11-14 02:07:08 +07:00
|
|
|
* Copyright (C) 2008-2016 The sfall team
|
2016-11-01 03:53:07 +07:00
|
|
|
*
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2016-11-14 02:07:08 +07:00
|
|
|
#include "..\..\..\FalloutEngine\Fallout2.h"
|
|
|
|
|
#include "..\..\ScriptExtender.h"
|
|
|
|
|
#include "..\Arrays.h"
|
2016-11-14 21:57:44 +07:00
|
|
|
#include "..\OpcodeContext.h"
|
2017-02-23 23:45:15 +07:00
|
|
|
#include "..\OpcodeInfo.h"
|
2016-11-14 02:07:08 +07:00
|
|
|
#include "AsmMacros.h"
|
|
|
|
|
#include "Interface.h"
|
|
|
|
|
#include "Misc.h"
|
|
|
|
|
#include "Objects.h"
|
2016-11-01 03:53:07 +07:00
|
|
|
|
2016-11-14 02:07:08 +07:00
|
|
|
#include "Metarule.h"
|
2016-11-01 03:53:07 +07:00
|
|
|
|
2016-11-02 04:10:50 +07:00
|
|
|
// Metarule is a universal opcode(s) for all kinds of new sfall scripting functions.
|
|
|
|
|
// Prefix all function handlers with sf_ and add them to sfall_metarule_table.
|
|
|
|
|
// DO NOT add arguments and/or return values to function handlers!
|
2016-11-14 21:57:44 +07:00
|
|
|
// Use ctx.arg(i), inside handler function to access arguments.
|
|
|
|
|
// Use ctx.setReturn(x) to set return value.
|
2016-11-02 04:10:50 +07:00
|
|
|
// If you want to call user-defined procedures in your handler, use RunScriptProc().
|
2016-11-01 03:53:07 +07:00
|
|
|
|
2016-11-04 03:37:30 +07:00
|
|
|
struct SfallMetarule {
|
|
|
|
|
// function name
|
|
|
|
|
const char* name;
|
2017-02-23 23:45:15 +07:00
|
|
|
|
2016-11-04 03:37:30 +07:00
|
|
|
// pointer to handler function
|
2016-11-14 21:50:27 +07:00
|
|
|
ScriptingFunctionHandler func;
|
2017-02-23 23:45:15 +07:00
|
|
|
|
|
|
|
|
// minimum number of arguments
|
2016-11-04 03:37:30 +07:00
|
|
|
int minArgs;
|
2017-02-23 23:45:15 +07:00
|
|
|
|
2016-11-04 03:37:30 +07:00
|
|
|
// maximum number of arguments
|
|
|
|
|
int maxArgs;
|
2017-02-23 23:45:15 +07:00
|
|
|
|
|
|
|
|
// argument validation settings
|
|
|
|
|
OpcodeArgumentInfo argValidation[OP_MAX_ARGUMENTS];
|
2016-11-04 03:37:30 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef std::tr1::unordered_map<std::string, const SfallMetarule*> MetaruleTableType;
|
2016-11-02 04:10:50 +07:00
|
|
|
|
|
|
|
|
static MetaruleTableType metaruleTable;
|
|
|
|
|
|
2016-11-06 16:52:09 +07:00
|
|
|
// currently executed metarule
|
|
|
|
|
static const SfallMetarule* currentMetarule;
|
|
|
|
|
|
2016-11-02 04:10:50 +07:00
|
|
|
static std::string sf_test_stringBuf;
|
|
|
|
|
|
2016-11-14 21:57:44 +07:00
|
|
|
void sf_test(OpcodeContext& ctx) {
|
2016-11-02 04:10:50 +07:00
|
|
|
std::ostringstream sstream;
|
2016-11-03 20:55:59 +07:00
|
|
|
sstream << "sfall_funcX(\"test\"";
|
2016-11-14 21:57:44 +07:00
|
|
|
for (int i = 0; i < ctx.numArgs(); i++) {
|
|
|
|
|
const ScriptValue &arg = ctx.arg(i);
|
2016-11-02 04:10:50 +07:00
|
|
|
sstream << ", ";
|
2016-11-05 03:34:09 +07:00
|
|
|
switch (arg.type()) {
|
2016-11-02 04:10:50 +07:00
|
|
|
case DATATYPE_INT:
|
2016-11-05 03:34:09 +07:00
|
|
|
sstream << arg.asInt();
|
2016-11-02 04:10:50 +07:00
|
|
|
break;
|
|
|
|
|
case DATATYPE_FLOAT:
|
2016-11-05 03:34:09 +07:00
|
|
|
sstream << arg.asFloat();
|
2016-11-02 04:10:50 +07:00
|
|
|
break;
|
|
|
|
|
case DATATYPE_STR:
|
2016-11-05 03:34:09 +07:00
|
|
|
sstream << '"' << arg.asString() << '"';
|
2016-11-02 04:10:50 +07:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
sstream << "???";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-03 20:55:59 +07:00
|
|
|
sstream << ")";
|
2016-11-02 04:10:50 +07:00
|
|
|
|
|
|
|
|
sf_test_stringBuf = sstream.str();
|
2016-11-14 21:57:44 +07:00
|
|
|
ctx.setReturn(sf_test_stringBuf.c_str());
|
2016-11-02 04:10:50 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// returns current contents of metarule table
|
2016-11-14 21:57:44 +07:00
|
|
|
void sf_get_metarule_table(OpcodeContext& ctx) {
|
2016-11-02 04:10:50 +07:00
|
|
|
DWORD arr = TempArray(metaruleTable.size(), 0);
|
|
|
|
|
int i = 0;
|
2017-02-23 19:07:22 +07:00
|
|
|
for (auto it = metaruleTable.begin(); it != metaruleTable.end(); it++) {
|
2016-11-03 20:55:59 +07:00
|
|
|
arrays[arr].val[i].set(it->first.c_str());
|
2016-11-02 04:10:50 +07:00
|
|
|
i++;
|
|
|
|
|
}
|
2016-11-14 21:50:27 +07:00
|
|
|
ctx.setReturn(arr, DATATYPE_INT);
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
|
|
|
|
|
2016-11-04 17:22:05 +07:00
|
|
|
/*
|
|
|
|
|
Metarule array.
|
|
|
|
|
|
|
|
|
|
Add your custom scripting functions here.
|
|
|
|
|
|
|
|
|
|
Format is as follows:
|
2016-11-06 17:37:25 +07:00
|
|
|
{ name, handler, minArgs, maxArgs }
|
2016-11-04 17:22:05 +07:00
|
|
|
- name - name of function that will be used to call it from scripts,
|
2016-11-06 17:37:25 +07:00
|
|
|
- handler - pointer to handler function (see examples below),
|
|
|
|
|
- minArgs/maxArgs - minimum and maximum number of arguments allowed for this function
|
2017-02-23 23:45:15 +07:00
|
|
|
- argument types for validation
|
2016-11-04 17:22:05 +07:00
|
|
|
*/
|
2016-11-04 03:37:30 +07:00
|
|
|
static const SfallMetarule metaruleArray[] = {
|
2016-11-06 17:37:25 +07:00
|
|
|
{"get_metarule_table", sf_get_metarule_table, 0, 0},
|
2017-02-23 23:45:15 +07:00
|
|
|
{"validate_test", sf_test, 2, 5, {ARG_INT, ARG_FLOAT, ARG_STRING, ARG_ANY}},
|
|
|
|
|
{"spatial_radius", sf_spatial_radius, 1, 1, {ARG_OBJECT}},
|
|
|
|
|
{"critter_inven_obj2", sf_critter_inven_obj2, 2, 2, {ARG_OBJECT, ARG_INT}},
|
2016-11-06 17:37:25 +07:00
|
|
|
{"intface_redraw", sf_intface_redraw, 0, 0},
|
|
|
|
|
{"intface_show", sf_intface_show, 0, 0},
|
|
|
|
|
{"intface_hide", sf_intface_hide, 0, 0},
|
|
|
|
|
{"intface_is_hidden", sf_intface_is_hidden, 0, 0},
|
|
|
|
|
{"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0},
|
2016-11-04 03:37:30 +07:00
|
|
|
};
|
|
|
|
|
|
2016-11-14 02:07:08 +07:00
|
|
|
void InitMetaruleTable() {
|
2016-11-04 03:37:30 +07:00
|
|
|
int length = sizeof(metaruleArray) / sizeof(SfallMetarule);
|
|
|
|
|
for (int i = 0; i < length; ++i) {
|
|
|
|
|
metaruleTable[metaruleArray[i].name] = &metaruleArray[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validates arguments against metarule specification.
|
|
|
|
|
// On error prints to debug.log and returns false.
|
2016-11-14 21:57:44 +07:00
|
|
|
static bool ValidateMetaruleArguments(OpcodeContext& ctx, const SfallMetarule* metaruleInfo) {
|
|
|
|
|
int argCount = ctx.numArgs();
|
2016-11-04 03:37:30 +07:00
|
|
|
if (argCount < metaruleInfo->minArgs || argCount > metaruleInfo->maxArgs) {
|
2016-11-14 21:57:44 +07:00
|
|
|
ctx.printOpcodeError(
|
2016-11-04 03:37:30 +07:00
|
|
|
"sfall_funcX(\"%s\", ...) - invalid number of arguments (%d), must be from %d to %d.",
|
|
|
|
|
metaruleInfo->name,
|
|
|
|
|
argCount,
|
|
|
|
|
metaruleInfo->minArgs,
|
|
|
|
|
metaruleInfo->maxArgs);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
2017-02-23 23:45:15 +07:00
|
|
|
return ctx.validateArguments(metaruleInfo->argValidation, metaruleInfo->name);
|
2016-11-04 03:37:30 +07:00
|
|
|
}
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
|
|
|
|
|
2017-02-23 19:07:22 +07:00
|
|
|
void HandleMetarule(OpcodeContext& ctx) {
|
2016-11-14 21:57:44 +07:00
|
|
|
const ScriptValue &nameArg = ctx.arg(0);
|
2016-11-05 03:34:09 +07:00
|
|
|
if (nameArg.isString()) {
|
|
|
|
|
const char* name = nameArg.asString();
|
2016-11-02 04:10:50 +07:00
|
|
|
MetaruleTableType::iterator lookup = metaruleTable.find(name);
|
|
|
|
|
if (lookup != metaruleTable.end()) {
|
2016-11-06 16:52:09 +07:00
|
|
|
currentMetarule = lookup->second;
|
|
|
|
|
// shift function name away, so argument #0 will correspond to actual first argument of function
|
|
|
|
|
// this allows to use the same handlers for opcodes and metarule functions
|
2016-11-14 21:57:44 +07:00
|
|
|
ctx.setArgShift(1);
|
|
|
|
|
if (ValidateMetaruleArguments(ctx, currentMetarule)) {
|
|
|
|
|
currentMetarule->func(ctx);
|
2016-11-04 03:37:30 +07:00
|
|
|
}
|
2016-11-01 03:53:07 +07:00
|
|
|
} else {
|
2016-11-14 21:57:44 +07:00
|
|
|
ctx.printOpcodeError("sfall_funcX(name, ...) - name '%s' is unknown.", name);
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
2016-11-14 21:50:27 +07:00
|
|
|
} else {
|
2016-11-14 21:57:44 +07:00
|
|
|
ctx.printOpcodeError("sfall_funcX(name, ...) - name must be string.");
|
2016-11-01 03:53:07 +07:00
|
|
|
}
|
|
|
|
|
}
|