mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Refactor: encapsulated opcode-related functions and variables into classes
This commit is contained in:
+184
-132
@@ -41,6 +41,104 @@ void _stdcall HandleMapUpdateForScripts(DWORD procId);
|
||||
// variables for new opcodes
|
||||
#define OP_MAX_ARGUMENTS (10)
|
||||
|
||||
class ScriptValue {
|
||||
public:
|
||||
ScriptValue(SfallDataType type, DWORD value) {
|
||||
_val.dw = value;
|
||||
_type = type;
|
||||
}
|
||||
|
||||
ScriptValue() {
|
||||
_val.dw = 0;
|
||||
_type = DATATYPE_NONE;
|
||||
}
|
||||
|
||||
ScriptValue(const char* strval) {
|
||||
_val.str = strval;
|
||||
_type = DATATYPE_STR;
|
||||
}
|
||||
|
||||
ScriptValue(int val) {
|
||||
_val.i = val;
|
||||
_type = DATATYPE_INT;
|
||||
}
|
||||
|
||||
ScriptValue(float strval) {
|
||||
_val.f = strval;
|
||||
_type = DATATYPE_FLOAT;
|
||||
}
|
||||
|
||||
ScriptValue(TGameObj* obj) {
|
||||
_val.gObj = obj;
|
||||
_type = DATATYPE_INT;
|
||||
}
|
||||
|
||||
bool isInt() const {
|
||||
return _type == DATATYPE_INT;
|
||||
}
|
||||
|
||||
bool isFloat() const {
|
||||
return _type == DATATYPE_FLOAT;
|
||||
}
|
||||
|
||||
bool isString() const {
|
||||
return _type == DATATYPE_STR;
|
||||
}
|
||||
|
||||
DWORD rawValue() const {
|
||||
return _val.dw;
|
||||
}
|
||||
|
||||
int asInt() const {
|
||||
switch (_type) {
|
||||
case DATATYPE_FLOAT:
|
||||
return static_cast<int>(_val.f);
|
||||
case DATATYPE_INT:
|
||||
return _val.i;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
float 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* asString() const {
|
||||
return (_type == DATATYPE_STR)
|
||||
? _val.str
|
||||
: "";
|
||||
}
|
||||
|
||||
TGameObj* asObject() const {
|
||||
return (_type == DATATYPE_INT)
|
||||
? _val.gObj
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
SfallDataType type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
private:
|
||||
union Value {
|
||||
DWORD dw;
|
||||
int i;
|
||||
float f;
|
||||
const char* str;
|
||||
TGameObj* gObj;
|
||||
} _val;
|
||||
|
||||
SfallDataType _type; // TODO: replace with enum class
|
||||
} ;
|
||||
|
||||
typedef struct {
|
||||
union Value {
|
||||
DWORD dw;
|
||||
@@ -50,93 +148,99 @@ typedef struct {
|
||||
TGameObj* gObj;
|
||||
} val;
|
||||
DWORD type; // TODO: replace with enum class
|
||||
} ScriptValue;
|
||||
} ScriptValue1;
|
||||
|
||||
static TProgram* opProgram;
|
||||
static DWORD opArgCount = 0;
|
||||
static ScriptValue opArgs[OP_MAX_ARGUMENTS];
|
||||
static ScriptValue opRet;
|
||||
|
||||
static void _stdcall SetOpReturn(DWORD value, DWORD type) {
|
||||
opRet.val.dw = value;
|
||||
opRet.type = type;
|
||||
}
|
||||
|
||||
static void _stdcall SetOpReturn(int value) {
|
||||
opRet.val.i = value;
|
||||
opRet.type = DATATYPE_INT;
|
||||
}
|
||||
|
||||
static void _stdcall SetOpReturn(float value) {
|
||||
opRet.val.f = value;
|
||||
opRet.type = DATATYPE_FLOAT;
|
||||
}
|
||||
|
||||
static void _stdcall SetOpReturn(const char* value) {
|
||||
opRet.val.str = value;
|
||||
opRet.type = DATATYPE_STR;
|
||||
}
|
||||
|
||||
static void _stdcall SetOpReturn(TGameObj* value) {
|
||||
opRet.val.gObj = value;
|
||||
opRet.type = DATATYPE_INT;
|
||||
}
|
||||
|
||||
|
||||
// TODO: replace these functions with proper ScriptValue class (encapsulation...)
|
||||
static bool _stdcall IsOpArgInt(int num) {
|
||||
return (opArgs[num].type == DATATYPE_INT);
|
||||
}
|
||||
|
||||
static bool _stdcall IsOpArgFloat(int num) {
|
||||
return (opArgs[num].type == DATATYPE_FLOAT);
|
||||
}
|
||||
|
||||
static bool _stdcall IsOpArgStr(int num) {
|
||||
return (opArgs[num].type == DATATYPE_STR);
|
||||
}
|
||||
|
||||
static int _stdcall GetOpArgCount() {
|
||||
return opArgCount;
|
||||
}
|
||||
|
||||
static int _stdcall GetOpArgInt(int num) {
|
||||
switch (opArgs[num].type) {
|
||||
case DATATYPE_FLOAT:
|
||||
return static_cast<int>(opArgs[num].val.f);
|
||||
case DATATYPE_INT:
|
||||
return opArgs[num].val.i;
|
||||
default:
|
||||
return 0;
|
||||
class OpcodeHandler {
|
||||
public:
|
||||
// number of arguments
|
||||
int numArgs() const {
|
||||
return _args.size();
|
||||
}
|
||||
}
|
||||
|
||||
static float _stdcall GetOpArgFloat(int num) {
|
||||
switch (opArgs[num].type) {
|
||||
case DATATYPE_FLOAT:
|
||||
return opArgs[num].val.f;
|
||||
case DATATYPE_INT:
|
||||
return static_cast<float>(opArgs[num].val.i);
|
||||
default:
|
||||
return 0.0;
|
||||
// returns argument with given index
|
||||
const ScriptValue& arg(int index) const {
|
||||
return _args.at(index);
|
||||
}
|
||||
|
||||
// current return value
|
||||
const ScriptValue& returnValue() const {
|
||||
return _ret;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* _stdcall GetOpArgStr(int num) {
|
||||
return (opArgs[num].type == DATATYPE_STR)
|
||||
? opArgs[num].val.str
|
||||
: "";
|
||||
}
|
||||
// current script program
|
||||
TProgram* program() const {
|
||||
return _program;
|
||||
}
|
||||
|
||||
// set return value for current opcode
|
||||
void setReturn(DWORD value, SfallDataType type) {
|
||||
_ret = ScriptValue(type, value);
|
||||
}
|
||||
|
||||
// set return value for current opcode
|
||||
void setReturn(const ScriptValue& val) {
|
||||
_ret = val;
|
||||
}
|
||||
|
||||
static TGameObj* _stdcall GetOpArgObj(int num) {
|
||||
return (opArgs[num].type == DATATYPE_INT)
|
||||
? opArgs[num].val.gObj
|
||||
: nullptr;
|
||||
}
|
||||
// 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* scriptPtr, void(*func)(), int argNum, bool hasReturn) {
|
||||
assert(argNum < OP_MAX_ARGUMENTS);
|
||||
|
||||
_program = scriptPtr;
|
||||
|
||||
// reset return value
|
||||
_ret = ScriptValue();
|
||||
|
||||
// process arguments on stack (reverse order)
|
||||
_args.resize(0);
|
||||
for (int i = argNum - 1; i >= 0; i--) {
|
||||
// get argument from stack
|
||||
DWORD rawValueType = InterpretPopShort(scriptPtr);
|
||||
DWORD rawValue = InterpretPopLong(scriptPtr);
|
||||
SfallDataType type = static_cast<SfallDataType>(getSfallTypeByScriptType(rawValueType));
|
||||
|
||||
// retrieve string argument
|
||||
if (type == DATATYPE_STR) {
|
||||
_args.push_back(InterpretGetString(scriptPtr, rawValue, rawValueType));
|
||||
} else {
|
||||
_args.push_back(ScriptValue(type, rawValue));
|
||||
}
|
||||
}
|
||||
|
||||
// call opcode handler
|
||||
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 = InterpretAddString(scriptPtr, _ret.asString());
|
||||
}
|
||||
InterpretPushLong(scriptPtr, rawResult);
|
||||
InterpretPushShort(scriptPtr, getScriptTypeBySfallType(_ret.type()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TProgram* _program;
|
||||
|
||||
int _argCount;
|
||||
std::vector<ScriptValue> _args;
|
||||
ScriptValue _ret;
|
||||
};
|
||||
|
||||
static OpcodeHandler opHandler;
|
||||
|
||||
// writes error message to debug.log along with the name of script & procedure
|
||||
static void _stdcall PrintOpcodeError(const char* fmt, ...) {
|
||||
assert(opProgram != nullptr);
|
||||
assert(opHandler.program() != nullptr);
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@@ -144,62 +248,10 @@ static void _stdcall PrintOpcodeError(const char* fmt, ...) {
|
||||
vsnprintf_s(msg, sizeof msg, _TRUNCATE, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
const char* procName = FindCurrentProc(opProgram);
|
||||
DebugPrintf("\nOPCODE ERROR: %s\n Current script: %s, procedure %s.", msg, opProgram->fileName, procName);
|
||||
const char* procName = FindCurrentProc(opHandler.program());
|
||||
DebugPrintf("\nOPCODE ERROR: %s\n Current script: %s, procedure %s.", msg, opHandler.program()->fileName, procName);
|
||||
}
|
||||
|
||||
// Handle opcodes
|
||||
// scriptPtr - pointer to script program (from the engine)
|
||||
// func - opcode handler
|
||||
// hasReturn - true if opcode has return value (is expression)
|
||||
static void __stdcall HandleOpcode(TProgram* scriptPtr, void(*func)(), int argNum, bool hasReturn) {
|
||||
assert(argNum < OP_MAX_ARGUMENTS);
|
||||
|
||||
opProgram = scriptPtr;
|
||||
|
||||
// reset return value
|
||||
opRet.type = DATATYPE_NONE;
|
||||
opRet.val.dw = 0;
|
||||
|
||||
// process arguments on stack (reverse order)
|
||||
opArgCount = argNum;
|
||||
for (int i = OP_MAX_ARGUMENTS - 1; i >= 0; i--) {
|
||||
if (i < argNum) {
|
||||
// get argument from stack
|
||||
DWORD rawValueType = InterpretPopShort(scriptPtr);
|
||||
DWORD rawValue = InterpretPopLong(scriptPtr);
|
||||
opArgs[i].type = getSfallTypeByScriptType(rawValueType);
|
||||
|
||||
// retrieve string argument
|
||||
if (opArgs[i].type == DATATYPE_STR) {
|
||||
opArgs[i].val.str = InterpretGetString(scriptPtr, rawValue, rawValueType);
|
||||
} else {
|
||||
opArgs[i].val.dw = rawValue;
|
||||
}
|
||||
} else {
|
||||
// reset other arguments
|
||||
opArgs[i].val.dw = 0;
|
||||
opArgs[i].type = DATATYPE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// call opcode handler
|
||||
func();
|
||||
|
||||
// process return value
|
||||
if (hasReturn) {
|
||||
if (opRet.type == DATATYPE_NONE) {
|
||||
// if no value was set in handler, force return 0 to avoid stack error
|
||||
SetOpReturn(0, DATATYPE_INT);
|
||||
}
|
||||
DWORD rawResult = opRet.val.dw;
|
||||
if (opRet.type == DATATYPE_STR) {
|
||||
rawResult = InterpretAddString(scriptPtr, opRet.val.str);
|
||||
}
|
||||
InterpretPushLong(scriptPtr, rawResult);
|
||||
InterpretPushShort(scriptPtr, getScriptTypeBySfallType(opRet.type));
|
||||
}
|
||||
}
|
||||
|
||||
#include "ScriptOps\AsmMacros.h"
|
||||
#include "ScriptOps\ScriptArrays.hpp"
|
||||
|
||||
@@ -145,53 +145,9 @@ __asm resultnotstr##num: \
|
||||
__asm push argnum \
|
||||
__asm push func \
|
||||
__asm push eax \
|
||||
__asm call HandleOpcode \
|
||||
__asm lea ecx, opHandler \
|
||||
__asm call OpcodeHandler::HandleOpcode \
|
||||
__asm popad \
|
||||
__asm retn \
|
||||
}
|
||||
|
||||
// Old wrapping macros.. does not support string arguments
|
||||
#define _WRAP_OPCODE_OLD(argnum, func) __asm { \
|
||||
__asm pushad \
|
||||
__asm mov ebp, eax \
|
||||
__asm mov esi, argnum \
|
||||
__asm shl esi, 2 \
|
||||
__asm mov opArgCount, argnum \
|
||||
__asm mov opRetType, 0 \
|
||||
__asm loopbegin: \
|
||||
__asm test esi, esi \
|
||||
__asm jz loopend \
|
||||
__asm sub esi, 4 \
|
||||
__asm mov eax, ebp \
|
||||
__asm call interpretPopShort_ \
|
||||
__asm push eax \
|
||||
__asm call getSfallTypeByScriptType \
|
||||
__asm mov opArgTypes[esi], eax \
|
||||
__asm mov eax, ebp \
|
||||
__asm call interpretPopLong_ \
|
||||
__asm mov opArgs[esi], eax \
|
||||
__asm jmp loopbegin \
|
||||
__asm loopend: \
|
||||
__asm call func \
|
||||
__asm mov eax, opRetType \
|
||||
__asm test eax, eax \
|
||||
__asm jz end \
|
||||
__asm push eax \
|
||||
__asm call getScriptTypeBySfallType \
|
||||
__asm mov ecx, eax \
|
||||
__asm mov edx, opRet \
|
||||
__asm cmp ecx, VAR_TYPE_STR \
|
||||
__asm jne notstring \
|
||||
__asm mov eax, ebp \
|
||||
__asm call interpretAddString_ \
|
||||
__asm mov edx, eax \
|
||||
__asm notstring: \
|
||||
__asm mov eax, ebp \
|
||||
__asm call interpretPushLong_ \
|
||||
__asm mov edx, ecx \
|
||||
__asm mov eax, ebp \
|
||||
__asm call interpretPushShort_ \
|
||||
__asm end: \
|
||||
__asm popad \
|
||||
__asm retn \
|
||||
}
|
||||
|
||||
@@ -459,5 +459,5 @@ static void sf_intface_is_hidden() {
|
||||
call intface_is_hidden_
|
||||
mov isHidden, eax;
|
||||
}
|
||||
SetOpReturn(isHidden);
|
||||
opHandler.setReturn(isHidden);
|
||||
}
|
||||
@@ -29,7 +29,7 @@
|
||||
// Prefix all function handlers with sf_ and add them to sfall_metarule_table.
|
||||
// DO NOT add arguments and/or return values to function handlers!
|
||||
// Use functions GetOpArgXXX(), IsOpArgXXX() inside handler function to read arguments, but argument 0 is always function name.
|
||||
// Use SetOpReturn() to set return value.
|
||||
// Use opHandler.setReturn() to set return value.
|
||||
// If you want to call user-defined procedures in your handler, use RunScriptProc().
|
||||
|
||||
struct SfallMetarule {
|
||||
@@ -61,17 +61,18 @@ static std::string sf_test_stringBuf;
|
||||
static void sf_test() {
|
||||
std::ostringstream sstream;
|
||||
sstream << "sfall_funcX(\"test\"";
|
||||
for (DWORD i = 1; i < opArgCount; i++) {
|
||||
for (int i = 1; i < opHandler.numArgs(); i++) {
|
||||
const ScriptValue &arg = opHandler.arg(i);
|
||||
sstream << ", ";
|
||||
switch (opArgs[i].type) {
|
||||
switch (arg.type()) {
|
||||
case DATATYPE_INT:
|
||||
sstream << GetOpArgInt(i);
|
||||
sstream << arg.asInt();
|
||||
break;
|
||||
case DATATYPE_FLOAT:
|
||||
sstream << GetOpArgFloat(i);
|
||||
sstream << arg.asFloat();
|
||||
break;
|
||||
case DATATYPE_STR:
|
||||
sstream << '"' << GetOpArgStr(i) << '"';
|
||||
sstream << '"' << arg.asString() << '"';
|
||||
break;
|
||||
default:
|
||||
sstream << "???";
|
||||
@@ -81,7 +82,7 @@ static void sf_test() {
|
||||
sstream << ")";
|
||||
|
||||
sf_test_stringBuf = sstream.str();
|
||||
SetOpReturn(sf_test_stringBuf.c_str());
|
||||
opHandler.setReturn(sf_test_stringBuf.c_str());
|
||||
}
|
||||
|
||||
// returns current contents of metarule table
|
||||
@@ -92,7 +93,7 @@ static void sf_get_metarule_table() {
|
||||
arrays[arr].val[i].set(it->first.c_str());
|
||||
i++;
|
||||
}
|
||||
SetOpReturn(arr, DATATYPE_INT);
|
||||
opHandler.setReturn(arr, DATATYPE_INT);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -130,7 +131,7 @@ static void InitMetaruleTable() {
|
||||
// Validates arguments against metarule specification.
|
||||
// On error prints to debug.log and returns false.
|
||||
static bool ValidateOpcodeArguments(const SfallMetarule* metaruleInfo) {
|
||||
int argCount = GetOpArgCount() - 1; // don't count function name
|
||||
int argCount = opHandler.numArgs() - 1; // don't count function name
|
||||
if (argCount < metaruleInfo->minArgs || argCount > metaruleInfo->maxArgs) {
|
||||
PrintOpcodeError(
|
||||
"sfall_funcX(\"%s\", ...) - invalid number of arguments (%d), must be from %d to %d.",
|
||||
@@ -143,16 +144,16 @@ static bool ValidateOpcodeArguments(const SfallMetarule* metaruleInfo) {
|
||||
} else {
|
||||
for (int i = 0; i < argCount; i++) {
|
||||
int typeMask = metaruleInfo->argTypeMasks[i];
|
||||
ScriptValue arg = opArgs[i + 1];
|
||||
if (typeMask != 0 && ((1 << arg.type) & typeMask) == 0) {
|
||||
const ScriptValue &arg = opHandler.arg(i + 1);
|
||||
if (typeMask != 0 && ((1 << arg.type()) & typeMask) == 0) {
|
||||
PrintOpcodeError(
|
||||
"sfall_funcX(\"%s\", ...) - argument #%d has invalid type: %s.",
|
||||
metaruleInfo->name,
|
||||
i + 1,
|
||||
GetSfallTypeName(arg.type));
|
||||
GetSfallTypeName(arg.type()));
|
||||
|
||||
return false;
|
||||
} else if ((typeMask & DATATYPE_MASK_NOT_NULL) && arg.val.dw == 0) {
|
||||
} else if ((typeMask & DATATYPE_MASK_NOT_NULL) && arg.rawValue() == 0) {
|
||||
PrintOpcodeError(
|
||||
"sfall_funcX(\"%s\", ...) - argument #%d is null.",
|
||||
metaruleInfo->name,
|
||||
@@ -166,8 +167,9 @@ static bool ValidateOpcodeArguments(const SfallMetarule* metaruleInfo) {
|
||||
}
|
||||
|
||||
static void _stdcall op_sfall_metarule_handler() {
|
||||
if (IsOpArgStr(0)) {
|
||||
const char* name = GetOpArgStr(0);
|
||||
const ScriptValue &nameArg = opHandler.arg(0);
|
||||
if (nameArg.isString()) {
|
||||
const char* name = nameArg.asString();
|
||||
MetaruleTableType::iterator lookup = metaruleTable.find(name);
|
||||
if (lookup != metaruleTable.end()) {
|
||||
const SfallMetarule* metaruleInfo = lookup->second;
|
||||
|
||||
@@ -115,10 +115,10 @@ end:
|
||||
|
||||
// TODO: rewrite, remove all ASM
|
||||
static void _stdcall op_create_spatial2() {
|
||||
DWORD scriptIndex = GetOpArgInt(0),
|
||||
tile = GetOpArgInt(1),
|
||||
elevation = GetOpArgInt(2),
|
||||
radius = GetOpArgInt(3),
|
||||
DWORD scriptIndex = opHandler.arg(0).asInt(),
|
||||
tile = opHandler.arg(1).asInt(),
|
||||
elevation = opHandler.arg(2).asInt(),
|
||||
radius = opHandler.arg(3).asInt(),
|
||||
scriptId, tmp, objectPtr,
|
||||
scriptPtr;
|
||||
__asm {
|
||||
@@ -151,7 +151,7 @@ static void _stdcall op_create_spatial2() {
|
||||
call scr_find_obj_from_program_;
|
||||
mov objectPtr, eax;
|
||||
}
|
||||
SetOpReturn((int)objectPtr);
|
||||
opHandler.setReturn((int)objectPtr);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_create_spatial() {
|
||||
@@ -159,10 +159,10 @@ static void __declspec(naked) op_create_spatial() {
|
||||
}
|
||||
|
||||
static void sf_spatial_radius() {
|
||||
TGameObj* spatialObj = GetOpArgObj(1);
|
||||
TGameObj* spatialObj = opHandler.arg(1).asObject();
|
||||
TScript* script;
|
||||
if (ScrPtr(spatialObj->scriptID, &script) != -1) {
|
||||
SetOpReturn(script->spatial_radius);
|
||||
opHandler.setReturn(script->spatial_radius);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,13 +376,13 @@ static DWORD getBlockingFunc(DWORD type) {
|
||||
}
|
||||
|
||||
static void _stdcall op_make_straight_path2() {
|
||||
DWORD objFrom = GetOpArgInt(0),
|
||||
tileTo = GetOpArgInt(1),
|
||||
type = GetOpArgInt(2),
|
||||
DWORD objFrom = opHandler.arg(0).asInt(),
|
||||
tileTo = opHandler.arg(1).asInt(),
|
||||
type = opHandler.arg(2).asInt(),
|
||||
resultObj, arg6;
|
||||
arg6 = (type == BLOCKING_TYPE_SHOOT) ? 32 : 0;
|
||||
make_straight_path_func_wrapper(objFrom, *(DWORD*)(objFrom + 4), 0, tileTo, &resultObj, arg6, getBlockingFunc(type));
|
||||
SetOpReturn(resultObj, DATATYPE_INT);
|
||||
opHandler.setReturn(resultObj, DATATYPE_INT);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_make_straight_path() {
|
||||
@@ -390,15 +390,15 @@ static void __declspec(naked) op_make_straight_path() {
|
||||
}
|
||||
|
||||
static void _stdcall op_make_path2() {
|
||||
DWORD objFrom = GetOpArgInt(0),
|
||||
DWORD objFrom = opHandler.arg(0).asInt(),
|
||||
tileFrom = 0,
|
||||
tileTo = GetOpArgInt(1),
|
||||
type = GetOpArgInt(2),
|
||||
tileTo = opHandler.arg(1).asInt(),
|
||||
type = opHandler.arg(2).asInt(),
|
||||
func = getBlockingFunc(type),
|
||||
arr;
|
||||
long pathLength, a5 = 1;
|
||||
if (!objFrom) {
|
||||
SetOpReturn(0, DATATYPE_INT);
|
||||
opHandler.setReturn(0, DATATYPE_INT);
|
||||
return;
|
||||
}
|
||||
tileFrom = *(DWORD*)(objFrom + 4);
|
||||
@@ -418,7 +418,7 @@ static void _stdcall op_make_path2() {
|
||||
for (int i=0; i < pathLength; i++) {
|
||||
arrays[arr].val[i].set((long)pathData[i]);
|
||||
}
|
||||
SetOpReturn(arr, DATATYPE_INT);
|
||||
opHandler.setReturn(arr, DATATYPE_INT);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_make_path() {
|
||||
@@ -426,16 +426,16 @@ static void __declspec(naked) op_make_path() {
|
||||
}
|
||||
|
||||
static void _stdcall op_obj_blocking_at2() {
|
||||
DWORD tile = GetOpArgInt(0),
|
||||
elevation = GetOpArgInt(1),
|
||||
type = GetOpArgInt(2),
|
||||
DWORD tile = opHandler.arg(0).asInt(),
|
||||
elevation = opHandler.arg(1).asInt(),
|
||||
type = opHandler.arg(2).asInt(),
|
||||
resultObj;
|
||||
resultObj = obj_blocking_at_wrapper(0, tile, elevation, getBlockingFunc(type));
|
||||
if (resultObj && type == BLOCKING_TYPE_SHOOT && (*(DWORD*)(resultObj + 39) & 0x80)) { // don't know what this flag means, copy-pasted from the engine code
|
||||
// this check was added because the engine always does exactly this when using shoot blocking checks
|
||||
resultObj = 0;
|
||||
}
|
||||
SetOpReturn(resultObj, DATATYPE_INT);
|
||||
opHandler.setReturn(resultObj, DATATYPE_INT);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_obj_blocking_at() {
|
||||
@@ -443,8 +443,8 @@ static void __declspec(naked) op_obj_blocking_at() {
|
||||
}
|
||||
|
||||
static void _stdcall op_tile_get_objects2() {
|
||||
DWORD tile = GetOpArgInt(0),
|
||||
elevation = GetOpArgInt(1),
|
||||
DWORD tile = opHandler.arg(0).asInt(),
|
||||
elevation = opHandler.arg(1).asInt(),
|
||||
obj;
|
||||
DWORD arrayId = TempArray(0, 4);
|
||||
__asm {
|
||||
@@ -460,7 +460,7 @@ static void _stdcall op_tile_get_objects2() {
|
||||
mov obj, eax;
|
||||
}
|
||||
}
|
||||
SetOpReturn(arrayId, DATATYPE_INT);
|
||||
opHandler.setReturn(arrayId, DATATYPE_INT);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_tile_get_objects() {
|
||||
@@ -468,7 +468,7 @@ static void __declspec(naked) op_tile_get_objects() {
|
||||
}
|
||||
|
||||
static void _stdcall op_get_party_members2() {
|
||||
DWORD obj, mode = GetOpArgInt(0), isDead;
|
||||
DWORD obj, mode = opHandler.arg(0).asInt(), isDead;
|
||||
int i, actualCount = *(DWORD*)_partyMemberCount;
|
||||
DWORD arrayId = TempArray(0, 4);
|
||||
DWORD* partyMemberList = *(DWORD**)_partyMemberList;
|
||||
@@ -489,7 +489,7 @@ static void _stdcall op_get_party_members2() {
|
||||
}
|
||||
arrays[arrayId].push_back((long)obj);
|
||||
}
|
||||
SetOpReturn(arrayId, DATATYPE_INT);
|
||||
opHandler.setReturn(arrayId, DATATYPE_INT);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_get_party_members() {
|
||||
@@ -512,11 +512,14 @@ end:
|
||||
}
|
||||
|
||||
static void _stdcall op_obj_is_carrying_obj2() {
|
||||
DWORD num = 0;
|
||||
if (IsOpArgInt(0) && IsOpArgInt(1)) {
|
||||
TGameObj *invenObj = (TGameObj*)GetOpArgInt(0),
|
||||
*itemObj = (TGameObj*)GetOpArgInt(1);
|
||||
if (invenObj && itemObj) {
|
||||
int num = 0;
|
||||
const ScriptValue &invenObjArg = opHandler.arg(0),
|
||||
&itemObjArg = opHandler.arg(1);
|
||||
|
||||
if (invenObjArg.isInt() && itemObjArg.isInt()) {
|
||||
TGameObj *invenObj = (TGameObj*)invenObjArg.asObject(),
|
||||
*itemObj = (TGameObj*)itemObjArg.asObject();
|
||||
if (invenObj != nullptr && itemObj != nullptr) {
|
||||
for (int i = 0; i < invenObj->invenCount; i++) {
|
||||
if (invenObj->invenTablePtr[i].object == itemObj) {
|
||||
num = invenObj->invenTablePtr[i].count;
|
||||
@@ -525,7 +528,7 @@ static void _stdcall op_obj_is_carrying_obj2() {
|
||||
}
|
||||
}
|
||||
}
|
||||
SetOpReturn(num, DATATYPE_INT);
|
||||
opHandler.setReturn(num);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_obj_is_carrying_obj() {
|
||||
@@ -533,20 +536,20 @@ static void __declspec(naked) op_obj_is_carrying_obj() {
|
||||
}
|
||||
|
||||
static void sf_critter_inven_obj2() {
|
||||
TGameObj* critter = GetOpArgObj(1);
|
||||
int slot = GetOpArgInt(2);
|
||||
TGameObj* critter = opHandler.arg(1).asObject();
|
||||
int slot = opHandler.arg(2).asInt();
|
||||
switch (slot) {
|
||||
case 0:
|
||||
SetOpReturn(InvenWorn(critter));
|
||||
opHandler.setReturn(InvenWorn(critter));
|
||||
break;
|
||||
case 1:
|
||||
SetOpReturn(InvenRightHand(critter));
|
||||
opHandler.setReturn(InvenRightHand(critter));
|
||||
break;
|
||||
case 2:
|
||||
SetOpReturn(InvenLeftHand(critter));
|
||||
opHandler.setReturn(InvenLeftHand(critter));
|
||||
break;
|
||||
case -2:
|
||||
SetOpReturn(critter->invenCount);
|
||||
opHandler.setReturn(critter->invenCount);
|
||||
break;
|
||||
default:
|
||||
PrintOpcodeError("critter_inven_obj2() - invalid type.");
|
||||
|
||||
@@ -770,21 +770,22 @@ end:
|
||||
}
|
||||
|
||||
static void funcPow2() {
|
||||
float base, result = 0.0;
|
||||
if (!IsOpArgStr(0) && !IsOpArgStr(1)) {
|
||||
base = GetOpArgFloat(0);
|
||||
if (IsOpArgFloat(1))
|
||||
result = pow(base, GetOpArgFloat(1));
|
||||
const ScriptValue &base = opHandler.arg(0),
|
||||
&power = opHandler.arg(1);
|
||||
float result = 0.0;
|
||||
if (!base.isString() && !power.isString()) {
|
||||
if (power.isFloat())
|
||||
result = pow(base.asFloat(), power.asFloat());
|
||||
else
|
||||
result = pow(base, GetOpArgInt(1));
|
||||
result = pow(base.asFloat(), power.asInt());
|
||||
|
||||
if (IsOpArgInt(0) && IsOpArgInt(1)) {
|
||||
SetOpReturn((DWORD)(int)result, DATATYPE_INT);
|
||||
if (base.isInt() && power.isInt()) {
|
||||
opHandler.setReturn(static_cast<int>(result));
|
||||
} else {
|
||||
SetOpReturn(result);
|
||||
opHandler.setReturn(result);
|
||||
}
|
||||
} else {
|
||||
SetOpReturn(0, DATATYPE_INT);
|
||||
opHandler.setReturn(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -793,7 +794,7 @@ static void __declspec(naked) funcPow() {
|
||||
}
|
||||
|
||||
static void funcLog2() {
|
||||
SetOpReturn(log(GetOpArgFloat(0)));
|
||||
opHandler.setReturn(log(opHandler.arg(0).asFloat()));
|
||||
}
|
||||
|
||||
static void __declspec(naked) funcLog() {
|
||||
@@ -801,7 +802,7 @@ static void __declspec(naked) funcLog() {
|
||||
}
|
||||
|
||||
static void funcExp2() {
|
||||
SetOpReturn(exp(GetOpArgFloat(0)));
|
||||
opHandler.setReturn(exp(opHandler.arg(0).asFloat()));
|
||||
}
|
||||
|
||||
static void __declspec(naked) funcExp() {
|
||||
@@ -809,7 +810,7 @@ static void __declspec(naked) funcExp() {
|
||||
}
|
||||
|
||||
static void funcCeil2() {
|
||||
SetOpReturn((int)ceil(GetOpArgFloat(0)), DATATYPE_INT);
|
||||
opHandler.setReturn(static_cast<int>(ceil(opHandler.arg(0).asFloat())));
|
||||
}
|
||||
|
||||
static void __declspec(naked) funcCeil() {
|
||||
@@ -817,12 +818,13 @@ static void __declspec(naked) funcCeil() {
|
||||
}
|
||||
|
||||
static void funcRound2() {
|
||||
float arg = GetOpArgFloat(0);
|
||||
int argI = (int)arg;
|
||||
float mod = arg - (float)argI;
|
||||
if (abs(mod) >= 0.5)
|
||||
float arg = opHandler.arg(0).asFloat();
|
||||
int argI = static_cast<int>(arg);
|
||||
float mod = arg - static_cast<float>(argI);
|
||||
if (abs(mod) >= 0.5) {
|
||||
argI += (mod > 0 ? 1 : -1);
|
||||
SetOpReturn(argI, DATATYPE_INT);
|
||||
}
|
||||
opHandler.setReturn(argI);
|
||||
}
|
||||
|
||||
static void __declspec(naked) funcRound() {
|
||||
@@ -833,6 +835,7 @@ static void __declspec(naked) funcRound() {
|
||||
|
||||
*/
|
||||
|
||||
// TODO: move to FalloutEngine module
|
||||
static const DWORD game_msg_files[] =
|
||||
{ 0x56D368 // COMBAT
|
||||
, 0x56D510 // AI
|
||||
@@ -855,14 +858,16 @@ static const DWORD game_msg_files[] =
|
||||
, 0x66BE38 // TRAIT
|
||||
, 0x672FB0 }; // WORLDMAP
|
||||
|
||||
// TODO: move to FalloutEngine
|
||||
static const DWORD* proto_msg_files = (DWORD*)0x006647AC;
|
||||
|
||||
static void _stdcall op_message_str_game2() {
|
||||
const char* msg = 0;
|
||||
|
||||
if (IsOpArgInt(0) && IsOpArgInt(1)) {
|
||||
int fileId = GetOpArgInt(0);
|
||||
int msgId = GetOpArgInt(1);
|
||||
const ScriptValue &fileIdArg = opHandler.arg(0),
|
||||
&msgIdArg = opHandler.arg(1);
|
||||
if (fileIdArg.isInt() && msgIdArg.isInt()) {
|
||||
int fileId = fileIdArg.asInt();
|
||||
int msgId = msgIdArg.asInt();
|
||||
if (fileId < 20) { // main msg files
|
||||
msg = GetMessageStr(game_msg_files[fileId], msgId);
|
||||
}
|
||||
@@ -877,11 +882,10 @@ static void _stdcall op_message_str_game2() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msg == 0)
|
||||
if (msg == 0) {
|
||||
msg = "Error";
|
||||
|
||||
SetOpReturn(msg);
|
||||
}
|
||||
opHandler.setReturn(msg);
|
||||
}
|
||||
|
||||
static void __declspec(naked) op_message_str_game() {
|
||||
|
||||
Reference in New Issue
Block a user