Added validation for null arguments #55;

Added scripting function "spatial_radius";
Added scripting function "critter_inven_obj2" #38.
This commit is contained in:
phobos2077
2016-11-04 17:22:05 +07:00
parent 1a40c40cd3
commit af4bad36d4
6 changed files with 111 additions and 17 deletions
+23
View File
@@ -725,6 +725,14 @@ void SkillSetTags(int* tags, DWORD num) {
}
}
int __stdcall ScrPtr(int scriptId, TScript** scriptPtr) {
__asm {
mov eax, scriptId;
mov edx, scriptPtr;
call scr_ptr_;
}
}
// redraws the main game interface windows (useful after changing some data like active hand, etc.)
void InterfaceRedraw() {
__asm {
@@ -800,4 +808,19 @@ const char* __stdcall FindCurrentProc(TProgram* program) {
mov eax, program
call findCurrentProc_
}
}
TGameObj* __stdcall InvenWorn(TGameObj* critter) {
__asm mov eax, critter
__asm call inven_worn_
}
TGameObj* __stdcall InvenLeftHand(TGameObj* critter) {
__asm mov eax, critter
__asm call inven_left_hand_
}
TGameObj* __stdcall InvenRightHand(TGameObj* critter) {
__asm mov eax, critter
__asm call inven_right_hand_
}
+14 -1
View File
@@ -854,6 +854,10 @@ void CritterPcSetName(const char* newName);
// Returns the name of the critter
const char* __stdcall CritterName(TGameObj* critter);
// Saves pointer to script object into scriptPtr using scriptID.
// Returns 0 on success, -1 on failure.
int __stdcall ScrPtr(int scriptId, TScript** scriptPtr);
void SkillGetTags(int* result, DWORD num);
void SkillSetTags(int* tags, DWORD num);
@@ -884,4 +888,13 @@ void __declspec() InterpretError(const char* fmt, ...);
void __declspec() DebugPrintf(const char* fmt, ...);
// returns the name of current procedure by program pointer
const char* __stdcall FindCurrentProc(TProgram* program);
const char* __stdcall FindCurrentProc(TProgram* program);
// critter worn item (armor)
TGameObj* __stdcall InvenWorn(TGameObj* critter);
// item in critter's left hand slot
TGameObj* __stdcall InvenLeftHand(TGameObj* critter);
// item in critter's right hand slot
TGameObj* __stdcall InvenRightHand(TGameObj* critter);
+2 -2
View File
@@ -34,7 +34,7 @@ struct TInvenRec
};
#pragma pack(pop)
/* 8 */
/* 15 */
#pragma pack(push, 1)
struct TGameObj
{
@@ -52,7 +52,7 @@ struct TGameObj
TInvenRec *invenTablePtr;
char gap_38[4];
int itemCharges;
int movePoints;
int critterAP_weaponAmmoPid;
char gap_44[16];
int lastTarget;
char gap_58[12];
+13
View File
@@ -47,6 +47,7 @@ typedef struct {
int i;
float f;
const char* str;
TGameObj* gObj;
} val;
DWORD type; // TODO: replace with enum class
} ScriptValue;
@@ -76,6 +77,12 @@ static void _stdcall SetOpReturn(const char* 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);
@@ -121,6 +128,12 @@ static const char* _stdcall GetOpArgStr(int num) {
: "";
}
static TGameObj* _stdcall GetOpArgObj(int num) {
return (opArgs[num].type == DATATYPE_INT)
? opArgs[num].val.gObj
: nullptr;
}
// writes error message to debug.log along with the name of script & procedure
static void _stdcall PrintOpcodeError(const char* fmt, ...) {
assert(opProgram != nullptr);
+29 -3
View File
@@ -48,6 +48,8 @@ struct SfallMetarule {
#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)
typedef std::tr1::unordered_map<std::string, const SfallMetarule*> MetaruleTableType;
@@ -93,10 +95,24 @@ static void sf_get_metarule_table() {
SetOpReturn(arr, DATATYPE_INT);
}
/*
Metarule array.
Add your custom scripting functions here.
Format is as follows:
{ name, handler, minArgs, maxArgs, {MASK1, MASK2, ...} }
- name - name of function that will be used to call it from scripts,
- handler - pointer to handler function (see examples above),
- minArgs/maxArgs - minimum and maximum number of arguments allowed for this function,
- MASK1, MASK2, ... - validation parameters for each argument as bit masks (see DATATYPE_MASK_* defines)
*/
static const SfallMetarule metaruleArray[] = {
{"test", sf_test, 0, 6, {}},
{"get_metarule_table", sf_get_metarule_table, 0, 0, {}},
{"validate_test", sf_test, 2, 5, {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}}
{"validate_test", sf_test, 2, 5, {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}},
{"spatial_radius", sf_spatial_radius, 1, 1, {DATATYPE_MASK_VALID_OBJ}},
{"critter_inven_obj2", sf_critter_inven_obj2, 2, 2, {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
};
static void InitMetaruleTable() {
@@ -121,12 +137,22 @@ static bool ValidateOpcodeArguments(const SfallMetarule* metaruleInfo) {
return false;
} else {
for (int i = 0; i < argCount; i++) {
if (metaruleInfo->argTypeMasks[i] != 0 && ((1 << opArgs[i + 1].type) & metaruleInfo->argTypeMasks[i]) == 0) {
int typeMask = metaruleInfo->argTypeMasks[i];
ScriptValue arg = opArgs[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(opArgs[i + 1].type));
GetSfallTypeName(arg.type));
return false;
} else if ((typeMask & DATATYPE_MASK_NOT_NULL) && arg.val.dw == 0) {
PrintOpcodeError(
"sfall_funcX(\"%s\", ...) - argument #%d is null.",
metaruleInfo->name,
i + 1);
return false;
}
}
+30 -11
View File
@@ -24,6 +24,7 @@
//script control functions
// TODO: rewrite
static void __declspec(naked) RemoveScript() {
__asm {
push ebx;
@@ -52,6 +53,7 @@ end:
}
}
// TODO: rewrite
static void __declspec(naked) SetScript() {
__asm {
pushad;
@@ -111,6 +113,7 @@ end:
}
}
// TODO: rewrite, remove all ASM
static void _stdcall op_create_spatial2() {
DWORD scriptIndex = GetOpArgInt(0),
tile = GetOpArgInt(1),
@@ -154,18 +157,13 @@ static void _stdcall op_create_spatial2() {
static void __declspec(naked) op_create_spatial() {
_WRAP_OPCODE(op_create_spatial2, 4, 1)
}
static void __declspec(naked) op_spatial_radius() {
_OP_BEGIN(ebp)
_GET_ARG_R32(ebp, ecx, eax)
_CHECK_ARG_INT(cx, fail)
__asm {
test eax, eax;
js fail;
mov eax, [eax+0xC];
fail:
static void sf_spatial_radius() {
TGameObj* spatialObj = GetOpArgObj(1);
TScript* script;
if (ScrPtr(spatialObj->scriptID, &script) != -1) {
SetOpReturn(script->spatial_radius);
}
_RET_VAL_INT(ebp)
_OP_END
}
static void __declspec(naked) GetScript() {
@@ -533,3 +531,24 @@ static void _stdcall op_obj_is_carrying_obj2() {
static void __declspec(naked) op_obj_is_carrying_obj() {
_WRAP_OPCODE(op_obj_is_carrying_obj2, 2, 1)
}
static void sf_critter_inven_obj2() {
TGameObj* critter = GetOpArgObj(1);
int slot = GetOpArgInt(2);
switch (slot) {
case 0:
SetOpReturn(InvenWorn(critter));
break;
case 1:
SetOpReturn(InvenRightHand(critter));
break;
case 2:
SetOpReturn(InvenLeftHand(critter));
break;
case -2:
SetOpReturn(critter->invenCount);
break;
default:
PrintOpcodeError("critter_inven_obj2() - invalid type.");
}
}