2015-06-30 00:07:12 +07:00
|
|
|
/*
|
|
|
|
|
* sfall
|
|
|
|
|
* Copyright (C) 2008, 2009, 2010, 2012 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 "main.h"
|
2019-01-08 13:28:00 +08:00
|
|
|
|
2015-06-30 00:07:12 +07:00
|
|
|
#include "Inventory.h"
|
2019-10-07 09:36:46 +08:00
|
|
|
#include "Objects.h"
|
2019-05-22 12:59:27 +08:00
|
|
|
#include "PartyControl.h"
|
2015-06-30 00:07:12 +07:00
|
|
|
|
|
|
|
|
//script control functions
|
|
|
|
|
|
2016-11-04 17:22:05 +07:00
|
|
|
// TODO: rewrite
|
2015-06-30 00:07:12 +07:00
|
|
|
static void __declspec(naked) RemoveScript() {
|
|
|
|
|
__asm {
|
|
|
|
|
push ebx;
|
|
|
|
|
push ecx;
|
|
|
|
|
push edx;
|
|
|
|
|
mov ecx, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edx, eax;
|
|
|
|
|
mov eax, ecx;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp dx, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz end;
|
|
|
|
|
mov edx, eax;
|
|
|
|
|
mov eax, [eax+0x78];
|
|
|
|
|
cmp eax, 0xffffffff;
|
|
|
|
|
jz end;
|
2015-07-16 00:37:05 +07:00
|
|
|
call scr_remove_
|
2015-06-30 00:07:12 +07:00
|
|
|
mov dword ptr [edx+0x78], 0xffffffff;
|
|
|
|
|
end:
|
|
|
|
|
pop edx;
|
|
|
|
|
pop ecx;
|
|
|
|
|
pop ebx;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-08 13:28:00 +08:00
|
|
|
// TODO: rewrite
|
2015-06-30 00:07:12 +07:00
|
|
|
static void __declspec(naked) SetScript() {
|
|
|
|
|
__asm {
|
|
|
|
|
pushad;
|
|
|
|
|
mov ecx, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edx, eax;
|
|
|
|
|
mov eax, ecx;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov ebx, eax;
|
|
|
|
|
mov eax, ecx;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edi, eax;
|
|
|
|
|
mov eax, ecx;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp dx, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp di, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz end;
|
|
|
|
|
mov esi, [eax+0x78];
|
|
|
|
|
cmp esi, 0xffffffff;
|
|
|
|
|
jz newscript
|
|
|
|
|
push eax;
|
|
|
|
|
mov eax, esi;
|
2015-07-16 00:37:05 +07:00
|
|
|
call scr_remove_
|
2015-06-30 00:07:12 +07:00
|
|
|
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;
|
2015-07-16 00:37:05 +07:00
|
|
|
call obj_new_sid_inst_
|
2015-06-30 00:07:12 +07:00
|
|
|
mov eax, [ecx+0x78];
|
|
|
|
|
mov edx, 1; // start
|
2015-07-16 00:37:05 +07:00
|
|
|
call exec_script_proc_
|
2015-06-30 00:07:12 +07:00
|
|
|
cmp esi, 1; // run map enter?
|
|
|
|
|
jnz end;
|
|
|
|
|
mov eax, [ecx+0x78];
|
|
|
|
|
mov edx, 0xf; // map_enter_p_proc
|
2015-07-16 00:37:05 +07:00
|
|
|
call exec_script_proc_
|
2015-06-30 00:07:12 +07:00
|
|
|
end:
|
|
|
|
|
popad;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall op_create_spatial2() {
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &scriptIdxArg = opHandler.arg(0),
|
|
|
|
|
&tileArg = opHandler.arg(1),
|
|
|
|
|
&elevArg = opHandler.arg(2),
|
|
|
|
|
&radiusArg = opHandler.arg(3);
|
|
|
|
|
|
|
|
|
|
if (scriptIdxArg.isInt() && tileArg.isInt() && elevArg.isInt() && radiusArg.isInt()) {
|
2019-11-28 14:42:07 +08:00
|
|
|
DWORD scriptIndex = scriptIdxArg.rawValue(),
|
|
|
|
|
tile = tileArg.rawValue(),
|
|
|
|
|
elevation = elevArg.rawValue(),
|
|
|
|
|
radius = radiusArg.rawValue(),
|
2019-11-28 10:24:40 +08:00
|
|
|
scriptId, tmp, objectPtr,
|
|
|
|
|
scriptPtr;
|
|
|
|
|
__asm {
|
|
|
|
|
lea eax, scriptId;
|
|
|
|
|
mov edx, 1;
|
|
|
|
|
call scr_new_;
|
|
|
|
|
mov tmp, eax;
|
|
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
if (tmp == -1) return;
|
2019-11-28 10:24:40 +08:00
|
|
|
__asm {
|
|
|
|
|
mov eax, scriptId;
|
|
|
|
|
lea edx, scriptPtr;
|
|
|
|
|
call scr_ptr_;
|
|
|
|
|
mov tmp, eax;
|
|
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
if (tmp == -1) return;
|
2019-11-28 10:24:40 +08:00
|
|
|
// fill spatial script properties:
|
|
|
|
|
*(DWORD*)(scriptPtr + 0x14) = scriptIndex - 1;
|
|
|
|
|
*(DWORD*)(scriptPtr + 0x8) = (elevation << 29) & 0xE0000000 | tile;
|
|
|
|
|
*(DWORD*)(scriptPtr + 0xC) = 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;
|
|
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(objectPtr);
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("create_spatial");
|
|
|
|
|
opHandler.setReturn(0);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_create_spatial() {
|
2016-11-03 20:55:59 +07:00
|
|
|
_WRAP_OPCODE(op_create_spatial2, 4, 1)
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
2016-11-04 17:22:05 +07:00
|
|
|
|
|
|
|
|
static void sf_spatial_radius() {
|
2016-11-06 17:37:25 +07:00
|
|
|
TGameObj* spatialObj = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
if (spatialObj) {
|
|
|
|
|
TScript* script;
|
|
|
|
|
if (ScrPtr(spatialObj->scriptID, &script) != -1) {
|
|
|
|
|
opHandler.setReturn(script->spatial_radius);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("spatial_radius");
|
|
|
|
|
opHandler.setReturn(0);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) GetScript() {
|
|
|
|
|
__asm {
|
|
|
|
|
pushad;
|
|
|
|
|
mov ecx, eax;
|
|
|
|
|
mov ecx, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edx, eax;
|
|
|
|
|
mov eax, ecx;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp dx, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
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;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPushLong_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov eax, ecx;
|
2017-12-03 23:29:28 +08:00
|
|
|
mov edx, VAR_TYPE_INT;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPushShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
popad;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) set_critter_burst_disable() {
|
|
|
|
|
__asm {
|
|
|
|
|
pushad;
|
|
|
|
|
mov ebp, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov ecx, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov esi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp di, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp si, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
|
|
|
|
push ecx;
|
|
|
|
|
push eax;
|
|
|
|
|
call SetNoBurstMode;
|
|
|
|
|
end:
|
|
|
|
|
popad;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static void __declspec(naked) get_weapon_ammo_pid() {
|
|
|
|
|
__asm {
|
|
|
|
|
pushad;
|
|
|
|
|
mov ebp, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp di, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz fail;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz fail;
|
|
|
|
|
mov edx, [eax+0x40];
|
|
|
|
|
jmp end;
|
|
|
|
|
fail:
|
|
|
|
|
xor edx, edx;
|
|
|
|
|
dec edx;
|
|
|
|
|
end:
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPushLong_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov eax, ebp;
|
2017-12-03 23:29:28 +08:00
|
|
|
mov edx, VAR_TYPE_INT;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPushShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
popad;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static void __declspec(naked) set_weapon_ammo_pid() {
|
|
|
|
|
__asm {
|
|
|
|
|
pushad;
|
|
|
|
|
mov ebp, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov ecx, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov esi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp di, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp si, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz end;
|
|
|
|
|
mov [eax+0x40], ecx;
|
|
|
|
|
end:
|
|
|
|
|
popad;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static void __declspec(naked) get_weapon_ammo_count() {
|
|
|
|
|
__asm {
|
|
|
|
|
pushad;
|
|
|
|
|
mov ebp, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp di, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz fail;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz fail;
|
|
|
|
|
mov edx, [eax+0x3c];
|
|
|
|
|
jmp end;
|
|
|
|
|
fail:
|
|
|
|
|
xor edx, edx;
|
|
|
|
|
end:
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPushLong_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov eax, ebp;
|
2017-12-03 23:29:28 +08:00
|
|
|
mov edx, VAR_TYPE_INT;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPushShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
popad;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static void __declspec(naked) set_weapon_ammo_count() {
|
|
|
|
|
__asm {
|
|
|
|
|
pushad;
|
|
|
|
|
mov ebp, eax;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov edi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov ecx, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopShort_;
|
2015-06-30 00:07:12 +07:00
|
|
|
mov esi, eax;
|
|
|
|
|
mov eax, ebp;
|
2015-11-16 10:40:26 +08:00
|
|
|
call interpretPopLong_;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp di, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
2017-12-03 23:29:28 +08:00
|
|
|
cmp si, VAR_TYPE_INT;
|
2015-06-30 00:07:12 +07:00
|
|
|
jnz end;
|
|
|
|
|
test eax, eax;
|
|
|
|
|
jz end;
|
|
|
|
|
mov [eax+0x3c], ecx;
|
|
|
|
|
end:
|
|
|
|
|
popad;
|
|
|
|
|
retn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define BLOCKING_TYPE_BLOCK (0)
|
|
|
|
|
#define BLOCKING_TYPE_SHOOT (1)
|
|
|
|
|
#define BLOCKING_TYPE_AI (2)
|
|
|
|
|
#define BLOCKING_TYPE_SIGHT (3)
|
|
|
|
|
#define BLOCKING_TYPE_SCROLL (4)
|
|
|
|
|
|
|
|
|
|
static DWORD getBlockingFunc(DWORD type) {
|
|
|
|
|
switch (type) {
|
2019-01-08 13:28:00 +08:00
|
|
|
case BLOCKING_TYPE_BLOCK: default:
|
2015-06-30 00:07:12 +07:00
|
|
|
return obj_blocking_at_;
|
2019-01-08 13:28:00 +08:00
|
|
|
case BLOCKING_TYPE_SHOOT:
|
2015-06-30 00:07:12 +07:00
|
|
|
return obj_shoot_blocking_at_;
|
2019-01-08 13:28:00 +08:00
|
|
|
case BLOCKING_TYPE_AI:
|
2015-06-30 00:07:12 +07:00
|
|
|
return obj_ai_blocking_at_;
|
2019-01-08 13:28:00 +08:00
|
|
|
case BLOCKING_TYPE_SIGHT:
|
2015-07-16 00:37:05 +07:00
|
|
|
return obj_sight_blocking_at_;
|
2019-01-08 13:28:00 +08:00
|
|
|
//case 4:
|
2015-06-30 00:07:12 +07:00
|
|
|
// return obj_scroll_blocking_at_;
|
2019-01-08 13:28:00 +08:00
|
|
|
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall op_make_straight_path2() {
|
2019-01-08 13:28:00 +08:00
|
|
|
TGameObj* objFrom = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &tileToArg = opHandler.arg(1),
|
|
|
|
|
&typeArg = opHandler.arg(2);
|
2019-01-08 13:28:00 +08:00
|
|
|
|
2019-11-28 10:24:40 +08:00
|
|
|
if (objFrom && tileToArg.isInt() && typeArg.isInt()) {
|
2019-11-28 14:42:07 +08:00
|
|
|
DWORD tileTo = tileToArg.rawValue(),
|
|
|
|
|
type = typeArg.rawValue();
|
2019-11-28 10:24:40 +08:00
|
|
|
|
|
|
|
|
long flag = (type == BLOCKING_TYPE_SHOOT) ? 32 : 0;
|
|
|
|
|
DWORD resultObj = 0;
|
|
|
|
|
make_straight_path_func_wrapper(objFrom, objFrom->tile, tileTo, 0, &resultObj, flag, (void*)getBlockingFunc(type));
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(resultObj);
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("obj_blocking_line");
|
|
|
|
|
opHandler.setReturn(0);
|
|
|
|
|
}
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_make_straight_path() {
|
2016-11-03 20:55:59 +07:00
|
|
|
_WRAP_OPCODE(op_make_straight_path2, 3, 1)
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall op_make_path2() {
|
2019-01-08 13:28:00 +08:00
|
|
|
TGameObj* objFrom = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &tileToArg = opHandler.arg(1),
|
|
|
|
|
&typeArg = opHandler.arg(2);
|
2019-01-08 13:28:00 +08:00
|
|
|
|
2019-11-28 10:24:40 +08:00
|
|
|
if (objFrom && tileToArg.isInt() && typeArg.isInt()) {
|
|
|
|
|
DWORD tileFrom = 0,
|
2019-11-28 14:42:07 +08:00
|
|
|
tileTo = tileToArg.rawValue(),
|
|
|
|
|
type = typeArg.rawValue(),
|
2019-11-28 10:24:40 +08:00
|
|
|
func = getBlockingFunc(type);
|
2019-01-08 13:28:00 +08:00
|
|
|
|
2019-11-28 10:24:40 +08:00
|
|
|
// if the object is not a critter, then there is no need to check tile (tileTo) for blocking
|
|
|
|
|
long pathLength, checkFlag = (objFrom->pid >> 24 == OBJ_TYPE_CRITTER);
|
|
|
|
|
|
|
|
|
|
tileFrom = objFrom->tile;
|
|
|
|
|
char pathData[800];
|
|
|
|
|
char* pathDataPtr = pathData;
|
|
|
|
|
__asm {
|
|
|
|
|
mov eax, objFrom;
|
|
|
|
|
mov edx, tileFrom;
|
|
|
|
|
mov ecx, pathDataPtr;
|
|
|
|
|
mov ebx, tileTo;
|
|
|
|
|
push func;
|
|
|
|
|
push checkFlag;
|
|
|
|
|
call make_path_func_;
|
|
|
|
|
mov pathLength, eax;
|
|
|
|
|
}
|
|
|
|
|
DWORD arrayId = TempArray(pathLength, 0);
|
|
|
|
|
for (int i = 0; i < pathLength; i++) {
|
|
|
|
|
arrays[arrayId].val[i].set((long)pathData[i]);
|
|
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(arrayId);
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("path_find_to");
|
|
|
|
|
opHandler.setReturn(-1);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_make_path() {
|
2016-11-03 20:55:59 +07:00
|
|
|
_WRAP_OPCODE(op_make_path2, 3, 1)
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall op_obj_blocking_at2() {
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &tileArg = opHandler.arg(0),
|
|
|
|
|
&elevArg = opHandler.arg(1),
|
|
|
|
|
&typeArg = opHandler.arg(2);
|
2019-01-08 13:28:00 +08:00
|
|
|
|
2019-11-28 10:24:40 +08:00
|
|
|
if (tileArg.isInt() && elevArg.isInt() && typeArg.isInt()) {
|
2019-11-28 14:42:07 +08:00
|
|
|
DWORD tile = tileArg.rawValue(),
|
|
|
|
|
elevation = elevArg.rawValue(),
|
|
|
|
|
type = typeArg.rawValue();
|
2019-11-28 10:24:40 +08:00
|
|
|
|
|
|
|
|
TGameObj* resultObj = obj_blocking_at_wrapper(0, tile, elevation, (void*)getBlockingFunc(type));
|
|
|
|
|
if (resultObj && type == BLOCKING_TYPE_SHOOT && (resultObj->flags & 0x80000000)) { // 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 = nullptr;
|
|
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(resultObj);
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("obj_blocking_tile");
|
|
|
|
|
opHandler.setReturn(0);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_obj_blocking_at() {
|
2016-11-03 20:55:59 +07:00
|
|
|
_WRAP_OPCODE(op_obj_blocking_at2, 3, 1)
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall op_tile_get_objects2() {
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &tileArg = opHandler.arg(0),
|
|
|
|
|
&elevArg = opHandler.arg(1);
|
|
|
|
|
|
|
|
|
|
if (tileArg.isInt() && elevArg.isInt()) {
|
2019-11-28 14:42:07 +08:00
|
|
|
DWORD tile = tileArg.rawValue(),
|
|
|
|
|
elevation = elevArg.rawValue();
|
2019-11-28 10:24:40 +08:00
|
|
|
DWORD arrayId = TempArray(0, 4);
|
|
|
|
|
TGameObj* obj = ObjFindFirstAtTile(elevation, tile);
|
|
|
|
|
while (obj) {
|
|
|
|
|
arrays[arrayId].push_back(reinterpret_cast<long>(obj));
|
|
|
|
|
obj = ObjFindNextAtTile();
|
|
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(arrayId);
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("tile_get_objs");
|
|
|
|
|
opHandler.setReturn(-1);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_tile_get_objects() {
|
2016-11-03 20:55:59 +07:00
|
|
|
_WRAP_OPCODE(op_tile_get_objects2, 2, 1)
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall op_get_party_members2() {
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &modeArg = opHandler.arg(0);
|
|
|
|
|
|
|
|
|
|
if (modeArg.isInt()) {
|
2019-11-28 14:42:07 +08:00
|
|
|
DWORD mode = modeArg.rawValue(), isDead;
|
2019-11-28 10:24:40 +08:00
|
|
|
int actualCount = *ptr_partyMemberCount;
|
|
|
|
|
DWORD arrayId = TempArray(0, 4);
|
|
|
|
|
DWORD* partyMemberList = *ptr_partyMemberList;
|
|
|
|
|
for (int i = 0; i < actualCount; i++) {
|
|
|
|
|
TGameObj* obj = reinterpret_cast<TGameObj*>(partyMemberList[i * 4]);
|
|
|
|
|
if (mode == 0) { // mode 0 will act just like op_party_member_count in fallout2
|
|
|
|
|
if (obj->pid >> 24 != OBJ_TYPE_CRITTER) // obj type != critter
|
|
|
|
|
continue;
|
|
|
|
|
__asm {
|
|
|
|
|
mov eax, obj;
|
|
|
|
|
call critter_is_dead_;
|
|
|
|
|
mov isDead, eax;
|
|
|
|
|
}
|
|
|
|
|
if (isDead)
|
|
|
|
|
continue;
|
|
|
|
|
if (obj->flags & 1) // Mouse_3d flag
|
|
|
|
|
continue;
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
2019-11-28 10:24:40 +08:00
|
|
|
arrays[arrayId].push_back((long)obj);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(arrayId);
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("party_member_list");
|
|
|
|
|
opHandler.setReturn(-1);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_get_party_members() {
|
2016-11-03 20:55:59 +07:00
|
|
|
_WRAP_OPCODE(op_get_party_members2, 1, 1)
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_art_exists() {
|
|
|
|
|
_OP_BEGIN(ebp)
|
|
|
|
|
_GET_ARG_R32(ebp, ecx, eax)
|
|
|
|
|
_CHECK_ARG_INT(cx, fail)
|
|
|
|
|
__asm {
|
|
|
|
|
call art_exists_;
|
|
|
|
|
jmp end;
|
|
|
|
|
fail:
|
|
|
|
|
xor eax, eax;
|
|
|
|
|
end:
|
|
|
|
|
}
|
|
|
|
|
_RET_VAL_INT(ebp)
|
|
|
|
|
_OP_END
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall op_obj_is_carrying_obj2() {
|
2016-11-05 03:34:09 +07:00
|
|
|
int num = 0;
|
|
|
|
|
const ScriptValue &invenObjArg = opHandler.arg(0),
|
|
|
|
|
&itemObjArg = opHandler.arg(1);
|
|
|
|
|
|
2019-11-28 10:24:40 +08:00
|
|
|
TGameObj *invenObj = invenObjArg.asObject(),
|
|
|
|
|
*itemObj = itemObjArg.asObject();
|
2019-11-29 11:58:14 +08:00
|
|
|
if (invenObj != nullptr && itemObj != nullptr) {
|
|
|
|
|
for (int i = 0; i < invenObj->invenCount; i++) {
|
|
|
|
|
if (invenObj->invenTablePtr[i].object == itemObj) {
|
|
|
|
|
num = invenObj->invenTablePtr[i].count;
|
|
|
|
|
break;
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
}
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("obj_is_carrying_obj");
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
2016-11-05 03:34:09 +07:00
|
|
|
opHandler.setReturn(num);
|
2015-06-30 00:07:12 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) op_obj_is_carrying_obj() {
|
2016-11-03 20:55:59 +07:00
|
|
|
_WRAP_OPCODE(op_obj_is_carrying_obj2, 2, 1)
|
2015-11-16 10:40:26 +08:00
|
|
|
}
|
2016-11-04 17:22:05 +07:00
|
|
|
|
|
|
|
|
static void sf_critter_inven_obj2() {
|
2016-11-06 17:37:25 +07:00
|
|
|
TGameObj* critter = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &slotArg = opHandler.arg(1);
|
|
|
|
|
|
|
|
|
|
if (critter && slotArg.isInt()) {
|
2019-11-28 14:42:07 +08:00
|
|
|
int slot = slotArg.rawValue();
|
2019-11-28 10:24:40 +08:00
|
|
|
switch (slot) {
|
|
|
|
|
case 0:
|
|
|
|
|
opHandler.setReturn(InvenWorn(critter));
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
opHandler.setReturn(InvenRightHand(critter));
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
opHandler.setReturn(InvenLeftHand(critter));
|
|
|
|
|
break;
|
|
|
|
|
case -2:
|
|
|
|
|
opHandler.setReturn(critter->invenCount);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
opHandler.printOpcodeError("critter_inven_obj2() - invalid type.");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("critter_inven_obj2");
|
|
|
|
|
opHandler.setReturn(0);
|
2016-11-04 17:22:05 +07:00
|
|
|
}
|
|
|
|
|
}
|
2018-09-21 19:27:57 +08:00
|
|
|
|
2018-10-10 17:24:05 +08:00
|
|
|
static void sf_set_outline() {
|
2019-11-28 14:42:07 +08:00
|
|
|
TGameObj* obj = opHandler.arg(0).object();
|
|
|
|
|
int color = opHandler.arg(1).rawValue();
|
2018-10-10 17:24:05 +08:00
|
|
|
obj->outline = color;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sf_get_outline() {
|
|
|
|
|
TGameObj* obj = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
if (obj) {
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(obj->outline);
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("get_outline");
|
|
|
|
|
opHandler.setReturn(0);
|
|
|
|
|
}
|
2018-10-10 17:24:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sf_set_flags() {
|
2019-11-28 14:42:07 +08:00
|
|
|
TGameObj* obj = opHandler.arg(0).object();
|
|
|
|
|
int flags = opHandler.arg(1).rawValue();
|
2018-10-10 17:24:05 +08:00
|
|
|
obj->flags = flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sf_get_flags() {
|
|
|
|
|
TGameObj* obj = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
if (obj) {
|
|
|
|
|
opHandler.setReturn(obj->flags);
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("get_flags");
|
|
|
|
|
opHandler.setReturn(0);
|
|
|
|
|
}
|
2018-10-10 17:24:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sf_outlined_object() {
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(*ptr_outlined_object);
|
2018-10-10 17:24:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sf_item_weight() {
|
|
|
|
|
TGameObj* item = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
int weight = 0;
|
|
|
|
|
if (item) {
|
|
|
|
|
weight = ItemWeight(item);
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("item_weight");
|
2018-10-10 17:24:05 +08:00
|
|
|
}
|
|
|
|
|
opHandler.setReturn(weight);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 12:59:27 +08:00
|
|
|
static void sf_real_dude_obj() {
|
|
|
|
|
opHandler.setReturn(RealDudeObject());
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-04 09:14:02 +08:00
|
|
|
static void sf_lock_is_jammed() {
|
|
|
|
|
TGameObj* obj = opHandler.arg(0).asObject();
|
2019-11-28 10:24:40 +08:00
|
|
|
int result = 0;
|
|
|
|
|
if (obj) {
|
|
|
|
|
__asm {
|
|
|
|
|
mov eax, obj;
|
|
|
|
|
call obj_lock_is_jammed_;
|
|
|
|
|
mov result, eax;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("lock_is_jammed");
|
2018-11-04 09:14:02 +08:00
|
|
|
}
|
|
|
|
|
opHandler.setReturn(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sf_unjam_lock() {
|
2019-11-28 14:42:07 +08:00
|
|
|
TGameObj* obj = opHandler.arg(0).object();
|
2018-11-04 09:14:02 +08:00
|
|
|
__asm {
|
|
|
|
|
mov eax, obj;
|
|
|
|
|
call obj_unjam_lock_;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-07 09:36:46 +08:00
|
|
|
static void sf_set_unjam_locks_time() {
|
2019-11-28 14:42:07 +08:00
|
|
|
int time = opHandler.arg(0).rawValue();
|
2019-10-07 09:36:46 +08:00
|
|
|
if (time < 0 || time > 127) {
|
|
|
|
|
opHandler.printOpcodeError("set_unjam_locks_time() - time argument must be in the range of 0 to 127.");
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(-1);
|
2019-10-07 09:36:46 +08:00
|
|
|
} else {
|
|
|
|
|
SetAutoUnjamLockTime(time);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-21 19:27:57 +08:00
|
|
|
static void sf_get_current_inven_size() {
|
2019-11-28 10:24:40 +08:00
|
|
|
TGameObj* obj = opHandler.arg(0).asObject();
|
|
|
|
|
if (obj) {
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(sf_item_total_size(obj));
|
2019-11-28 10:24:40 +08:00
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("get_current_inven_size");
|
|
|
|
|
opHandler.setReturn(0);
|
|
|
|
|
}
|
2018-09-21 19:27:57 +08:00
|
|
|
}
|
2018-12-05 10:17:26 +08:00
|
|
|
|
2019-05-08 21:04:18 +08:00
|
|
|
static void sf_get_dialog_object() {
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(InDialog() ? *ptr_dialog_target : 0);
|
2019-05-08 21:04:18 +08:00
|
|
|
}
|
|
|
|
|
|
2019-01-08 13:28:00 +08:00
|
|
|
static void sf_get_obj_under_cursor() {
|
2019-11-28 10:24:40 +08:00
|
|
|
const ScriptValue &crSwitchArg = opHandler.arg(0),
|
|
|
|
|
&inclDudeArg = opHandler.arg(1);
|
2019-01-08 13:28:00 +08:00
|
|
|
|
2019-11-28 10:24:40 +08:00
|
|
|
long obj = 0;
|
|
|
|
|
if (crSwitchArg.isInt() && inclDudeArg.isInt()) {
|
|
|
|
|
int crSwitch = crSwitchArg.asBool() ? 1 : -1,
|
|
|
|
|
inclDude = inclDudeArg.rawValue();
|
|
|
|
|
|
|
|
|
|
__asm {
|
|
|
|
|
mov ebx, dword ptr ds:[_map_elevation];
|
|
|
|
|
mov edx, inclDude;
|
|
|
|
|
mov eax, crSwitch;
|
|
|
|
|
call object_under_mouse_;
|
|
|
|
|
mov obj, eax;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("obj_under_cursor");
|
2019-01-08 13:28:00 +08:00
|
|
|
}
|
|
|
|
|
opHandler.setReturn(obj);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-08 21:04:18 +08:00
|
|
|
static void sf_get_loot_object() {
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn((GetLoopFlags() & INTFACELOOT) ? LoadGameHook_LootTarget : 0);
|
2019-05-08 21:04:18 +08:00
|
|
|
}
|
|
|
|
|
|
2019-10-20 12:02:14 +08:00
|
|
|
static const char* failedLoad = "%s() - failed to load a prototype ID: %d";
|
2019-10-05 07:53:50 +08:00
|
|
|
static bool protoMaxLimitPatch = false;
|
|
|
|
|
|
|
|
|
|
static void _stdcall get_proto_data2() {
|
|
|
|
|
const ScriptValue &pidArg = opHandler.arg(0),
|
|
|
|
|
&offsetArg = opHandler.arg(1);
|
2019-11-28 10:24:40 +08:00
|
|
|
|
|
|
|
|
if (pidArg.isInt() && offsetArg.isInt()) {
|
2019-10-05 07:53:50 +08:00
|
|
|
char* protoPtr;
|
|
|
|
|
int pid = pidArg.rawValue();
|
|
|
|
|
int result;
|
|
|
|
|
__asm {
|
|
|
|
|
lea edx, protoPtr;
|
|
|
|
|
mov eax, pid;
|
|
|
|
|
call proto_ptr_;
|
|
|
|
|
mov result, eax;
|
|
|
|
|
}
|
|
|
|
|
if (result != -1) {
|
|
|
|
|
result = *(long*)((BYTE*)protoPtr + offsetArg.rawValue());
|
|
|
|
|
} else {
|
|
|
|
|
opHandler.printOpcodeError(failedLoad, "get_proto_data", pid);
|
|
|
|
|
}
|
|
|
|
|
opHandler.setReturn(result);
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("get_proto_data");
|
|
|
|
|
opHandler.setReturn(-1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) get_proto_data() {
|
|
|
|
|
_WRAP_OPCODE(get_proto_data2, 2, 1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _stdcall set_proto_data2() {
|
|
|
|
|
const ScriptValue &pidArg = opHandler.arg(0),
|
|
|
|
|
&offsetArg = opHandler.arg(1),
|
|
|
|
|
&valueArg = opHandler.arg(2);
|
2019-11-28 10:24:40 +08:00
|
|
|
|
|
|
|
|
if (pidArg.isInt() && offsetArg.isInt() && valueArg.isInt()) {
|
2019-10-05 07:53:50 +08:00
|
|
|
char* protoPtr;
|
|
|
|
|
int pid = pidArg.rawValue();
|
|
|
|
|
int result;
|
|
|
|
|
__asm {
|
|
|
|
|
lea edx, protoPtr;
|
|
|
|
|
mov eax, pid;
|
|
|
|
|
call proto_ptr_;
|
|
|
|
|
mov result, eax;
|
|
|
|
|
}
|
|
|
|
|
if (result != -1) {
|
|
|
|
|
*(long*)((BYTE*)protoPtr + offsetArg.rawValue()) = valueArg.rawValue();
|
|
|
|
|
if (!protoMaxLimitPatch) {
|
|
|
|
|
LoadProtoAutoMaxLimit();
|
|
|
|
|
protoMaxLimitPatch = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
opHandler.printOpcodeError(failedLoad, "set_proto_data", pid);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
OpcodeInvalidArgs("set_proto_data");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __declspec(naked) set_proto_data() {
|
|
|
|
|
_WRAP_OPCODE(set_proto_data2, 3, 0)
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-05 10:17:26 +08:00
|
|
|
static void sf_get_object_data() {
|
2019-09-30 07:51:43 +08:00
|
|
|
DWORD result = 0;
|
2019-11-28 10:24:40 +08:00
|
|
|
TGameObj* obj = opHandler.arg(0).asObject();
|
|
|
|
|
const ScriptValue &offsetArg = opHandler.arg(1);
|
|
|
|
|
|
|
|
|
|
if (obj && offsetArg.isInt()) {
|
|
|
|
|
DWORD* object_ptr = (DWORD*)obj;
|
|
|
|
|
if (*(object_ptr - 1) != 0xFEEDFACE) {
|
|
|
|
|
opHandler.printOpcodeError("get_object_data() - invalid object pointer.");
|
|
|
|
|
} else {
|
|
|
|
|
result = *(long*)((BYTE*)object_ptr + offsetArg.rawValue());
|
|
|
|
|
}
|
2019-09-30 07:51:43 +08:00
|
|
|
} else {
|
2019-11-28 10:24:40 +08:00
|
|
|
OpcodeInvalidArgs("get_object_data");
|
2019-09-30 07:51:43 +08:00
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(result);
|
2018-12-05 10:17:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sf_set_object_data() {
|
2019-09-30 07:51:43 +08:00
|
|
|
DWORD* object_ptr = (DWORD*)opHandler.arg(0).rawValue();
|
|
|
|
|
if (*(object_ptr - 1) != 0xFEEDFACE) {
|
|
|
|
|
opHandler.printOpcodeError("set_object_data() - invalid object pointer.");
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(-1);
|
2019-09-30 07:51:43 +08:00
|
|
|
} else {
|
|
|
|
|
*(long*)((BYTE*)object_ptr + opHandler.arg(1).rawValue()) = opHandler.arg(2).rawValue();
|
|
|
|
|
}
|
2018-12-05 10:17:26 +08:00
|
|
|
}
|
2019-04-12 21:27:14 +08:00
|
|
|
|
|
|
|
|
static void sf_set_unique_id() {
|
2019-11-28 14:42:07 +08:00
|
|
|
TGameObj* obj = opHandler.arg(0).object();
|
2019-04-16 20:53:41 +08:00
|
|
|
long id;
|
2019-11-28 14:42:07 +08:00
|
|
|
if (opHandler.numArgs() > 1 && opHandler.arg(1).rawValue() == -1) {
|
2019-04-16 20:53:41 +08:00
|
|
|
id = NewObjId();
|
|
|
|
|
obj->ID = id;
|
|
|
|
|
} else {
|
|
|
|
|
id = SetObjectUniqueID(obj);
|
|
|
|
|
}
|
2019-11-28 14:42:07 +08:00
|
|
|
opHandler.setReturn(id);
|
2019-04-12 21:27:14 +08:00
|
|
|
}
|