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
2020-02-02 21:49:54 +08:00
#include "Combat.h"
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
2019-12-09 11:07:40 +08:00
#define exec_script_proc(script, proc) __asm { \
__asm mov eax, script \
__asm mov edx, proc \
__asm call exec_script_proc_ \
}
2015-06-30 00:07:12 +07:00
2020-05-19 10:05:27 +08:00
static void __stdcall op_remove_script2 () {
2019-12-09 11:07:40 +08:00
TGameObj * object = opHandler . arg ( 0 ). asObject ();
if ( object ) {
2020-07-16 11:10:48 +08:00
if ( object -> scriptId != 0xFFFFFFFF ) {
ScrRemove ( object -> scriptId );
object -> scriptId = 0xFFFFFFFF ;
2019-12-09 11:07:40 +08:00
}
} else {
OpcodeInvalidArgs ( "remove_script" );
2015-06-30 00:07:12 +07:00
}
}
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_remove_script () {
_WRAP_OPCODE ( op_remove_script2 , 1 , 0 )
2019-12-09 11:07:40 +08:00
}
2020-05-19 10:05:27 +08:00
static void __stdcall op_set_script2 () {
2020-07-16 11:10:48 +08:00
using Scripts :: start ;
using Scripts :: map_enter_p_proc ;
2019-12-09 11:07:40 +08:00
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 -- ;
2020-07-16 11:10:48 +08:00
if ( object -> scriptId != 0xFFFFFFFF ) {
ScrRemove ( object -> scriptId );
object -> scriptId = 0xFFFFFFFF ;
2019-12-09 11:07:40 +08:00
}
2020-07-16 11:10:48 +08:00
if ( object -> Type () == OBJ_TYPE_CRITTER ) {
scriptType = Scripts :: SCRIPT_CRITTER ;
2019-12-09 11:07:40 +08:00
} else {
2020-07-16 11:10:48 +08:00
scriptType = Scripts :: SCRIPT_ITEM ;
2019-12-09 11:07:40 +08:00
}
ObjNewSidInst ( object , scriptType , scriptIndex );
2020-07-16 11:10:48 +08:00
long scriptId = object -> scriptId ;
2019-12-09 11:07:40 +08:00
exec_script_proc ( scriptId , start );
if (( valArg & 0x80000000 ) == 0 ) exec_script_proc ( scriptId , map_enter_p_proc );
} else {
OpcodeInvalidArgs ( "set_script" );
2015-06-30 00:07:12 +07:00
}
}
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_set_script () {
_WRAP_OPCODE ( op_set_script2 , 2 , 0 )
2019-12-09 11:07:40 +08:00
}
2020-05-07 12:23:22 +08:00
static void __stdcall op_create_spatial2 () {
2020-07-16 11:10:48 +08:00
using Scripts :: start ;
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 (),
2019-12-09 11:07:40 +08:00
radius = radiusArg . rawValue ();
long scriptId ;
TScript * scriptPtr ;
2020-07-16 11:10:48 +08:00
if ( ScrNew ( & scriptId , Scripts :: SCRIPT_SPATIAL ) == - 1 || ScrPtr ( scriptId , & scriptPtr ) == - 1 ) return ;
2019-12-09 11:07:40 +08:00
// set spatial script properties:
2020-07-16 11:10:48 +08:00
scriptPtr -> scriptIdx = scriptIndex - 1 ;
scriptPtr -> elevationAndTile = ( elevation << 29 ) & 0xE0000000 | tile ;
scriptPtr -> spatialRadius = radius ;
2019-12-09 11:07:40 +08:00
2019-11-28 10:24:40 +08:00
// this will load appropriate script program and link it to the script instance we just created:
2019-12-09 11:07:40 +08:00
exec_script_proc ( scriptId , start );
2020-07-16 11:10:48 +08:00
opHandler . setReturn ( ScrFindObjFromProgram ( scriptPtr -> program ));
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
2020-05-20 11:33:43 +08:00
static void mf_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 ;
2020-07-16 11:10:48 +08:00
if ( ScrPtr ( spatialObj -> scriptId , & script ) != - 1 ) {
opHandler . setReturn ( script -> spatialRadius );
2019-11-28 10:24:40 +08:00
}
} else {
OpcodeInvalidArgs ( "spatial_radius" );
opHandler . setReturn ( 0 );
2015-06-30 00:07:12 +07:00
}
}
2020-05-19 10:05:27 +08:00
static void __stdcall op_get_script2 () {
2019-12-09 11:07:40 +08:00
TGameObj * object = opHandler . arg ( 0 ). asObject ();
if ( object ) {
2020-07-16 11:10:48 +08:00
long scriptIndex = object -> scriptIndex ;
2019-12-09 11:07:40 +08:00
opHandler . setReturn (( scriptIndex >= 0 ) ? ++ scriptIndex : 0 );
} else {
OpcodeInvalidArgs ( "get_script" );
opHandler . setReturn ( - 1 );
}
}
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_get_script () {
_WRAP_OPCODE ( op_get_script2 , 1 , 1 )
2019-12-09 11:07:40 +08:00
}
2020-05-19 10:05:27 +08:00
static void __stdcall op_set_critter_burst_disable2 () {
2019-12-09 11:07:40 +08:00
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" );
2015-06-30 00:07:12 +07:00
}
}
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_set_critter_burst_disable () {
_WRAP_OPCODE ( op_set_critter_burst_disable2 , 2 , 0 )
2015-06-30 00:07:12 +07:00
}
2019-12-09 11:07:40 +08:00
2020-05-19 10:05:27 +08:00
static void __stdcall op_get_weapon_ammo_pid2 () {
2020-03-24 12:12:34 +08:00
TGameObj * obj = opHandler . arg ( 0 ). asObject ();
if ( obj ) {
2020-07-18 10:50:49 +08:00
opHandler . setReturn ( obj -> item . ammoPid );
2020-03-24 12:12:34 +08:00
} else {
OpcodeInvalidArgs ( "get_weapon_ammo_pid" );
opHandler . setReturn ( - 1 );
}
}
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_get_weapon_ammo_pid () {
_WRAP_OPCODE ( op_get_weapon_ammo_pid2 , 1 , 1 )
2020-03-24 12:12:34 +08:00
}
2020-05-19 10:05:27 +08:00
static void __stdcall op_set_weapon_ammo_pid2 () {
2020-03-24 12:12:34 +08:00
TGameObj * obj = opHandler . arg ( 0 ). asObject ();
const ScriptValue & pidArg = opHandler . arg ( 1 );
if ( obj && pidArg . isInt ()) {
2020-07-18 10:50:49 +08:00
obj -> item . ammoPid = pidArg . rawValue ();
2020-03-24 12:12:34 +08:00
} else {
OpcodeInvalidArgs ( "set_weapon_ammo_pid" );
2015-06-30 00:07:12 +07:00
}
}
2019-12-09 11:07:40 +08:00
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_set_weapon_ammo_pid () {
_WRAP_OPCODE ( op_set_weapon_ammo_pid2 , 2 , 0 )
2020-03-24 12:12:34 +08:00
}
2020-05-19 10:05:27 +08:00
static void __stdcall op_get_weapon_ammo_count2 () {
2020-03-24 12:12:34 +08:00
TGameObj * obj = opHandler . arg ( 0 ). asObject ();
if ( obj ) {
2020-07-18 10:50:49 +08:00
opHandler . setReturn ( obj -> item . charges );
2020-03-24 12:12:34 +08:00
} else {
OpcodeInvalidArgs ( "get_weapon_ammo_count" );
opHandler . setReturn ( 0 );
2015-06-30 00:07:12 +07:00
}
}
2019-12-09 11:07:40 +08:00
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_get_weapon_ammo_count () {
_WRAP_OPCODE ( op_get_weapon_ammo_count2 , 1 , 1 )
2020-03-24 12:12:34 +08:00
}
2020-05-19 10:05:27 +08:00
static void __stdcall op_set_weapon_ammo_count2 () {
2020-03-24 12:12:34 +08:00
TGameObj * obj = opHandler . arg ( 0 ). asObject ();
const ScriptValue & countArg = opHandler . arg ( 1 );
if ( obj && countArg . isInt ()) {
2020-07-18 10:50:49 +08:00
obj -> item . charges = countArg . rawValue ();
2020-03-24 12:12:34 +08:00
} else {
OpcodeInvalidArgs ( "set_weapon_ammo_count" );
2015-06-30 00:07:12 +07:00
}
}
2019-12-09 11:07:40 +08:00
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_set_weapon_ammo_count () {
_WRAP_OPCODE ( op_set_weapon_ammo_count2 , 2 , 0 )
2015-06-30 00:07:12 +07:00
}
2020-04-02 12:00:52 +08:00
enum {
BLOCKING_TYPE_BLOCK = 0 ,
BLOCKING_TYPE_SHOOT = 1 ,
BLOCKING_TYPE_AI = 2 ,
BLOCKING_TYPE_SIGHT = 3 ,
BLOCKING_TYPE_SCROLL = 4
};
2015-06-30 00:07:12 +07:00
static DWORD getBlockingFunc ( DWORD type ) {
switch ( type ) {
2019-01-08 13:28:00 +08:00
case BLOCKING_TYPE_BLOCK : default :
2020-12-13 08:46:33 +08:00
return obj_blocking_at_ ; // with calling hook
2019-01-08 13:28:00 +08:00
case BLOCKING_TYPE_SHOOT :
2020-12-13 08:46:33 +08:00
return obj_shoot_blocking_at_ ; // w/o calling hook
2019-01-08 13:28:00 +08:00
case BLOCKING_TYPE_AI :
2020-12-13 08:46:33 +08:00
return obj_ai_blocking_at_ ; // w/o calling hook
2019-01-08 13:28:00 +08:00
case BLOCKING_TYPE_SIGHT :
2020-12-13 08:46:33 +08:00
return obj_sight_blocking_at_ ; // w/o calling hook
2019-01-08 13:28:00 +08:00
//case 4:
2015-06-30 00:07:12 +07:00
// return obj_scroll_blocking_at_;
}
}
2020-05-07 12:23:22 +08: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 ;
2020-04-30 10:28:31 +08:00
MakeStraightPathFunc ( 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
}
2020-05-07 12:23:22 +08: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 ()) {
2020-09-19 21:34:14 +08:00
DWORD tileTo = tileToArg . rawValue (),
type = typeArg . rawValue (),
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
2020-09-19 21:34:14 +08:00
long checkFlag = ( objFrom -> Type () == OBJ_TYPE_CRITTER );
2019-11-28 10:24:40 +08:00
char pathData [ 800 ];
2020-09-19 21:34:14 +08:00
long pathLength = MakePathFunc ( objFrom , objFrom -> tile , tileTo , pathData , checkFlag , ( void * ) func );
2020-10-12 11:03:55 +08:00
DWORD arrayId = CreateTempArray ( pathLength , 0 );
2019-11-28 10:24:40 +08:00
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
}
2020-05-07 12:23:22 +08: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 ));
2020-07-16 11:10:48 +08:00
if ( resultObj && type == BLOCKING_TYPE_SHOOT && ( resultObj -> flags & ObjectFlag :: ShootThru )) { // don't know what this flag means, copy-pasted from the engine code
2019-11-28 10:24:40 +08:00
// 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
}
2020-05-07 12:23:22 +08: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 ();
2020-10-12 11:03:55 +08:00
DWORD arrayId = CreateTempArray ( 0 , 4 );
2019-11-28 10:24:40 +08:00
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
}
2020-05-07 12:23:22 +08: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 ()) {
2020-09-19 21:34:14 +08:00
DWORD includeHidden = modeArg . rawValue ();
2019-11-28 10:24:40 +08:00
int actualCount = * ptr_partyMemberCount ;
2020-10-12 11:03:55 +08:00
DWORD arrayId = CreateTempArray ( 0 , 4 );
2019-11-28 10:24:40 +08:00
DWORD * partyMemberList = * ptr_partyMemberList ;
for ( int i = 0 ; i < actualCount ; i ++ ) {
TGameObj * obj = reinterpret_cast < TGameObj *> ( partyMemberList [ i * 4 ]);
2020-09-19 21:34:14 +08:00
if ( includeHidden || ( obj -> Type () == OBJ_TYPE_CRITTER && ! CritterIsDead ( obj ) && ! ( obj -> flags & ObjectFlag :: Mouse_3d ))) {
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 () {
__asm {
2020-03-23 13:52:28 +08:00
_GET_ARG_INT ( fail );
2015-06-30 00:07:12 +07:00
call art_exists_ ;
2020-03-23 13:52:28 +08:00
mov edx , eax ;
2015-06-30 00:07:12 +07:00
end :
2020-03-23 13:52:28 +08:00
mov eax , ebx ;
_J_RET_VAL_TYPE ( VAR_TYPE_INT );
fail :
xor edx , edx ; // return 0
jmp end ;
2015-06-30 00:07:12 +07:00
}
}
2020-05-07 12:23:22 +08:00
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 ) {
2020-07-16 11:10:48 +08:00
for ( int i = 0 ; i < invenObj -> invenSize ; i ++ ) {
if ( invenObj -> invenTable [ i ]. object == itemObj ) {
num = invenObj -> invenTable [ i ]. count ;
2019-11-29 11:58:14 +08:00
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
2020-05-20 11:33:43 +08:00
static void mf_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 :
2020-07-16 11:10:48 +08:00
opHandler . setReturn ( critter -> invenSize );
2019-11-28 10:24:40 +08:00
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
2020-05-20 11:33:43 +08:00
static void mf_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 ;
}
2020-05-20 11:33:43 +08:00
static void mf_get_outline () {
2018-10-10 17:24:05 +08:00
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
}
2020-05-20 11:33:43 +08:00
static void mf_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 ;
}
2020-05-20 11:33:43 +08:00
static void mf_get_flags () {
2018-10-10 17:24:05 +08:00
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
}
2020-05-20 11:33:43 +08:00
static void mf_outlined_object () {
2019-11-28 14:42:07 +08:00
opHandler . setReturn ( * ptr_outlined_object );
2018-10-10 17:24:05 +08:00
}
2020-05-20 11:33:43 +08:00
static void mf_item_weight () {
2018-10-10 17:24:05 +08:00
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 );
}
2020-05-20 11:33:43 +08:00
static void mf_real_dude_obj () {
2020-12-30 22:33:37 +08:00
opHandler . setReturn ( PartyControl_RealDudeObject ());
2019-05-22 12:59:27 +08:00
}
2020-10-08 22:13:07 +08:00
static void mf_car_gas_amount () {
opHandler . setReturn ( * ptr_carGasAmount );
}
2020-05-20 11:33:43 +08:00
static void mf_lock_is_jammed () {
2018-11-04 09:14:02 +08:00
TGameObj * obj = opHandler . arg ( 0 ). asObject ();
2019-11-28 10:24:40 +08:00
if ( obj ) {
2020-03-25 12:26:26 +08:00
opHandler . setReturn ( ObjLockIsJammed ( obj ));
2019-11-28 10:24:40 +08:00
} else {
OpcodeInvalidArgs ( "lock_is_jammed" );
2020-03-25 12:26:26 +08:00
opHandler . setReturn ( 0 );
2018-11-04 09:14:02 +08:00
}
}
2020-05-20 11:33:43 +08:00
static void mf_unjam_lock () {
2020-03-25 12:26:26 +08:00
ObjUnjamLock ( opHandler . arg ( 0 ). object ());
2018-11-04 09:14:02 +08:00
}
2020-05-20 11:33:43 +08:00
static void mf_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 {
2020-10-08 22:13:07 +08:00
Objects_SetAutoUnjamLockTime ( time );
2019-10-07 09:36:46 +08:00
}
}
2020-05-20 11:33:43 +08:00
static void mf_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
2020-05-20 11:33:43 +08:00
static void mf_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
}
2020-05-20 11:33:43 +08:00
static void mf_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
if ( crSwitchArg . isInt () && inclDudeArg . isInt ()) {
2020-03-25 12:26:26 +08:00
opHandler . setReturn ( ObjectUnderMouse ( crSwitchArg . asBool () ? 1 : - 1 , inclDudeArg . rawValue (), * ptr_map_elevation ));
2019-11-28 10:24:40 +08:00
} else {
OpcodeInvalidArgs ( "obj_under_cursor" );
2020-03-25 12:26:26 +08:00
opHandler . setReturn ( 0 );
2019-01-08 13:28:00 +08:00
}
}
2020-05-20 11:33:43 +08:00
static void mf_get_loot_object () {
2020-04-18 09:03:16 +08:00
opHandler . setReturn (( GetLoopFlags () & INTFACELOOT ) ? ptr_target_stack [ * ptr_target_curr_stack ] : 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 ;
2020-05-19 10:05:27 +08:00
static void __stdcall op_get_proto_data2 () {
2019-10-05 07:53:50 +08:00
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 );
}
}
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_get_proto_data () {
_WRAP_OPCODE ( op_get_proto_data2 , 2 , 1 )
2019-10-05 07:53:50 +08:00
}
2020-05-19 10:05:27 +08:00
static void __stdcall op_set_proto_data2 () {
2019-10-05 07:53:50 +08:00
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 ) {
2020-10-08 22:13:07 +08:00
Objects_LoadProtoAutoMaxLimit ();
2019-10-05 07:53:50 +08:00
protoMaxLimitPatch = true ;
}
} else {
opHandler . printOpcodeError ( failedLoad , "set_proto_data" , pid );
}
} else {
OpcodeInvalidArgs ( "set_proto_data" );
}
}
2020-05-19 10:05:27 +08:00
static void __declspec ( naked ) op_set_proto_data () {
_WRAP_OPCODE ( op_set_proto_data2 , 3 , 0 )
2019-10-05 07:53:50 +08:00
}
2020-05-20 11:33:43 +08:00
static void mf_get_object_data () {
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 ;
2020-10-08 13:49:26 +08:00
opHandler . setReturn ( * ( 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" );
2020-10-08 13:49:26 +08:00
opHandler . setReturn ( 0 );
2019-09-30 07:51:43 +08:00
}
2018-12-05 10:17:26 +08:00
}
2020-05-20 11:33:43 +08:00
static void mf_set_object_data () {
2019-09-30 07:51:43 +08:00
DWORD * object_ptr = ( DWORD * ) opHandler . arg ( 0 ). rawValue ();
2020-10-08 13:49:26 +08:00
* ( 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
2020-05-20 11:33:43 +08:00
static void mf_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 ;
2020-10-25 01:05:34 +08:00
if ( opHandler . arg ( 1 ). rawValue () == - 1 ) {
2019-04-16 20:53:41 +08:00
id = NewObjId ();
2020-07-16 11:10:48 +08:00
obj -> id = id ;
2019-04-16 20:53:41 +08:00
} else {
2020-10-08 22:13:07 +08:00
id = Objects_SetObjectUniqueID ( obj );
2019-04-16 20:53:41 +08:00
}
2019-11-28 14:42:07 +08:00
opHandler . setReturn ( id );
2019-04-12 21:27:14 +08:00
}
2019-12-13 10:56:15 +08:00
2020-05-20 11:33:43 +08:00
static void mf_objects_in_radius () {
2019-12-13 10:56:15 +08:00
const ScriptValue & tileArg = opHandler . arg ( 0 ),
& radiusArg = opHandler . arg ( 1 ),
& elevArg = opHandler . arg ( 2 );
DWORD id = 0 ;
if ( tileArg . isInt () && radiusArg . isInt () && elevArg . isInt ()) {
long type = - 1 ;
if ( opHandler . numArgs () > 3 ) {
const ScriptValue & typeArg = opHandler . arg ( 3 );
if ( ! typeArg . isInt ()) goto invalidArgs ;
type = typeArg . rawValue ();
}
long radius = radiusArg . rawValue ();
if ( radius <= 0 ) radius = 1 ; else if ( radius > 50 ) radius = 50 ;
long elev = elevArg . rawValue ();
if ( elev < 0 ) elev = 0 ; else if ( elev > 2 ) elev = 2 ;
std :: vector < TGameObj *> objects ;
objects . reserve ( 25 );
GetObjectsTileRadius ( objects , tileArg . rawValue (), radius , elev , type );
size_t sz = objects . size ();
2020-10-12 11:03:55 +08:00
id = CreateTempArray ( sz , 0 );
2019-12-13 10:56:15 +08:00
for ( size_t i = 0 ; i < sz ; i ++ ) {
arrays [ id ]. val [ i ]. set (( long ) objects [ i ]);
}
} else {
invalidArgs :
OpcodeInvalidArgs ( "get_objects_at_radius" );
}
opHandler . setReturn ( id );
}