Rewrote some script functions in ObjectsOps in C++

* remove_script, set/get_script, set_critter_burst_disable.

Changed the return value of get_script to 0 for unscripted objects.
This commit is contained in:
NovaRain
2019-12-09 11:07:40 +08:00
parent cbc822c9e0
commit b4dac84ddd
8 changed files with 145 additions and 183 deletions
+3 -2
View File
@@ -153,12 +153,13 @@ array - array ID to be used with array-related functions (actually an integer)
- accepts a pointer to an object and will remove the script from that object.
> void set_script(object, int scriptid)
- accepts a pointer to an object and scriptID, and applies the given script to an object (scriptID accept the same values as create_object_sid from sfall 3.6)
- accepts a pointer to an object and scriptID, and applies the given script to an object (scriptID accepts the same values as create_object_sid)
- If used on an object that is already scripted, it will remove the existing script first; you cannot have multiple scripts attached to a single object. Calling set_script on self_obj will have all sorts of wacky side effects, and should be avoided.
- if you add 0x80000000 to the sid when calling set_script, map_enter_p_proc will be SKIPPED. The start proc will always be run.
> int get_script(object)
- accepts a pointer to an object and returns its scriptID (line number in scripts.lst), or -1 if the object is unscripted.
- accepts a pointer to an object and returns its scriptID (line number in scripts.lst), or 0 if the object is unscripted.
- returns -1 on argument error.
> void set_self(int obj)
- overrides the scripts self_obj for the next function call.
+2 -2
View File
@@ -243,7 +243,7 @@ static void __declspec(naked) determine_to_hit_func_hack() {
}
static long __fastcall CheckDisableBurst(TGameObj* critter) {
for (DWORD i = 0; i < noBursts.size(); i++) {
for (size_t i = 0; i < noBursts.size(); i++) {
if (noBursts[i] == critter->ID) {
return 10; // Disable Burst (area_attack_mode - non-existent value)
}
@@ -354,7 +354,7 @@ void _stdcall SetHitChanceMax(TGameObj* critter, DWORD maximum, DWORD mod) {
hitChanceMods.push_back(cm);
}
void _stdcall SetNoBurstMode(TGameObj* critter, DWORD on) {
void _stdcall SetNoBurstMode(TGameObj* critter, bool on) {
if (critter == *ptr_obj_dude || critter->pid >> 24 != OBJ_TYPE_CRITTER) return;
long id = SetObjectUniqueID(critter);
+1 -1
View File
@@ -29,6 +29,6 @@ void _stdcall KnockbackSetMod(TGameObj* object, DWORD type, float val, DWORD mod
void _stdcall KnockbackRemoveMod(TGameObj* object, DWORD mode);
void CombatInit();
void Combat_OnGameLoad();
void _stdcall SetNoBurstMode(TGameObj* critter, DWORD on);
void _stdcall SetNoBurstMode(TGameObj* critter, bool on);
void _stdcall DisableAimedShots(DWORD pid);
void _stdcall ForceAimedShots(DWORD pid);
+33 -3
View File
@@ -873,16 +873,38 @@ void SkillSetTags(int* tags, DWORD num) {
}
}
TGameObj* __stdcall ScrFindObjFromProgram(TProgram* program) {
__asm {
mov eax, program;
call scr_find_obj_from_program_;
}
}
// Saves pointer to script object into scriptPtr using scriptID.
// Returns 0 on success, -1 on failure.
long __stdcall ScrPtr(long scriptId, TScript** scriptPtr) {
__asm {
mov eax, scriptId;
mov edx, scriptPtr;
mov eax, scriptId;
call scr_ptr_;
}
}
long __stdcall ScrNew(long* scriptID, long sType) {
__asm {
mov edx, sType;
mov eax, scriptID;
call scr_new_;
}
}
long __stdcall ScrRemove(long scriptID) {
__asm {
mov eax, scriptID;
call scr_remove_;
}
}
// Returns the number of local variables of the object script
long GetScriptLocalVars(long sid) {
TScript* script = nullptr;
@@ -1037,10 +1059,10 @@ TGameObj* __stdcall InvenRightHand(TGameObj* critter) {
}
}
long __fastcall CreateWindowFunc(const char* winName, long x, long y, long width, long height, long bgColorIndex, long flags) {
long __fastcall CreateWindowFunc(const char* winName, DWORD x, DWORD y, DWORD width, DWORD height, long color, long flags) {
__asm {
push flags;
push bgColorIndex;
push color;
push height;
mov eax, ecx;
mov ebx, y;
@@ -1300,6 +1322,14 @@ TGameObj* __fastcall ObjBlockingAt(TGameObj* object, long tile, long elevation)
}
}
long __fastcall ObjNewSidInst(TGameObj* object, long sType, long scriptIndex) {
__asm {
mov ebx, scriptIndex;
mov eax, ecx;
call obj_new_sid_inst_;
}
}
long __fastcall TileNumInDirection(long tile, long rotation, long distance) {
__asm {
mov ebx, distance;
+9 -1
View File
@@ -1042,10 +1042,16 @@ void __stdcall CritterPcSetName(const char* newName);
// Checks if given file exists in DB
bool __stdcall DbAccess(const char* fileName);
TGameObj* __stdcall ScrFindObjFromProgram(TProgram* program);
// Saves pointer to script object into scriptPtr using scriptID.
// Returns 0 on success, -1 on failure.
long __stdcall ScrPtr(long scriptId, TScript** scriptPtr);
long __stdcall ScrNew(long* scriptID, long sType);
long __stdcall ScrRemove(long scriptID);
// Returns the number of local variables of the object script
long GetScriptLocalVars(long sid);
@@ -1099,7 +1105,7 @@ void __declspec() InterpretError(const char* fmt, ...);
const char* __stdcall FindCurrentProc(TProgram* program);
// creates a window with the name and flags
long __fastcall CreateWindowFunc(const char* winName, long x, long y, long width, long height, long bgColorIndex, long flags);
long __fastcall CreateWindowFunc(const char* winName, DWORD x, DWORD y, DWORD width, DWORD height, long color, long flags);
// creates a button
long __stdcall WinRegisterButton(DWORD winRef, long xPos, long yPos, long width, long height, long hoverOn, long hoverOff, long buttonDown, long buttonUp, BYTE* pictureUp, BYTE* pictureDown, long arg12, long buttonType);
@@ -1156,6 +1162,8 @@ void __stdcall MapDirErase(const char* folder, const char* ext);
TGameObj* __fastcall ObjBlockingAt(TGameObj* object, long tile, long elevation);
long __fastcall ObjNewSidInst(TGameObj* object, long sType, long scriptIndex);
long __fastcall TileNumInDirection(long tile, long rotation, long distance);
long __stdcall TileDir(long scrTile, long dstTile);
+2 -2
View File
@@ -128,7 +128,7 @@ struct TScript {
};
#pragma pack(pop)
enum ScriptTypes
enum ScriptTypes : long
{
SCRIPT_SYSTEM = 0,
SCRIPT_SPATIAL = 1,
@@ -138,7 +138,7 @@ enum ScriptTypes
};
/* 24 */
enum ObjectTypes
enum ObjectTypes : char
{
OBJ_TYPE_ITEM = 0,
OBJ_TYPE_CRITTER = 1,
+94 -167
View File
@@ -24,97 +24,66 @@
#include "Objects.h"
#include "PartyControl.h"
//script control functions
#define exec_script_proc(script, proc) __asm { \
__asm mov eax, script \
__asm mov edx, proc \
__asm call exec_script_proc_ \
}
// TODO: rewrite
static void __declspec(naked) RemoveScript() {
__asm {
push ebx;
push ecx;
push edx;
mov ecx, eax;
call interpretPopShort_;
mov edx, eax;
mov eax, ecx;
call interpretPopLong_;
cmp dx, VAR_TYPE_INT;
jnz end;
test eax, eax;
jz end;
mov edx, eax;
mov eax, [eax+0x78];
cmp eax, 0xffffffff;
jz end;
call scr_remove_
mov dword ptr [edx+0x78], 0xffffffff;
end:
pop edx;
pop ecx;
pop ebx;
retn;
static void _stdcall RemoveScript2() {
TGameObj* object = opHandler.arg(0).asObject();
if (object) {
if (object->scriptID != 0xFFFFFFFF) {
ScrRemove(object->scriptID);
object->scriptID = 0xFFFFFFFF;
}
} else {
OpcodeInvalidArgs("remove_script");
}
}
// TODO: rewrite
static void __declspec(naked) SetScript() {
__asm {
pushad;
mov ecx, eax;
call interpretPopShort_;
mov edx, eax;
mov eax, ecx;
call interpretPopLong_;
mov ebx, eax;
mov eax, ecx;
call interpretPopShort_;
mov edi, eax;
mov eax, ecx;
call interpretPopLong_;
cmp dx, VAR_TYPE_INT;
jnz end;
cmp di, VAR_TYPE_INT;
jnz end;
test eax, eax;
jz end;
mov esi, [eax+0x78];
cmp esi, 0xffffffff;
jz newscript
push eax;
mov eax, esi;
call scr_remove_
pop eax;
mov dword ptr [eax+0x78], 0xffffffff;
newscript:
mov esi, 1;
test ebx, 0x80000000;
jz execMapEnter;
xor esi, esi;
xor ebx, 0x80000000;
execMapEnter:
mov ecx, eax;
mov edx, 3; // script_type_item
mov edi, [eax+0x64];
shr edi, 24;
cmp edi, 1;
jnz notCritter;
inc edx; // 4 - "critter" type script
notCritter:
dec ebx;
call obj_new_sid_inst_
mov eax, [ecx+0x78];
mov edx, 1; // start
call exec_script_proc_
cmp esi, 1; // run map enter?
jnz end;
mov eax, [ecx+0x78];
mov edx, 0xf; // map_enter_p_proc
call exec_script_proc_
end:
popad;
retn;
static void __declspec(naked) RemoveScript() {
_WRAP_OPCODE(RemoveScript2, 1, 0)
}
static void _stdcall SetScript2() {
TGameObj* object = opHandler.arg(0).asObject();
const ScriptValue &scriptIdxArg = opHandler.arg(1);
if (object && scriptIdxArg.isInt()) {
long scriptType;
unsigned long valArg = scriptIdxArg.rawValue();
long scriptIndex = valArg & ~0xF0000000;
if (scriptIndex == 0 || valArg > 0x8FFFFFFF) { // negative values are not allowed
opHandler.printOpcodeError("set_script() - the script index number is incorrect.");
return;
}
scriptIndex--;
if (object->scriptID != 0xFFFFFFFF) {
ScrRemove(object->scriptID);
object->scriptID = 0xFFFFFFFF;
}
if (object->pid >> 24 == OBJ_TYPE_CRITTER) {
scriptType = SCRIPT_CRITTER;
} else {
scriptType = SCRIPT_ITEM;
}
ObjNewSidInst(object, scriptType, scriptIndex);
long scriptId = object->scriptID;
exec_script_proc(scriptId, start);
if ((valArg & 0x80000000) == 0) exec_script_proc(scriptId, map_enter_p_proc);
} else {
OpcodeInvalidArgs("set_script");
}
}
static void __declspec(naked) SetScript() {
_WRAP_OPCODE(SetScript2, 2, 0)
}
static void _stdcall op_create_spatial2() {
const ScriptValue &scriptIdxArg = opHandler.arg(0),
&tileArg = opHandler.arg(1),
@@ -125,38 +94,21 @@ static void _stdcall op_create_spatial2() {
DWORD scriptIndex = scriptIdxArg.rawValue(),
tile = tileArg.rawValue(),
elevation = elevArg.rawValue(),
radius = radiusArg.rawValue(),
scriptId, tmp, objectPtr,
scriptPtr;
__asm {
lea eax, scriptId;
mov edx, 1;
call scr_new_;
mov tmp, eax;
}
if (tmp == -1) return;
__asm {
mov eax, scriptId;
lea edx, scriptPtr;
call scr_ptr_;
mov tmp, eax;
}
if (tmp == -1) return;
// fill spatial script properties:
*(DWORD*)(scriptPtr + 0x14) = scriptIndex - 1;
*(DWORD*)(scriptPtr + 0x8) = (elevation << 29) & 0xE0000000 | tile;
*(DWORD*)(scriptPtr + 0xC) = radius;
radius = radiusArg.rawValue();
long scriptId;
TScript* scriptPtr;
if (ScrNew(&scriptId, SCRIPT_SPATIAL) == -1 || ScrPtr(scriptId, &scriptPtr) == -1) return;
// set spatial script properties:
scriptPtr->script_index = scriptIndex - 1;
scriptPtr->elevation_and_tile = (elevation << 29) & 0xE0000000 | tile;
scriptPtr->spatial_radius = radius;
// this will load appropriate script program and link it to the script instance we just created:
__asm {
mov eax, scriptId;
mov edx, 1; // start_p_proc
call exec_script_proc_;
mov eax, scriptPtr;
mov eax, [eax + 0x18]; // program pointer
call scr_find_obj_from_program_;
mov objectPtr, eax;
}
opHandler.setReturn(objectPtr);
exec_script_proc(scriptId, start);
opHandler.setReturn(ScrFindObjFromProgram(scriptPtr->program_ptr));
} else {
OpcodeInvalidArgs("create_spatial");
opHandler.setReturn(0);
@@ -180,64 +132,36 @@ static void sf_spatial_radius() {
}
}
static void _stdcall GetScript2() {
TGameObj* object = opHandler.arg(0).asObject();
if (object) {
long scriptIndex = object->script_index;
opHandler.setReturn((scriptIndex >= 0) ? ++scriptIndex : 0);
} else {
OpcodeInvalidArgs("get_script");
opHandler.setReturn(-1);
}
}
static void __declspec(naked) GetScript() {
__asm {
pushad;
mov ecx, eax;
mov ecx, eax;
call interpretPopShort_;
mov edx, eax;
mov eax, ecx;
call interpretPopLong_;
cmp dx, VAR_TYPE_INT;
jnz fail;
test eax, eax;
jz fail;
mov edx, [eax+0x80];
cmp edx, -1;
jz fail;
inc edx;
jmp end;
fail:
xor edx, edx;
dec edx;
end:
mov eax, ecx;
call interpretPushLong_;
mov eax, ecx;
mov edx, VAR_TYPE_INT;
call interpretPushShort_;
popad;
retn;
_WRAP_OPCODE(GetScript2, 1, 1)
}
static void _stdcall set_critter_burst_disable2() {
TGameObj* critter = opHandler.arg(0).asObject();
const ScriptValue &disableArg = opHandler.arg(1);
if (critter && disableArg.isInt()) {
SetNoBurstMode(critter, disableArg.asBool());
} else {
OpcodeInvalidArgs("set_critter_burst_disable");
}
}
static void __declspec(naked) set_critter_burst_disable() {
__asm {
pushad;
mov ebp, eax;
call interpretPopShort_;
mov edi, eax;
mov eax, ebp;
call interpretPopLong_;
mov ecx, eax;
mov eax, ebp;
call interpretPopShort_;
mov esi, eax;
mov eax, ebp;
call interpretPopLong_;
cmp di, VAR_TYPE_INT;
jnz end;
cmp si, VAR_TYPE_INT;
jnz end;
push ecx;
push eax;
call SetNoBurstMode;
end:
popad;
retn;
}
_WRAP_OPCODE(set_critter_burst_disable2, 2, 0)
}
static void __declspec(naked) get_weapon_ammo_pid() {
__asm {
pushad;
@@ -265,6 +189,7 @@ end:
retn;
}
}
static void __declspec(naked) set_weapon_ammo_pid() {
__asm {
pushad;
@@ -291,6 +216,7 @@ end:
retn;
}
}
static void __declspec(naked) get_weapon_ammo_count() {
__asm {
pushad;
@@ -317,6 +243,7 @@ end:
retn;
}
}
static void __declspec(naked) set_weapon_ammo_count() {
__asm {
pushad;
+1 -5
View File
@@ -529,11 +529,7 @@ static void FillListVector(DWORD type, std::vector<TGameObj*>& vec) {
self_obj = scriptPtr->self_obj;
if (self_obj == nullptr) {
programPtr = scriptPtr->program_ptr;
__asm {
mov eax, programPtr;
call scr_find_obj_from_program_;
mov self_obj, eax;
}
self_obj = ScrFindObjFromProgram(programPtr);
}
vec.push_back(self_obj);
__asm {