Refactoring ScriptExtender module.

This commit is contained in:
phobos2077
2016-11-07 03:44:25 +07:00
parent bd7518ca33
commit 10ec39ab60
20 changed files with 1476 additions and 1232 deletions
+1
View File
@@ -218,6 +218,7 @@ namespace VarPtr
#define VARDECL(type, name) \
extern type* const name;
// TODO: assign appropriate types (arrays, structs, strings, etc.) for all variables
VARDECL(long, pc_trait) // 2 of them
VARDECL(DWORD, aiInfoList)
+23
View File
@@ -61,6 +61,14 @@ void display_print(const char* msg) {
}
}
void executeProcedure(TProgram* sptr, int procNum) {
__asm {
mov edx, procNum;
mov eax, sptr;
call FuncOffs::executeProcedure_
}
}
const char* _stdcall getmsg(DWORD fileAddr, int messageId, sMessage* result) {
__asm {
mov eax, fileAddr
@@ -123,6 +131,14 @@ void intface_redraw() {
__asm call FuncOffs::intface_redraw_
}
int __stdcall interpretFindProcedure(TProgram* scriptPtr, const char* procName) {
__asm {
mov edx, procName;
mov eax, scriptPtr;
call FuncOffs::interpretFindProcedure_;
}
}
// pops value type from Data stack (must be followed by InterpretPopLong)
DWORD __stdcall interpretPopShort(TProgram* scriptPtr) {
__asm {
@@ -217,4 +233,11 @@ int __stdcall message_search(DWORD* file, sMessage* msg) {
}
}
DWORD* __stdcall runProgram(TProgram* progPtr) {
__asm {
mov eax, progPtr;
call FuncOffs::runProgram_;
}
}
}
+8
View File
@@ -38,6 +38,9 @@ char* proto_ptr(DWORD pid);
// Displays message in main UI console window
void display_print(const char* msg);
// execute script proc by internal proc number (from script's proc table, basically a sequential number of a procedure as defined in code, starting from 1)
void executeProcedure(TProgram* sptr, int procNum);
int __stdcall item_get_type(TGameObj* item);
// Change the name of playable character
@@ -68,6 +71,9 @@ TGameObj* __stdcall inven_left_hand(TGameObj* critter);
// item in critter's right hand slot
TGameObj* __stdcall inven_right_hand(TGameObj* critter);
// finds procedure ID for given script program pointer and procedure name
int __stdcall interpretFindProcedure(TProgram* scriptPtr, const char* procName);
// pops value type from Data stack (must be followed by InterpretPopLong)
DWORD __stdcall interpretPopShort(TProgram* scriptPtr);
@@ -96,4 +102,6 @@ const char* __stdcall findCurrentProc(TProgram* program);
int __stdcall message_search(DWORD* file, sMessage* msg);
DWORD* __stdcall runProgram(TProgram* progPtr);
}
+3 -3
View File
@@ -83,7 +83,7 @@ static void _stdcall RunSpecificHookScript(sHookScript *hook) {
cArg=0;
cRetTmp=0;
if (hook->callback != -1)
RunScriptProcByNum(hook->prog.ptr, hook->callback);
Wrapper::executeProcedure(hook->prog.ptr, hook->callback);
else
RunScriptProc(&hook->prog, start);
}
@@ -1076,7 +1076,7 @@ void _stdcall SetHSReturn(DWORD d) {
if (cRetTmp > cRet)
cRet = cRetTmp;
}
void _stdcall RegisterHook( DWORD script, DWORD id, DWORD procNum )
void _stdcall RegisterHook(TProgram* script, int id, int procNum )
{
if (id >= numHooks) return;
for (std::vector<sHookScript>::iterator it = hooks[id].begin(); it != hooks[id].end(); ++it) {
@@ -1108,7 +1108,7 @@ static void LoadHookScript(const char* name, int id) {
mov fileExist, al
}
if (fileExist && !isGameScript(name)) {
if (fileExist && !IsGameScript(name)) {
sScriptProgram prog;
dlog(">", DL_HOOK);
dlog(name, DL_HOOK);
+1 -1
View File
@@ -55,7 +55,7 @@ DWORD* _stdcall GetHSArgs();
void _stdcall SetHSArg(DWORD id, DWORD value);
void _stdcall SetHSReturn(DWORD d);
// register hook by proc num (special values: -1 - use default (start) procedure, 0 - unregister)
void _stdcall RegisterHook(DWORD script, DWORD id, DWORD procNum);
void _stdcall RegisterHook(TProgram* script, int id, int procNum);
void HookScriptInit();
void HookScriptClear();
File diff suppressed because it is too large Load Diff
+8 -18
View File
@@ -17,15 +17,9 @@
*/
#pragma once
#include "..\main.h"
// TODO: replace with enum class
enum SfallDataType {
DATATYPE_NONE = 0,
DATATYPE_INT,
DATATYPE_FLOAT,
DATATYPE_STR
};
#include "..\main.h"
#include "..\FalloutEngine\Structs.h"
struct sGlobalVar {
__int64 id;
@@ -34,13 +28,13 @@ struct sGlobalVar {
#define SCRIPT_PROC_MAX (27)
typedef struct {
DWORD ptr;
DWORD procLookup[SCRIPT_PROC_MAX+1];
TProgram* ptr;
int procLookup[SCRIPT_PROC_MAX+1];
char initialized;
} sScriptProgram;
void ScriptExtenderSetup();
bool _stdcall isGameScript(const char* filename);
bool _stdcall IsGameScript(const char* filename);
void LoadGlobalScripts();
void ClearGlobalScripts();
@@ -66,22 +60,18 @@ void GetAppearanceGlobals(int *race, int *style);
void _stdcall RegAnimCombatCheck(DWORD newValue);
DWORD _stdcall ScriptHasLoaded(DWORD script);
// finds procedure ID for given script program pointer and procedure name
DWORD GetScriptProcByName(DWORD scriptPtr, const char* procName);
bool _stdcall ScriptHasLoaded(TProgram* script);
// loads script from .int file into scripting engine, fill scriptPtr and proc table
void LoadScriptProgram(sScriptProgram &prog, const char* fileName);
// init program after load, needs to be called once
void InitScriptProgram(sScriptProgram &prog);
// execute script proc by internal proc number (from script's proc table, basically a sequential number of a procedure as defined in code, starting from 1)
void RunScriptProcByNum(DWORD sptr, DWORD procNum);
// execute script by specific proc name
void RunScriptProc(sScriptProgram* prog, const char* procName);
// execute script proc by procId from define.h
void RunScriptProc(sScriptProgram* prog, DWORD procId);
void RunScriptProc(sScriptProgram* prog, int procId);
void AddProgramToMap(sScriptProgram &prog);
sScriptProgram* GetGlobalScriptProgram(DWORD scriptPtr);
sScriptProgram* GetGlobalScriptProgram(TProgram* scriptPtr);
char* _stdcall mysubstr(char* str, int pos, int length);
// variables
+11 -49
View File
@@ -1,8 +1,11 @@
#include <set>
#include <algorithm>
#include "Arrays.h"
#include "..\ScriptExtender.h"
#include "..\Scripting\ScriptValue.h"
#include "..\Scripting\OpcodeHandler.h"
#include "Arrays.h"
/*
GLOBAL variable for arrays
@@ -314,47 +317,6 @@ void DESetArray(int id, const DWORD* types, const void* data) {
TODO: move somewhere else
*/
const char* _stdcall GetSfallTypeName(DWORD dataType) {
switch (dataType) {
case DATATYPE_NONE:
return "(none)";
case DATATYPE_STR:
return "string";
case DATATYPE_FLOAT:
return "float";
case DATATYPE_INT:
return "integer";
default:
return "(unknown)";
}
}
DWORD _stdcall getSfallTypeByScriptType(DWORD varType) {
varType &= 0xffff;
switch (varType) {
case VAR_TYPE_STR:
case VAR_TYPE_STR2:
return DATATYPE_STR;
case VAR_TYPE_FLOAT:
return DATATYPE_FLOAT;
case VAR_TYPE_INT:
default:
return DATATYPE_INT;
}
}
DWORD _stdcall getScriptTypeBySfallType(DWORD dataType) {
switch (dataType) {
case DATATYPE_STR:
return VAR_TYPE_STR;
case DATATYPE_FLOAT:
return VAR_TYPE_FLOAT;
case DATATYPE_INT:
default:
return VAR_TYPE_INT;
}
}
DWORD _stdcall CreateArray(int len, DWORD nothing) {
sArrayVar var;
if (len < 0) var.flags |= ARRAYFLAG_ASSOC;
@@ -419,7 +381,7 @@ DWORD _stdcall GetArray(DWORD id, DWORD key, DWORD keyType, DWORD* resultType) {
int el;
sArrayVar &arr = arrays[id];
if (arr.isAssoc()) {
ArrayKeysMap::iterator it = arr.keyHash.find(sArrayElement(key, getSfallTypeByScriptType(keyType)));
ArrayKeysMap::iterator it = arr.keyHash.find(sArrayElement(key, OpcodeHandler::getSfallTypeByScriptType(keyType)));
if (it != arr.keyHash.end())
el = it->second + 1;
else
@@ -443,8 +405,8 @@ DWORD _stdcall GetArray(DWORD id, DWORD key, DWORD keyType, DWORD* resultType) {
return 0;
}
void _stdcall SetArray(DWORD id, DWORD key, DWORD keyType, DWORD val, DWORD valType, DWORD allowUnset) {
keyType = getSfallTypeByScriptType(keyType);
valType = getSfallTypeByScriptType(valType);
keyType = OpcodeHandler::getSfallTypeByScriptType(keyType);
valType = OpcodeHandler::getSfallTypeByScriptType(valType);
if(arrays.find(id)==arrays.end()) return;
int el;
sArrayVar &arr = arrays[id];
@@ -536,7 +498,7 @@ void _stdcall FixArray(DWORD id) {
}
int _stdcall ScanArray(DWORD id, DWORD val, DWORD datatype, DWORD* resultType) {
*resultType = VAR_TYPE_INT;
datatype = getSfallTypeByScriptType(datatype);
datatype = OpcodeHandler::getSfallTypeByScriptType(datatype);
if (arrays.find(id) == arrays.end()) return -1;
char step = arrays[id].isAssoc() ? 2 : 1;
for (DWORD i = 0; i < arrays[id].val.size(); i += step) {
@@ -545,7 +507,7 @@ int _stdcall ScanArray(DWORD id, DWORD val, DWORD datatype, DWORD* resultType) {
if ((datatype != DATATYPE_STR && *(DWORD*)&(el.intVal) == val) ||
(datatype == DATATYPE_STR && strcmp(el.strVal, (char*)val) == 0)) {
if (arrays[id].isAssoc()) { // return key instead of index for associative arrays
*resultType = getScriptTypeBySfallType(arrays[id].val[i].type);
*resultType = OpcodeHandler::getScriptTypeBySfallType(arrays[id].val[i].type);
return *(DWORD *)&arrays[id].val[i].intVal;
} else {
return i;
@@ -557,7 +519,7 @@ int _stdcall ScanArray(DWORD id, DWORD val, DWORD datatype, DWORD* resultType) {
}
DWORD _stdcall LoadArray(DWORD key, DWORD keyType) {
int dataType = getSfallTypeByScriptType(keyType);
int dataType = OpcodeHandler::getSfallTypeByScriptType(keyType);
if (dataType != DATATYPE_INT || key != 0) { // returns arrayId by it's key (ignoring int(0) because it is used to "unsave" array)
sArrayElement keyEl = sArrayElement(key, dataType);
if (keyEl.type == DATATYPE_STR && strcmp(keyEl.strVal, get_all_arrays_special_key) == 0) { // this is a special case to get temp array containing all saved arrays
@@ -583,7 +545,7 @@ DWORD _stdcall LoadArray(DWORD key, DWORD keyType) {
void _stdcall SaveArray(DWORD key, DWORD keyType, DWORD id) {
array_itr it = arrays.find(id), it2;
int dataType = getSfallTypeByScriptType(keyType);
int dataType = OpcodeHandler::getSfallTypeByScriptType(keyType);
if (it != arrays.end()) {
if (dataType != DATATYPE_INT || key != 0) {
// make array permanent
-3
View File
@@ -143,9 +143,6 @@ void GetArrays(int* arrays);
void DEGetArray(int id, DWORD* types, void* data);
void DESetArray(int id, const DWORD* types, const void* data);
const char* _stdcall GetSfallTypeName(DWORD dataType);
DWORD _stdcall getSfallTypeByScriptType(DWORD varType);
DWORD _stdcall getScriptTypeBySfallType(DWORD dataType);
// creates new normal (persistent) array. len == -1 specifies associative array (map)
DWORD _stdcall CreateArray(int len, DWORD nothing);
// same as CreateArray, but creates temporary array instead (will die at the end of the frame)
+9
View File
@@ -10,6 +10,15 @@
- use this macros outside of other __asm {} blocks (obviously)
*/
//eax contains the script pointer, edx contains the opcode*4
//To read a value, mov the script pointer to eax, call interpretPopShort_, eax now contains the value type
//mov the script pointer to eax, call interpretPopLong_, eax now contains the value
//To return a value, move it to edx, mov the script pointer to eax, call FuncOffs::interpretPushLong_
//mov the value type to edx, mov the script pointer to eax, call FuncOffs::interpretPushShort_
// rscript - 32-bit register where script pointer will be put (it is used for several related functions)
#define _OP_BEGIN(rscript) __asm \
{ \
+1 -9
View File
@@ -135,16 +135,8 @@ static bool ValidateMetaruleArguments(const SfallMetarule* metaruleInfo) {
return false;
} else {
// check if metadata is available for this handler
OpcodeMetaTableType::iterator it = opcodeMetaTable.find(metaruleInfo->func);
if (it != opcodeMetaTable.end()) {
const SfallOpcodeMetadata* meta = it->second;
// automatically validate argument types
return opHandler.validateArguments(meta->argTypeMasks, argCount, metaruleInfo->name);
}
return opHandler.validateArguments(metaruleInfo->func, argCount);
}
return true;
}
static void _stdcall op_sfall_metarule_handler() {
+4
View File
@@ -21,11 +21,14 @@
#include "..\..\main.h"
#include "..\AI.h"
#include "..\Criticals.h"
#include "..\HeroAppearance.h"
#include "..\Inventory.h"
#include "..\KillCounter.h"
#include "..\Knockback.h"
#include "..\Movies.h"
#include "..\ScriptExtender.h"
#include "..\Stats.h"
/*
* Misc operators
@@ -972,6 +975,7 @@ end:
retn;
}
}
static void __declspec(naked) funcGetCriticalTable() {
__asm {
pushad;
+208
View File
@@ -0,0 +1,208 @@
/*
* sfall
* Copyright (C) 2008-2016 The sfall team
*
* 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/>.
*/
#include "..\..\main.h"
#include "..\..\FalloutEngine\Fallout2.h"
#include "..\ScriptExtender.h"
#include "OpcodeHandler.h"
OpcodeHandler::OpcodeHandler() {
_argShift = 0;
_args.reserve (OP_MAX_ARGUMENTS);
}
int OpcodeHandler::numArgs() const {
return _args.size() - _argShift;
}
int OpcodeHandler::argShift() const {
return _argShift;
}
void OpcodeHandler::setArgShift (int shift) {
assert(shift >= 0);
_argShift = shift;
}
const ScriptValue& OpcodeHandler::arg(int index) const {
return _args.at(index + _argShift);
}
const ScriptValue& OpcodeHandler::returnValue() const {
return _ret;
}
TProgram* OpcodeHandler::program() const {
return _program;
}
void OpcodeHandler::setReturn(DWORD value, SfallDataType type) {
_ret = ScriptValue(type, value);
}
void OpcodeHandler::setReturn(const ScriptValue& val) {
_ret = val;
}
void OpcodeHandler::resetState(TProgram* program, int argNum) {
_program = program;
// reset return value
_ret = ScriptValue();
// reset argument list
_args.resize(argNum);
// reset arg shift
_argShift = 0;
}
void OpcodeHandler::printOpcodeError(const char* fmt, ...) const {
assert(_program != nullptr);
va_list args;
va_start(args, fmt);
char msg[1024];
vsnprintf_s(msg, sizeof msg, _TRUNCATE, fmt, args);
va_end(args);
const char* procName = Wrapper::findCurrentProc(_program);
Wrapper::debug_printf("\nOPCODE ERROR: %s\n Current script: %s, procedure %s.", msg, _program->fileName, procName);
}
bool OpcodeHandler::validateArguments(void (*func)(), int argNum) const {
OpcodeMetaTableType::const_iterator it = _opcodeMetaTable.find(func);
if (it != _opcodeMetaTable.end()) {
const SfallOpcodeMetadata* meta = it->second;
// automatically validate argument types
return validateArguments(meta->argTypeMasks, argNum, meta->name);
}
return true;
}
bool OpcodeHandler::validateArguments(const int argTypeMasks[], int argCount, const char* opcodeName) const {
for (int i = 0; i < argCount; i++) {
int typeMask = argTypeMasks[i];
const ScriptValue &argI = arg(i);
if (typeMask != 0 && ((1 << argI.type()) & typeMask) == 0) {
printOpcodeError(
"%s() - argument #%d has invalid type: %s.",
opcodeName,
i,
getSfallTypeName(argI.type()));
return false;
} else if ((typeMask & DATATYPE_MASK_NOT_NULL) && argI.rawValue() == 0) {
printOpcodeError(
"%s() - argument #%d is null.",
opcodeName,
i);
return false;
}
}
return true;
}
void __thiscall OpcodeHandler::handleOpcode(TProgram* program, void(*func)(), int argNum, bool hasReturn) {
assert(argNum < OP_MAX_ARGUMENTS);
// reset state after previous
resetState(program, argNum);
// process arguments on stack (reverse order)
for (int i = argNum - 1; i >= 0; i--) {
// get argument from stack
DWORD rawValueType = Wrapper::interpretPopShort(program);
DWORD rawValue = Wrapper::interpretPopLong(program);
SfallDataType type = static_cast<SfallDataType>(getSfallTypeByScriptType(rawValueType));
// retrieve string argument
if (type == DATATYPE_STR) {
_args.at(i) = Wrapper::interpretGetString(program, rawValue, rawValueType);
} else {
_args.at(i) = ScriptValue(type, rawValue);
}
}
// call opcode handler if arguments are valid (or no automatic validation was done)
if (validateArguments(func, argNum)) {
func();
}
// process return value
if (hasReturn) {
if (_ret.type() == DATATYPE_NONE) {
// if no value was set in handler, force return 0 to avoid stack error
_ret = ScriptValue(0);
}
DWORD rawResult = _ret.rawValue();
if (_ret.type() == DATATYPE_STR) {
rawResult = Wrapper::interpretAddString(program, _ret.asString());
}
Wrapper::interpretPushLong(program, rawResult);
Wrapper::interpretPushShort(program, getScriptTypeBySfallType(_ret.type()));
}
}
void OpcodeHandler::addOpcodeMetaData(const SfallOpcodeMetadata* data) {
_opcodeMetaTable[data->handler] = data;
}
const char* OpcodeHandler::getSfallTypeName(DWORD dataType) {
switch (dataType) {
case DATATYPE_NONE:
return "(none)";
case DATATYPE_STR:
return "string";
case DATATYPE_FLOAT:
return "float";
case DATATYPE_INT:
return "integer";
default:
return "(unknown)";
}
}
DWORD OpcodeHandler::getSfallTypeByScriptType(DWORD varType) {
varType &= 0xffff;
switch (varType) {
case VAR_TYPE_STR:
case VAR_TYPE_STR2:
return DATATYPE_STR;
case VAR_TYPE_FLOAT:
return DATATYPE_FLOAT;
case VAR_TYPE_INT:
default:
return DATATYPE_INT;
}
}
DWORD OpcodeHandler::getScriptTypeBySfallType(DWORD dataType) {
switch (dataType) {
case DATATYPE_STR:
return VAR_TYPE_STR;
case DATATYPE_FLOAT:
return VAR_TYPE_FLOAT;
case DATATYPE_INT:
default:
return VAR_TYPE_INT;
}
}
+113
View File
@@ -0,0 +1,113 @@
/*
* sfall
* Copyright (C) 2008-2016 The sfall team
*
* 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/>.
*/
#pragma once
#include <unordered_map>
#include <vector>
#include "..\..\FalloutEngine\Structs.h"
#include "ScriptValue.h"
// variables for new opcodes
#define OP_MAX_ARGUMENTS (10)
// masks for argument validation
#define DATATYPE_MASK_INT (1 << DATATYPE_INT)
#define DATATYPE_MASK_FLOAT (1 << DATATYPE_FLOAT)
#define DATATYPE_MASK_STR (1 << DATATYPE_STR)
#define DATATYPE_MASK_NOT_NULL (0x00010000)
#define DATATYPE_MASK_VALID_OBJ (DATATYPE_MASK_INT | DATATYPE_MASK_NOT_NULL)
struct SfallOpcodeMetadata {
// opcode handler, will be used as key
void (*handler)();
// opcode name, only used for logging
const char* name;
// argument validation masks
int argTypeMasks[OP_MAX_ARGUMENTS];
};
typedef std::tr1::unordered_map<void(*)(), const SfallOpcodeMetadata*> OpcodeMetaTableType;
class OpcodeHandler {
public:
OpcodeHandler();
void addOpcodeMetaData(const SfallOpcodeMetadata* data);
// number of arguments, possibly reduced by argShift
int numArgs() const;
// returns current argument shift, default is 0
int argShift() const;
// sets shift value for arguments
// for example if shift value is 2, then subsequent calls to arg(i) will return arg(i+2) instead, etc.
void setArgShift(int shift);
// returns argument with given index, possible shifted by argShift
const ScriptValue& arg(int index) const;
// current return value
const ScriptValue& returnValue() const;
// current script program
TProgram* program() const;
// set return value for current opcode
void setReturn(unsigned long value, SfallDataType type);
// set return value for current opcode
void setReturn(const ScriptValue& val);
// resets the state of handler for new opcode invocation
void resetState(TProgram* program, int argNum);
// writes error message to debug.log along with the name of script & procedure
void printOpcodeError(const char* fmt, ...) const;
// Validate opcode arguments against type masks
// if validation pass, returns true, otherwise writes error to debug.log and returns false
bool validateArguments(const int argTypeMasks[], int argCount, const char* opcodeName) const;
// validate opcode arguments given opcode handler function and actual number of arguments
bool validateArguments(void (*func)(), int argNum) const;
// Handle opcodes
// scriptPtr - pointer to script program (from the engine)
// func - opcode handler
// hasReturn - true if opcode has return value (is expression)
void __thiscall handleOpcode(TProgram* program, void(*func)(), int argNum, bool hasReturn);
static const char* getSfallTypeName(DWORD dataType);
static DWORD getSfallTypeByScriptType(DWORD varType);
static DWORD getScriptTypeBySfallType(DWORD dataType);
private:
TProgram* _program;
int _argShift;
std::vector<ScriptValue> _args;
ScriptValue _ret;
OpcodeMetaTableType _opcodeMetaTable;
};
File diff suppressed because it is too large Load Diff
+106
View File
@@ -0,0 +1,106 @@
/*
* sfall
* Copyright (C) 2008-2016 The sfall team
*
* 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/>.
*/
#include "ScriptValue.h"
ScriptValue::ScriptValue( SfallDataType type, unsigned long value )
{
_val.dw = value;
_type = type;
}
ScriptValue::ScriptValue() {
_val.dw = 0;
_type = DATATYPE_NONE;
}
ScriptValue::ScriptValue(const char* strval) {
_val.str = strval;
_type = DATATYPE_STR;
}
ScriptValue::ScriptValue(int val) {
_val.i = val;
_type = DATATYPE_INT;
}
ScriptValue::ScriptValue(float strval) {
_val.f = strval;
_type = DATATYPE_FLOAT;
}
ScriptValue::ScriptValue(TGameObj* obj) {
_val.gObj = obj;
_type = DATATYPE_INT;
}
bool ScriptValue::isInt() const
{
return _type == DATATYPE_INT;
}
bool ScriptValue::isFloat() const {
return _type == DATATYPE_FLOAT;
}
bool ScriptValue::isString() const {
return _type == DATATYPE_STR;
}
unsigned long ScriptValue::rawValue() const {
return _val.dw;
}
int ScriptValue::asInt() const {
switch (_type) {
case DATATYPE_FLOAT:
return static_cast<int>(_val.f);
case DATATYPE_INT:
return _val.i;
default:
return 0;
}
}
float ScriptValue::asFloat() const {
switch (_type) {
case DATATYPE_FLOAT:
return _val.f;
case DATATYPE_INT:
return static_cast<float>(_val.i);
default:
return 0.0;
}
}
const char* ScriptValue::asString() const {
return (_type == DATATYPE_STR)
? _val.str
: "";
}
TGameObj* ScriptValue::asObject() const {
return (_type == DATATYPE_INT)
? _val.gObj
: nullptr;
}
SfallDataType ScriptValue::type() const {
return _type;
}
+74
View File
@@ -0,0 +1,74 @@
/*
* sfall
* Copyright (C) 2008-2016 The sfall team
*
* 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/>.
*/
#pragma once
#include "..\..\FalloutEngine\Structs.h"
// TODO: replace with enum class
enum SfallDataType {
DATATYPE_NONE = 0,
DATATYPE_INT,
DATATYPE_FLOAT,
DATATYPE_STR
};
class ScriptValue {
public:
ScriptValue(SfallDataType type, unsigned long value);
ScriptValue();
ScriptValue(const char* strval);
ScriptValue(int val);
ScriptValue(float strval);
ScriptValue(TGameObj* obj);
bool isInt() const;
bool isFloat() const;
bool isString() const;
unsigned long rawValue() const;
int asInt() const;
float asFloat() const;
const char* asString() const;
TGameObj* asObject() const;
SfallDataType type() const;
private:
union Value {
unsigned long dw;
int i;
float f;
const char* str;
TGameObj* gObj;
} _val;
SfallDataType _type; // TODO: replace with enum class
};
+5
View File
@@ -222,9 +222,12 @@
<ClInclude Include="Modules\Scripting\MetaruleOp.hpp" />
<ClInclude Include="Modules\Scripting\MiscOps.hpp" />
<ClInclude Include="Modules\Scripting\ObjectsOps.hpp" />
<ClInclude Include="Modules\Scripting\OpcodeHandler.h" />
<ClInclude Include="Modules\Scripting\Opcodes.hpp" />
<ClInclude Include="Modules\Scripting\PerksOp.hpp" />
<ClInclude Include="Modules\Scripting\ScriptArrays.hpp" />
<ClInclude Include="Modules\Scripting\ScriptUtils.hpp" />
<ClInclude Include="Modules\Scripting\ScriptValue.h" />
<ClInclude Include="Modules\Scripting\StatsOp.hpp" />
<ClInclude Include="Modules\Scripting\WorldmapOps.hpp" />
<ClInclude Include="win9x\Cpp11_emu.h" />
@@ -305,6 +308,8 @@
<ClCompile Include="Modules\QuestList.cpp" />
<ClCompile Include="Modules\Reputations.cpp" />
<ClCompile Include="Modules\Scripting\Arrays.cpp" />
<ClCompile Include="Modules\Scripting\OpcodeHandler.cpp" />
<ClCompile Include="Modules\Scripting\ScriptValue.cpp" />
<ClCompile Include="SafeWrite.cpp" />
<ClCompile Include="Modules\Skills.cpp" />
<ClCompile Include="Modules\Sound.cpp" />
+15
View File
@@ -204,6 +204,15 @@
<ClInclude Include="FalloutEngine\Utils.h">
<Filter>FalloutEngine</Filter>
</ClInclude>
<ClInclude Include="Modules\Scripting\OpcodeHandler.h">
<Filter>Modules\Scripting</Filter>
</ClInclude>
<ClInclude Include="Modules\Scripting\ScriptValue.h">
<Filter>Modules\Scripting</Filter>
</ClInclude>
<ClInclude Include="Modules\Scripting\Opcodes.hpp">
<Filter>Modules\Scripting</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
@@ -340,6 +349,12 @@
<ClCompile Include="FalloutEngine\Utils.cpp">
<Filter>FalloutEngine</Filter>
</ClCompile>
<ClCompile Include="Modules\Scripting\OpcodeHandler.cpp">
<Filter>Modules\Scripting</Filter>
</ClCompile>
<ClCompile Include="Modules\Scripting\ScriptValue.cpp">
<Filter>Modules\Scripting</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />
+1
View File
@@ -18,6 +18,7 @@
#pragma once
#include <assert.h>
//#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include "SafeWrite.h"