2023-01-29 20:59:31 +01:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2023-10-31 20:39:28 +01:00
Copyright ( C ) 2023 the OpenMoHAA team
2023-01-29 20:59:31 +01:00
This file is part of OpenMoHAA source code .
OpenMoHAA source code 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 2 of the License ,
or ( at your option ) any later version .
OpenMoHAA source code 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 OpenMoHAA source code ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
// scriptvm.cpp : Script virtual machine, interprets and execute scripts
2023-06-17 01:24:20 +02:00
# include "../fgame/g_local.h"
# include "../fgame/scriptmaster.h"
# include "../fgame/scriptthread.h"
2023-01-30 18:20:50 +01:00
# include "scriptclass.h"
2023-01-29 20:59:31 +01:00
# include "scriptvm.h"
2023-01-30 18:20:50 +01:00
# include "scriptcompiler.h"
2023-04-29 21:56:38 +02:00
# include "scriptexception.h"
2023-06-17 01:24:20 +02:00
# include "../fgame/game.h"
# include "../fgame/level.h"
# include "../fgame/parm.h"
2023-10-08 00:07:12 +02:00
# include "../fgame/worldspawn.h"
2023-01-29 20:59:31 +01:00
2023-02-07 20:50:09 +01:00
# include <utility>
2023-01-29 20:59:31 +01:00
# ifdef CGAME_DLL
2023-07-05 21:23:39 +02:00
# define VM_Printf cgi.Printf
# define VM_DPrintf cgi.DPrintf
2023-01-29 20:59:31 +01:00
# elif defined GAME_DLL
2023-07-05 21:23:39 +02:00
# define VM_Printf gi.Printf
# define VM_DPrintf gi.DPrintf2
2023-01-29 20:59:31 +01:00
# else
2023-07-05 21:23:39 +02:00
# define VM_Printf printf
# define VM_DPrintf printf
2023-01-29 20:59:31 +01:00
# endif
2023-10-27 20:00:48 +02:00
static const ScriptVM * currentScriptFile ;
static unsigned int currentScriptLine ;
2023-02-02 23:48:51 +01:00
class ScriptCommandEvent : public Event
{
public :
2023-07-05 21:23:39 +02:00
ScriptCommandEvent ( unsigned int eventNum ) ;
2023-09-07 18:21:03 +02:00
ScriptCommandEvent ( unsigned int eventNum , int numArgs ) ;
2023-02-02 23:48:51 +01:00
} ;
ScriptCommandEvent : : ScriptCommandEvent ( unsigned int eventNum )
2023-07-05 21:23:39 +02:00
: Event ( eventNum )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
fromScript = true ;
2023-02-02 23:48:51 +01:00
}
2023-09-07 18:21:03 +02:00
ScriptCommandEvent : : ScriptCommandEvent ( unsigned int eventNum , int numArgs )
2023-10-01 22:47:25 +02:00
: Event ( eventNum , numArgs )
2023-02-02 23:48:51 +01:00
{
2023-10-01 22:47:25 +02:00
fromScript = true ;
2023-02-02 23:48:51 +01:00
}
ScriptVMStack : : ScriptVMStack ( )
2023-07-05 21:23:39 +02:00
: localStack ( nullptr )
, stackBottom ( nullptr )
, pTop ( nullptr )
2024-06-22 19:03:27 +02:00
, m_bMarkStack ( false )
2023-07-05 21:23:39 +02:00
{ }
2023-02-02 23:48:51 +01:00
ScriptVMStack : : ScriptVMStack ( size_t stackSize )
2023-11-27 19:30:40 +01:00
: ScriptVMStack ( )
2023-02-02 23:48:51 +01:00
{
2023-11-27 19:30:40 +01:00
Allocate ( stackSize ) ;
2023-02-02 23:48:51 +01:00
}
ScriptVMStack : : ScriptVMStack ( ScriptVMStack & & other )
2023-07-05 21:23:39 +02:00
: localStack ( other . localStack )
, stackBottom ( other . stackBottom )
, pTop ( other . pTop )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
other . localStack = other . stackBottom = nullptr ;
other . pTop = nullptr ;
2023-02-02 23:48:51 +01:00
}
ScriptVMStack & ScriptVMStack : : operator = ( ScriptVMStack & & other )
{
2023-07-05 21:23:39 +02:00
localStack = other . localStack ;
stackBottom = other . stackBottom ;
pTop = other . pTop ;
other . localStack = other . stackBottom = nullptr ;
other . pTop = nullptr ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
return * this ;
2023-02-02 23:48:51 +01:00
}
ScriptVMStack : : ~ ScriptVMStack ( )
2023-11-27 19:30:40 +01:00
{
Free ( ) ;
}
void ScriptVMStack : : Allocate ( size_t stackSize )
{
if ( localStack ) {
// free the current local stack
Free ( ) ;
}
if ( ! stackSize ) {
stackSize = 1 ;
}
// allocate at once
uint8_t * data = ( uint8_t * ) gi . Malloc ( ( sizeof ( ScriptVariable ) + sizeof ( ScriptVariable * ) ) * stackSize ) ;
localStack = new ( data ) ScriptVariable [ stackSize ] ;
data + = sizeof ( ScriptVariable ) * stackSize ;
pTop = localStack ;
stackBottom = localStack + stackSize ;
}
void ScriptVMStack : : Free ( )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
const size_t localStackSize = GetStackSize ( ) ;
for ( uintptr_t i = 0 ; i < localStackSize ; + + i ) {
localStack [ i ] . ~ ScriptVariable ( ) ;
}
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
uint8_t * const data = ( uint8_t * ) localStack ;
if ( data ) {
gi . Free ( data ) ;
}
2023-02-02 23:48:51 +01:00
}
size_t ScriptVMStack : : GetStackSize ( ) const
{
2023-07-05 21:23:39 +02:00
return stackBottom - localStack ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : SetTop ( ScriptVariable & newTop )
{
2023-07-05 21:23:39 +02:00
return * ( pTop = & newTop ) ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : GetTop ( ) const
{
2024-06-22 19:03:27 +02:00
assert ( m_bMarkStack | | pTop < stackBottom ) ;
2023-07-05 21:23:39 +02:00
return * pTop ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : GetTop ( size_t offset ) const
{
2024-06-22 19:03:27 +02:00
assert ( m_bMarkStack | | ( pTop + offset ) < stackBottom ) ;
2023-07-05 21:23:39 +02:00
return * ( pTop + offset ) ;
2023-02-02 23:48:51 +01:00
}
2023-07-05 21:23:39 +02:00
ScriptVariable * ScriptVMStack : : GetTopPtr ( ) const
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
return pTop ;
2023-02-02 23:48:51 +01:00
}
2023-07-05 21:23:39 +02:00
ScriptVariable * ScriptVMStack : : GetTopPtr ( size_t offset ) const
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
return pTop + offset ;
2023-02-02 23:48:51 +01:00
}
2023-07-05 21:23:39 +02:00
ScriptVariable * ScriptVMStack : : GetTopArray ( size_t offset ) const
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
return pTop + offset ;
2023-02-02 23:48:51 +01:00
}
uintptr_t ScriptVMStack : : GetIndex ( ) const
{
2023-07-05 21:23:39 +02:00
return pTop - localStack ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : Pop ( )
{
2023-07-05 21:23:39 +02:00
return * ( pTop - - ) ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : Pop ( size_t offset )
{
2023-07-05 21:23:39 +02:00
ScriptVariable & old = * pTop ;
pTop - = offset ;
return old ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : PopAndGet ( )
{
2023-07-05 21:23:39 +02:00
return * - - pTop ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : PopAndGet ( size_t offset )
{
2023-07-05 21:23:39 +02:00
pTop - = offset ;
return * pTop ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : Push ( )
{
2024-06-22 19:03:27 +02:00
assert ( ! m_bMarkStack & & ( pTop + 1 ) < stackBottom ) ;
2023-07-05 21:23:39 +02:00
return * ( pTop + + ) ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : Push ( size_t offset )
{
2023-07-05 21:23:39 +02:00
ScriptVariable & old = * pTop ;
2024-06-22 19:03:27 +02:00
assert ( ! m_bMarkStack & & ( pTop + offset ) < stackBottom ) ;
2023-07-05 21:23:39 +02:00
pTop + = offset ;
return old ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : PushAndGet ( )
{
2024-06-22 19:03:27 +02:00
assert ( ! m_bMarkStack & & ( pTop + 1 ) < stackBottom ) ;
2023-07-05 21:23:39 +02:00
return * + + pTop ;
2023-02-02 23:48:51 +01:00
}
ScriptVariable & ScriptVMStack : : PushAndGet ( size_t offset )
{
2024-06-22 19:03:27 +02:00
assert ( ! m_bMarkStack & & ( pTop + offset ) < stackBottom ) ;
2023-07-05 21:23:39 +02:00
pTop + = offset ;
return * pTop ;
2023-02-02 23:48:51 +01:00
}
2023-11-27 19:30:40 +01:00
void ScriptVMStack : : Archive ( Archiver & arc )
{
unsigned int size ;
unsigned int offset ;
2023-11-28 19:14:09 +01:00
unsigned int numVars ;
2023-11-27 19:30:40 +01:00
unsigned int i ;
if ( arc . Saving ( ) ) {
size = stackBottom - localStack ;
offset = pTop - localStack ;
2023-11-28 19:14:09 +01:00
numVars = offset + 1 ;
2023-11-27 19:30:40 +01:00
arc . ArchiveUnsigned ( & size ) ;
arc . ArchiveUnsigned ( & offset ) ;
} else {
arc . ArchiveUnsigned ( & size ) ;
arc . ArchiveUnsigned ( & offset ) ;
2023-11-28 19:14:09 +01:00
numVars = offset + 1 ;
2023-11-27 19:30:40 +01:00
Allocate ( size ) ;
pTop = localStack + offset ;
}
if ( localStack ) {
2023-11-28 19:14:09 +01:00
for ( i = 0 ; i < numVars ; i + + ) {
2023-11-27 19:30:40 +01:00
localStack [ i ] . ArchiveInternal ( arc ) ;
}
}
}
2023-02-02 23:48:51 +01:00
void ScriptVMStack : : MoveTop ( ScriptVariable & & other )
{
2023-07-05 21:23:39 +02:00
* pTop = std : : move ( other ) ;
2023-02-02 23:48:51 +01:00
}
2023-01-29 20:59:31 +01:00
//====================
// ScriptVM
//====================
2023-01-30 17:11:44 +01:00
MEM_BlockAlloc < ScriptVM > ScriptVM_allocator ;
2023-01-29 20:59:31 +01:00
/*
= = = = = = = = = = = = = = = = = = = =
new ScriptVM
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
void * ScriptVM : : operator new ( size_t size )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
return ScriptVM_allocator . Alloc ( ) ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
delete ptr
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
void ScriptVM : : operator delete ( void * ptr )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
ScriptVM_allocator . Free ( ptr ) ;
2023-01-29 20:59:31 +01:00
}
2023-11-27 19:30:40 +01:00
/*
= = = = = = = = = = = = = = = = = = = =
ScriptVM
= = = = = = = = = = = = = = = = = = = =
*/
ScriptVM : : ScriptVM ( )
{
m_Stack = NULL ;
m_PrevCodePos = NULL ;
m_pOldData = NULL ;
m_OldDataSize = 0 ;
m_StackPos = NULL ;
}
2023-01-29 20:59:31 +01:00
/*
= = = = = = = = = = = = = = = = = = = =
ScriptVM
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
ScriptVM : : ScriptVM ( ScriptClass * scriptClass , unsigned char * pCodePos , ScriptThread * thread )
: m_VMStack ( scriptClass - > GetScript ( ) - > GetRequiredStackSize ( ) )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
next = NULL ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_Thread = thread ;
m_ScriptClass = scriptClass ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_Stack = NULL ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_PrevCodePos = NULL ;
m_CodePos = pCodePos ;
2023-01-29 20:59:31 +01:00
2023-11-01 16:52:30 +01:00
state = STATE_EXECUTION ;
2023-07-05 21:23:39 +02:00
m_ThreadState = THREAD_RUNNING ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_pOldData = NULL ;
m_OldDataSize = 0 ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_StackPos = NULL ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_ScriptClass - > AddThread ( this ) ;
2023-10-26 20:13:07 +02:00
if ( g_scripttrace - > integer & & CanScriptTracePrint ( ) ) {
gi . DPrintf2 ( " +++THREAD: %p %p \n " , this , m_ScriptClass ) ;
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
~ ScriptVM
= = = = = = = = = = = = = = = = = = = =
*/
ScriptVM : : ~ ScriptVM ( )
{
2023-07-05 21:23:39 +02:00
fastEvent . data = m_pOldData ;
fastEvent . dataSize = m_OldDataSize ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
// clean-up the call stack
while ( callStack . NumObjects ( ) ) {
LeaveFunction ( ) ;
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
Archive
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : Archive ( Archiver & arc )
{
2023-07-05 21:23:39 +02:00
int stack = 0 ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( arc . Saving ( ) ) {
if ( m_Stack ) {
stack = m_Stack - > m_Count ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
arc . ArchiveInteger ( & stack ) ;
} else {
arc . ArchiveInteger ( & stack ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( stack ) {
m_Stack = new ScriptStack ;
m_Stack - > m_Array = new ScriptVariable [ stack ] ;
m_Stack - > m_Count = stack ;
2023-11-27 19:30:40 +01:00
} else {
m_Stack = NULL ;
2023-07-05 21:23:39 +02:00
}
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
for ( int i = 1 ; i < = stack ; i + + ) {
m_Stack - > m_Array [ i ] . ArchiveInternal ( arc ) ;
}
m_ReturnValue . ArchiveInternal ( arc ) ;
m_ScriptClass - > ArchiveCodePos ( arc , & m_PrevCodePos ) ;
m_ScriptClass - > ArchiveCodePos ( arc , & m_CodePos ) ;
arc . ArchiveByte ( & state ) ;
arc . ArchiveByte ( & m_ThreadState ) ;
2023-11-27 19:30:40 +01:00
m_VMStack . Archive ( arc ) ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
error
Triggers an error
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
void ScriptVM : : error ( const char * format , . . . )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
char buffer [ 4000 ] ;
va_list va ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
va_start ( va , format ) ;
2024-09-20 21:53:48 +02:00
Q_vsnprintf ( buffer , sizeof ( buffer ) , format , va ) ;
2023-07-05 21:23:39 +02:00
va_end ( va ) ;
2023-01-29 20:59:31 +01:00
2024-08-24 18:49:36 +02:00
gi . Printf ( " ---------------------------------------------------------- \n %s \n " , buffer ) ;
2023-07-05 21:23:39 +02:00
m_ReturnValue . setStringValue ( " $.INTERRUPTED " ) ;
2023-01-29 20:59:31 +01:00
}
2023-08-13 17:59:49 +02:00
void ScriptVM : : jump ( unsigned int offset )
2023-01-29 20:59:31 +01:00
{
2023-10-01 22:47:25 +02:00
m_CodePos + = offset ;
2023-02-02 23:48:51 +01:00
}
2023-01-29 20:59:31 +01:00
2023-08-13 17:59:49 +02:00
void ScriptVM : : jumpBack ( unsigned int offset )
2023-02-02 23:48:51 +01:00
{
2023-10-01 22:47:25 +02:00
m_CodePos - = offset ;
2023-08-13 17:59:49 +02:00
}
void ScriptVM : : jumpBool ( unsigned int offset , bool booleanValue )
{
2023-10-01 22:47:25 +02:00
if ( booleanValue ) {
jump ( offset ) ;
}
2023-08-13 17:59:49 +02:00
}
bool ScriptVM : : jumpVar ( unsigned int offset , bool booleanValue )
{
2023-10-01 22:47:25 +02:00
if ( booleanValue ) {
jump ( offset ) ;
return true ;
} else {
2023-08-13 17:59:49 +02:00
m_VMStack . Pop ( ) ;
2023-10-01 22:47:25 +02:00
return false ;
}
2023-08-13 17:59:49 +02:00
}
void ScriptVM : : doJumpIf ( bool booleanValue )
{
2023-10-01 22:47:25 +02:00
const unsigned int offset = fetchOpcodeValue < unsigned int > ( ) ;
jumpBool ( offset , booleanValue ) ;
2023-08-13 17:59:49 +02:00
}
bool ScriptVM : : doJumpVarIf ( bool booleanValue )
{
2023-10-01 22:47:25 +02:00
const unsigned int offset = fetchOpcodeValue < unsigned int > ( ) ;
return jumpVar ( offset , booleanValue ) ;
2023-02-02 23:48:51 +01:00
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
void ScriptVM : : loadTopInternal ( Listener * listener )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
const const_str variable = fetchOpcodeValue < op_name_t > ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( ! executeSetter ( listener , variable ) ) {
// just set the variable
2023-10-01 22:47:25 +02:00
ScriptVariable & pTop = m_VMStack . GetTop ( ) ;
2023-08-17 19:51:53 +02:00
listener - > Vars ( ) - > SetVariable ( variable , std : : move ( pTop ) ) ;
2023-07-05 21:23:39 +02:00
}
2023-02-02 23:48:51 +01:00
}
2023-07-05 21:23:39 +02:00
ScriptVariable * ScriptVM : : storeTopInternal ( Listener * listener )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
const const_str variable = fetchOpcodeValue < op_name_t > ( ) ;
ScriptVariable * listenerVar ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
if ( ! executeGetter ( listener , variable ) ) {
2023-10-01 22:47:25 +02:00
ScriptVariable & pTop = m_VMStack . GetTop ( ) ;
listenerVar = listener - > Vars ( ) - > GetOrCreateVariable ( variable ) ;
2023-07-05 21:23:39 +02:00
pTop = * listenerVar ;
} else {
listenerVar = nullptr ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
return listenerVar ;
2023-02-02 23:48:51 +01:00
}
2023-10-01 22:47:25 +02:00
void ScriptVM : : loadStoreTop ( Listener * listener )
2023-08-13 20:17:59 +02:00
{
const const_str variable = fetchOpcodeValue < op_name_t > ( ) ;
if ( ! executeSetter ( listener , variable ) ) {
// just set the variable
ScriptVariable & pTop = m_VMStack . GetTop ( ) ;
2023-08-17 19:51:53 +02:00
listener - > Vars ( ) - > SetVariable ( variable , pTop ) ;
2023-08-13 20:17:59 +02:00
}
}
2023-08-17 16:07:38 +02:00
void ScriptVM : : skipField ( )
{
m_CodePos + = sizeof ( unsigned int ) ;
}
2023-02-07 20:50:09 +01:00
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : loadTop < false > ( Listener * listener )
2023-02-07 20:50:09 +01:00
{
2023-07-05 21:23:39 +02:00
loadTopInternal ( listener ) ;
m_VMStack . Pop ( ) ;
2023-02-07 20:50:09 +01:00
}
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : loadTop < true > ( Listener * listener )
2023-02-07 20:50:09 +01:00
{
2023-07-05 21:23:39 +02:00
loadTopInternal ( listener ) ;
2023-02-07 20:50:09 +01:00
}
template < >
2023-07-05 21:23:39 +02:00
ScriptVariable * ScriptVM : : storeTop < false > ( Listener * listener )
2023-02-07 20:50:09 +01:00
{
2023-07-05 21:23:39 +02:00
m_VMStack . Push ( ) ;
2023-02-07 20:50:09 +01:00
2023-07-05 21:23:39 +02:00
return storeTopInternal ( listener ) ;
2023-02-07 20:50:09 +01:00
}
template < >
2023-07-05 21:23:39 +02:00
ScriptVariable * ScriptVM : : storeTop < true > ( Listener * listener )
2023-02-07 20:50:09 +01:00
{
2023-07-05 21:23:39 +02:00
return storeTopInternal ( listener ) ;
2023-02-07 20:50:09 +01:00
}
2023-02-02 23:48:51 +01:00
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : executeCommandInternal < false > (
Event & ev , Listener * listener , ScriptVariable * fromVar , op_parmNum_t iParamCount
)
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
transferVarsToEvent ( ev , fromVar , iParamCount ) ;
2025-01-16 23:25:26 +01:00
checkValidEvent ( ev , listener ) ;
2023-07-05 21:23:39 +02:00
listener - > ProcessScriptEvent ( ev ) ;
2023-02-02 23:48:51 +01:00
}
2023-01-29 20:59:31 +01:00
2023-02-02 23:48:51 +01:00
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : executeCommandInternal < true > (
Event & ev , Listener * listener , ScriptVariable * fromVar , op_parmNum_t iParamCount
)
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
transferVarsToEvent ( ev , fromVar , iParamCount ) ;
2025-01-16 23:25:26 +01:00
checkValidEvent ( ev , listener ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
try {
listener - > ProcessScriptEvent ( ev ) ;
} catch ( . . . ) {
m_VMStack . GetTop ( ) . Clear ( ) ;
throw ;
}
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
ScriptVariable & pTop = m_VMStack . GetTop ( ) ;
2023-11-14 00:16:09 +01:00
pTop = std : : move ( ev . GetValue ( ) ) ;
2023-01-29 20:59:31 +01:00
}
2023-02-02 23:48:51 +01:00
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : executeCommand < false , false > ( Listener * listener , op_parmNum_t iParamCount , op_evName_t eventnum )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
ScriptCommandEvent ev = iParamCount ? ScriptCommandEvent ( eventnum , iParamCount ) : ScriptCommandEvent ( eventnum ) ;
return executeCommandInternal < false > ( ev , listener , m_VMStack . GetTopArray ( 1 ) , iParamCount ) ;
2023-02-02 23:48:51 +01:00
}
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : executeCommand < true , false > ( Listener * listener , op_parmNum_t iParamCount , op_evName_t eventnum )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
ScriptCommandEvent ev = iParamCount ? ScriptCommandEvent ( eventnum , iParamCount ) : ScriptCommandEvent ( eventnum ) ;
return executeCommandInternal < false > ( ev , listener , m_VMStack . GetTopArray ( 1 ) , iParamCount ) ;
2023-02-02 23:48:51 +01:00
}
2023-01-29 20:59:31 +01:00
2023-02-02 23:48:51 +01:00
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : executeCommand < false , true > ( Listener * listener , op_parmNum_t iParamCount , op_evName_t eventnum )
2023-02-02 23:48:51 +01:00
{
2023-11-14 00:16:09 +01:00
ScriptCommandEvent ev = iParamCount ? ScriptCommandEvent ( eventnum , iParamCount ) : ScriptCommandEvent ( eventnum ) ;
2023-07-05 21:23:39 +02:00
return executeCommandInternal < true > ( ev , listener , m_VMStack . GetTopArray ( ) , iParamCount ) ;
2023-02-02 23:48:51 +01:00
}
template < >
2023-07-05 21:23:39 +02:00
void ScriptVM : : executeCommand < true , true > ( Listener * listener , op_parmNum_t iParamCount , op_evName_t eventnum )
2023-02-02 23:48:51 +01:00
{
2023-11-14 00:16:09 +01:00
ScriptCommandEvent ev = iParamCount ? ScriptCommandEvent ( eventnum , iParamCount ) : ScriptCommandEvent ( eventnum ) ;
2023-07-05 21:23:39 +02:00
return executeCommandInternal < true > ( ev , listener , m_VMStack . GetTopArray ( ) , iParamCount ) ;
2023-02-02 23:48:51 +01:00
}
2023-07-05 21:23:39 +02:00
void ScriptVM : : transferVarsToEvent ( Event & ev , ScriptVariable * fromVar , op_parmNum_t count )
2023-02-02 23:48:51 +01:00
{
2023-11-02 19:53:26 +01:00
ev . CopyValues ( fromVar , count ) ;
2023-02-02 23:48:51 +01:00
}
2023-01-29 20:59:31 +01:00
2025-01-16 23:25:26 +01:00
void ScriptVM : : checkValidEvent ( Event & ev , Listener * listener ) {
ClassDef * c = listener - > classinfo ( ) ;
if ( ! c - > GetDef ( & ev ) ) {
if ( listener = = m_Thread ) {
ScriptError ( " Failed execution of command '%s' " , ev . getName ( ) ) ;
} else if ( listener - > isSubclassOf ( SimpleEntity ) ) {
ScriptError ( " Failed execution of command '%s' for class '%s' Targetname '%s' " , ev . getName ( ) , c - > classname , static_cast < SimpleEntity * > ( listener ) - > targetname . c_str ( ) ) ;
} else {
ScriptError ( " Failed execution of command '%s' for class '%s' " , ev . getName ( ) , c - > classname ) ;
}
}
}
2023-07-05 21:23:39 +02:00
bool ScriptVM : : executeGetter ( Listener * listener , op_evName_t eventName )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
int eventNum = Event : : FindGetterEventNum ( eventName ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( eventNum & & listener - > classinfo ( ) - > GetDef ( eventNum ) ) {
ScriptCommandEvent ev ( eventNum ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
listener - > ProcessScriptEvent ( ev ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
ScriptVariable & pTop = m_VMStack . GetTop ( ) ;
2023-11-14 00:16:09 +01:00
pTop = std : : move ( ev . GetValue ( ) ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
return true ;
} else {
eventNum = Event : : FindSetterEventNum ( eventName ) ;
assert ( ! eventNum | | ! listener - > classinfo ( ) - > GetDef ( eventNum ) ) ;
if ( eventNum & & listener - > classinfo ( ) - > GetDef ( eventNum ) ) {
ScriptError ( " Cannot set a read-only variable " ) ;
}
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
return false ;
2023-01-29 20:59:31 +01:00
}
2023-07-05 21:23:39 +02:00
bool ScriptVM : : executeSetter ( Listener * listener , op_evName_t eventName )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
int eventNum = Event : : FindSetterEventNum ( eventName ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( eventNum & & listener - > classinfo ( ) - > GetDef ( eventNum ) ) {
ScriptCommandEvent ev ( eventNum , 1 ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
ScriptVariable & pTop = m_VMStack . GetTop ( ) ;
2023-11-02 19:53:26 +01:00
ev . CopyValues ( & pTop , 1 ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
listener - > ProcessScriptEvent ( ev ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
return true ;
} else {
eventNum = Event : : FindSetterEventNum ( eventName ) ;
assert ( ! eventNum | | ! listener - > classinfo ( ) - > GetDef ( eventNum ) ) ;
if ( eventNum & & listener - > classinfo ( ) - > GetDef ( eventNum ) ) {
ScriptError ( " Cannot get a write-only variable " ) ;
}
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
return false ;
2023-01-29 20:59:31 +01:00
}
2023-02-02 23:48:51 +01:00
void ScriptVM : : execCmdCommon ( op_parmNum_t param )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
const op_ev_t eventNum = fetchOpcodeValue < op_ev_t > ( ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
m_VMStack . Pop ( param ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
executeCommand ( m_Thread , param , eventNum ) ;
2023-01-29 20:59:31 +01:00
}
2023-02-02 23:48:51 +01:00
void ScriptVM : : execCmdMethodCommon ( op_parmNum_t param )
2023-01-29 20:59:31 +01:00
{
2023-10-01 22:47:25 +02:00
const ScriptVariable & a = m_VMStack . Pop ( ) ;
const op_ev_t eventNum = fetchOpcodeValue < op_ev_t > ( ) ;
2023-07-05 21:23:39 +02:00
m_VMStack . Pop ( param ) ;
const size_t arraysize = a . arraysize ( ) ;
if ( arraysize = = ( size_t ) - 1 ) {
2023-09-07 18:05:49 +02:00
throw ScriptException ( " command '%s' applied to NIL " , Event : : GetEventName ( eventNum ) ) ;
2023-07-05 21:23:39 +02:00
}
if ( arraysize > 1 ) {
2023-10-01 22:47:25 +02:00
if ( a . IsConstArray ( ) ) {
2023-08-17 03:04:01 +02:00
// copy the variable
// because if it's a targetlist, the container object can be modified
// while iterating
2023-10-01 22:47:25 +02:00
ScriptVariable array = a ;
array . CastConstArrayValue ( ) ;
2023-08-17 03:04:01 +02:00
for ( uintptr_t i = arraysize ; i > 0 ; i - - ) {
Listener * const listener = array . listenerAt ( i ) ;
2023-07-05 21:23:39 +02:00
// if the listener is NULL, don't throw an exception
// it would be unfair if the other listeners executed the command
if ( listener ) {
executeCommand < true > ( listener , param , eventNum ) ;
}
}
} else {
ScriptVariable array = a ;
// must cast into a const array value
array . CastConstArrayValue ( ) ;
for ( uintptr_t i = array . arraysize ( ) ; i > 0 ; i - - ) {
2024-02-03 23:22:06 +01:00
Listener * const listener = array . listenerAt ( i ) ;
2023-07-05 21:23:39 +02:00
if ( listener ) {
executeCommand < true > ( listener , param , eventNum ) ;
}
}
}
} else {
// avoid useless allocations of const array
Listener * const listener = a . listenerValue ( ) ;
if ( ! listener ) {
2023-09-07 18:05:49 +02:00
throw ScriptException ( " command '%s' applied to NULL listener " , Event : : GetEventName ( eventNum ) ) ;
2023-07-05 21:23:39 +02:00
}
executeCommand < true > ( listener , param , eventNum ) ;
}
2023-01-29 20:59:31 +01:00
}
2023-02-02 23:48:51 +01:00
void ScriptVM : : execMethodCommon ( op_parmNum_t param )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
const ScriptVariable & a = m_VMStack . Pop ( ) ;
const op_ev_t eventNum = fetchOpcodeValue < op_ev_t > ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_VMStack . Pop ( param ) ;
// push the return value
m_VMStack . Push ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
Listener * const listener = a . listenerValue ( ) ;
if ( ! listener ) {
2023-08-30 23:34:29 +02:00
m_VMStack . GetTop ( ) . Clear ( ) ;
2023-09-07 18:05:49 +02:00
throw ScriptException ( " command '%s' applied to NULL listener " , Event : : GetEventName ( eventNum ) ) ;
2023-07-05 21:23:39 +02:00
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
executeCommand < true , true > ( listener , param , eventNum ) ;
2023-01-29 20:59:31 +01:00
}
2023-02-02 23:48:51 +01:00
void ScriptVM : : execFunction ( ScriptMaster & Director )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
if ( ! fetchOpcodeValue < bool > ( ) ) {
const op_name_t label = fetchOpcodeValue < op_name_t > ( ) ;
const op_parmNum_t params = fetchOpcodeValue < op_parmNum_t > ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
Listener * listener ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
try {
listener = m_VMStack . GetTop ( ) . listenerValue ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( ! listener ) {
const str & labelName = Director . GetString ( label ) ;
throw ScriptException ( " function ' " + labelName + " ' applied to NULL listener " ) ;
}
} catch ( . . . ) {
m_VMStack . Pop ( params ) ;
throw ;
}
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
m_VMStack . Pop ( ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
Container < ScriptVariable > data ;
data . Resize ( params + 1 ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
ScriptVariable * labelVar = & data . ObjectAt ( data . AddObject ( ScriptVariable ( ) ) ) ;
labelVar - > setConstStringValue ( label ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
const ScriptVariable * var = & m_VMStack . Pop ( params ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
for ( int i = 0 ; i < params ; var + + , i + + ) {
data . AddObject ( * var ) ;
}
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
m_VMStack . Push ( ) ;
EnterFunction ( std : : move ( data ) ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
GetScriptClass ( ) - > m_Self = listener ;
} else {
const op_name_t filename = fetchOpcodeValue < op_name_t > ( ) ;
const op_name_t label = fetchOpcodeValue < op_name_t > ( ) ;
const op_parmNum_t params = fetchOpcodeValue < op_parmNum_t > ( ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
Listener * listener ;
try {
listener = m_VMStack . GetTop ( ) . listenerValue ( ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
if ( ! listener ) {
const str & labelStr = Director . GetString ( label ) ;
const str & fileStr = Director . GetString ( filename ) ;
throw ScriptException ( " function ' " + labelStr + " ' in ' " + fileStr + " ' applied to NULL listener " ) ;
}
} catch ( . . . ) {
m_VMStack . Pop ( params ) ;
throw ;
}
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
m_VMStack . Pop ( ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
ScriptVariable constarray ;
ScriptVariable * pVar = new ScriptVariable [ 2 ] ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
pVar [ 0 ] . setConstStringValue ( filename ) ;
pVar [ 1 ] . setConstStringValue ( label ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
constarray . setConstArrayValue ( pVar , 2 ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
delete [ ] pVar ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
Event ev ( EV_Listener_WaitCreateReturnThread ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
const ScriptVariable * var = & m_VMStack . Pop ( params ) ;
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
for ( int i = 0 ; i < params ; var + + , i + + ) {
ev . AddValue ( * var ) ;
}
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) = listener - > ProcessEventReturn ( & ev ) ;
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
ProgBuffer
Returns the current program buffer
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
unsigned char * ScriptVM : : ProgBuffer ( void )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
return m_CodePos ;
2023-01-29 20:59:31 +01:00
}
2023-10-27 20:00:48 +02:00
/*
= = = = = = = = = = = = = = = = = = = =
ScriptTrace1
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : ScriptTrace1 ( ) const
{
GameScript * scr ;
str sourceLine ;
int column ;
int line ;
scr = GetScript ( ) ;
if ( ! scr - > GetSourceAt ( m_CodePos , & sourceLine , column , line ) ) {
return ;
}
if ( currentScriptFile = = this & & line = = currentScriptLine ) {
return ;
}
currentScriptFile = this ;
currentScriptLine = line ;
gi . DPrintf2 ( " %s (%s, %d, %p, %d) \n " , sourceLine . c_str ( ) , Filename ( ) . c_str ( ) , line , this , m_VMStack . GetIndex ( ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
ScriptTrace2
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : ScriptTrace2 ( ) const
{
gi . DPrintf2 ( " %s, %p, %d \n " , OpcodeName ( * m_CodePos ) , this , m_VMStack . GetIndex ( ) ) ;
GetScript ( ) - > PrintSourcePos ( m_CodePos , true ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
GetSourcePos
= = = = = = = = = = = = = = = = = = = =
*/
const char * ScriptVM : : GetSourcePos ( ) const
{
static str debugLine ;
str sourceLine ;
int column ;
int line ;
debugLine =
str ( OpcodeName ( * m_CodePos ) ) + " @ " + str ( m_CodePos - GetScript ( ) - > m_ProgBuffer ) + " in " + Filename ( ) + " \n " ;
if ( GetScript ( ) - > GetSourceAt ( m_CodePos , & sourceLine , column , line ) ) {
debugLine + = str ( " ( " ) + str ( line ) + str ( " ) \n " ) ;
}
return debugLine . c_str ( ) ;
}
2023-01-29 20:59:31 +01:00
/*
= = = = = = = = = = = = = = = = = = = =
EnterFunction
Sets a new instruction pointer
= = = = = = = = = = = = = = = = = = = =
*/
2023-02-02 23:48:51 +01:00
void ScriptVM : : EnterFunction ( Container < ScriptVariable > & & )
2023-01-29 20:59:31 +01:00
{
2023-02-02 23:48:51 +01:00
#if 0
2023-01-29 20:59:31 +01:00
ScriptCallStack * stack ;
str label = ev - > GetString ( 1 ) ;
SetFastData ( ev - > data + 1 , ev - > dataSize - 1 ) ;
unsigned char * codePos = m_ScriptClass - > FindLabel ( label ) ;
if ( ! codePos )
{
ScriptError ( " ScriptVM::EnterFunction: label '%s' does not exist in '%s'. " , label . c_str ( ) , Filename ( ) . c_str ( ) ) ;
}
stack = new ScriptCallStack ;
stack - > codePos = m_CodePos ;
2023-02-02 23:48:51 +01:00
stack - > pTop = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
stack - > returnValue = m_ReturnValue ;
stack - > localStack = localStack ;
stack - > m_Self = m_ScriptClass - > GetSelf ( ) ;
callStack . AddObject ( stack ) ;
m_CodePos = codePos ;
localStack = new ScriptVariable [ localStackSize ] ;
pTop = localStack ;
m_ReturnValue . Clear ( ) ;
2023-02-02 23:48:51 +01:00
# endif
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
LeaveFunction
Returns to the previous function
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : LeaveFunction ( )
{
2023-02-02 23:48:51 +01:00
#if 0
2023-01-29 20:59:31 +01:00
int num = callStack . NumObjects ( ) ;
if ( num )
{
ScriptCallStack * stack = callStack . ObjectAt ( num ) ;
pTop = stack - > pTop ;
* pTop = m_ReturnValue ;
m_CodePos = stack - > codePos ;
m_ReturnValue = stack - > returnValue ;
m_ScriptClass - > m_Self = stack - > m_Self ;
delete [ ] localStack ;
localStack = stack - > localStack ;
delete stack ;
callStack . RemoveObjectAt ( num ) ;
}
else
{
delete m_Thread ;
}
2023-02-02 23:48:51 +01:00
# else
2023-07-05 21:23:39 +02:00
delete m_Thread ;
2023-02-02 23:48:51 +01:00
# endif
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
End
End with a return value
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : End ( const ScriptVariable & returnValue )
{
2023-07-05 21:23:39 +02:00
m_ReturnValue . setPointer ( returnValue ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
LeaveFunction ( ) ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
End
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : End ( )
{
2023-07-05 21:23:39 +02:00
m_ReturnValue . ClearPointer ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
LeaveFunction ( ) ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
Execute
Executes a program
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
void ScriptVM : : Execute ( ScriptVariable * data , int dataSize , str label )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
unsigned char * opcode ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
ScriptVariable * a ;
ScriptVariable * b ;
ScriptVariable * c ;
2023-01-29 20:59:31 +01:00
2023-10-31 20:39:28 +01:00
op_name_t fieldNameIndex ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
Listener * listener ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
Event ev ;
ScriptVariable * var = NULL ;
2023-01-29 20:59:31 +01:00
2024-10-22 20:05:53 +02:00
TargetList * targetList ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( Director . stackCount > = MAX_STACK_DEPTH ) {
state = STATE_EXECUTION ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
ScriptException : : next_abort = - 1 ;
2023-11-01 16:52:30 +01:00
throw ScriptException ( " stack overflow " ) ;
}
if ( label . length ( ) ) {
// Throw if label is not found
m_CodePos = m_ScriptClass - > FindLabel ( label ) ;
if ( ! m_CodePos ) {
ScriptError ( " ScriptVM::Execute: label '%s' does not exist in '%s'. " , label . c_str ( ) , Filename ( ) . c_str ( ) ) ;
}
}
2023-01-29 20:59:31 +01:00
2023-11-01 16:52:30 +01:00
if ( g_scripttrace - > integer & & CanScriptTracePrint ( ) ) {
gi . DPrintf2 (
" +++FRAME: %i (%p) +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \n " ,
Director . stackCount ,
this
) ;
2023-07-05 21:23:39 +02:00
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
Director . stackCount + + ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( dataSize ) {
SetFastData ( data , dataSize ) ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
state = STATE_RUNNING ;
2023-01-29 20:59:31 +01:00
2023-11-01 16:52:30 +01:00
while ( state = = STATE_RUNNING ) {
if ( g_scripttrace - > integer & & CanScriptTracePrint ( ) ) {
switch ( g_scripttrace - > integer ) {
case 1 :
case 3 :
ScriptTrace1 ( ) ;
break ;
case 2 :
case 4 :
ScriptTrace2 ( ) ;
break ;
}
}
2023-07-05 21:23:39 +02:00
m_PrevCodePos = m_CodePos ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
try {
2024-06-22 19:03:27 +02:00
if ( ! m_VMStack . m_bMarkStack ) {
2023-07-05 21:23:39 +02:00
/*
2023-01-29 20:59:31 +01:00
assert ( pTop > = localStack & & pTop < localStack + localStackSize ) ;
if ( pTop < localStack )
{
deleteThread = true ;
state = STATE_EXECUTION ;
error ( " VM stack error. Negative stack value %d. \n " , pTop - localStack ) ;
break ;
}
else if ( pTop > = localStack + localStackSize )
{
deleteThread = true ;
state = STATE_EXECUTION ;
error ( " VM stack error. Exceeded the maximum stack size %d. \n " , localStackSize ) ;
break ;
}
2023-02-02 23:48:51 +01:00
*/
2023-07-05 21:23:39 +02:00
}
2023-10-01 22:47:25 +02:00
2023-07-05 21:23:39 +02:00
opcode = m_CodePos + + ;
switch ( * opcode ) {
case OP_BIN_BITWISE_AND :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
* b & = * a ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_BITWISE_OR :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
* b | = * a ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_BITWISE_EXCL_OR :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
* b ^ = * a ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_EQUALITY :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
b - > setIntValue ( * b = = * a ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_INEQUALITY :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
b - > setIntValue ( * b ! = * a ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_GREATER_THAN :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
b - > greaterthan ( * a ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_GREATER_THAN_OR_EQUAL :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
b - > greaterthanorequal ( * a ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_LESS_THAN :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
b - > lessthan ( * a ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_LESS_THAN_OR_EQUAL :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
b - > lessthanorequal ( * a ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_PLUS :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
* b + = * a ;
break ;
case OP_BIN_MINUS :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
* b - = * a ;
break ;
case OP_BIN_MULTIPLY :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
* b * = * a ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_DIVIDE :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
* b / = * a ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_BIN_PERCENTAGE :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
* b % = * a ;
break ;
case OP_BIN_SHIFT_LEFT :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
* b < < = * a ;
break ;
case OP_BIN_SHIFT_RIGHT :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . GetTop ( ) ;
* b > > = * a ;
break ;
case OP_BOOL_JUMP_FALSE4 :
2023-10-01 22:47:25 +02:00
doJumpIf ( ! m_VMStack . Pop ( ) . m_data . intValue ) ;
break ;
2023-07-05 21:23:39 +02:00
2023-10-01 22:47:25 +02:00
case OP_BOOL_JUMP_TRUE4 :
doJumpIf ( m_VMStack . Pop ( ) . m_data . intValue ) ;
break ;
2023-07-05 21:23:39 +02:00
2023-10-01 22:47:25 +02:00
case OP_VAR_JUMP_FALSE4 :
doJumpIf ( ! m_VMStack . Pop ( ) . booleanValue ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
2023-10-01 22:47:25 +02:00
case OP_VAR_JUMP_TRUE4 :
doJumpIf ( m_VMStack . Pop ( ) . booleanValue ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_BOOL_LOGICAL_AND :
2023-10-01 22:47:25 +02:00
doJumpVarIf ( ! m_VMStack . GetTop ( ) . m_data . intValue ) ;
break ;
2023-07-05 21:23:39 +02:00
case OP_BOOL_LOGICAL_OR :
2023-10-01 22:47:25 +02:00
doJumpVarIf ( m_VMStack . GetTop ( ) . m_data . intValue ) ;
break ;
2023-07-05 21:23:39 +02:00
case OP_VAR_LOGICAL_AND :
2023-10-01 22:47:25 +02:00
if ( ! doJumpVarIf ( m_VMStack . GetTop ( ) . booleanValue ( ) ) ) {
2023-07-05 21:23:39 +02:00
m_VMStack . GetTop ( ) . SetFalse ( ) ;
2023-10-01 22:47:25 +02:00
}
break ;
2023-07-05 21:23:39 +02:00
case OP_VAR_LOGICAL_OR :
2023-10-01 22:47:25 +02:00
if ( ! doJumpVarIf ( ! m_VMStack . GetTop ( ) . booleanValue ( ) ) ) {
2023-07-05 21:23:39 +02:00
m_VMStack . GetTop ( ) . SetTrue ( ) ;
2023-10-01 22:47:25 +02:00
}
break ;
2023-07-05 21:23:39 +02:00
case OP_BOOL_STORE_FALSE :
m_VMStack . PushAndGet ( ) . SetFalse ( ) ;
break ;
case OP_BOOL_STORE_TRUE :
m_VMStack . PushAndGet ( ) . SetTrue ( ) ;
break ;
case OP_BOOL_UN_NOT :
m_VMStack . GetTop ( ) . m_data . intValue = ( m_VMStack . GetTop ( ) . m_data . intValue = = 0 ) ;
break ;
case OP_CALC_VECTOR :
c = & m_VMStack . Pop ( ) ;
b = & m_VMStack . Pop ( ) ;
a = & m_VMStack . GetTop ( ) ;
m_VMStack . GetTop ( ) . setVectorValue ( Vector ( a - > floatValue ( ) , b - > floatValue ( ) , c - > floatValue ( ) ) ) ;
break ;
case OP_EXEC_CMD0 :
{
execCmdCommon ( 0 ) ;
break ;
}
case OP_EXEC_CMD1 :
{
execCmdCommon ( 1 ) ;
break ;
}
case OP_EXEC_CMD2 :
{
execCmdCommon ( 2 ) ;
break ;
}
case OP_EXEC_CMD3 :
{
execCmdCommon ( 3 ) ;
break ;
}
case OP_EXEC_CMD4 :
{
execCmdCommon ( 4 ) ;
break ;
}
case OP_EXEC_CMD5 :
{
execCmdCommon ( 5 ) ;
break ;
}
case OP_EXEC_CMD_COUNT1 :
{
const op_parmNum_t numParms = fetchOpcodeValue < op_parmNum_t > ( ) ;
execCmdCommon ( numParms ) ;
break ;
}
case OP_EXEC_CMD_METHOD0 :
{
execCmdMethodCommon ( 0 ) ;
break ;
}
case OP_EXEC_CMD_METHOD1 :
{
execCmdMethodCommon ( 1 ) ;
break ;
}
case OP_EXEC_CMD_METHOD2 :
{
execCmdMethodCommon ( 2 ) ;
break ;
}
case OP_EXEC_CMD_METHOD3 :
{
execCmdMethodCommon ( 3 ) ;
break ;
}
case OP_EXEC_CMD_METHOD4 :
{
execCmdMethodCommon ( 4 ) ;
break ;
}
case OP_EXEC_CMD_METHOD5 :
{
execCmdMethodCommon ( 5 ) ;
break ;
}
case OP_EXEC_CMD_METHOD_COUNT1 :
{
const op_parmNum_t numParms = fetchOpcodeValue < op_parmNum_t > ( ) ;
execCmdMethodCommon ( numParms ) ;
break ;
}
case OP_EXEC_METHOD0 :
{
execMethodCommon ( 0 ) ;
break ;
}
case OP_EXEC_METHOD1 :
{
execMethodCommon ( 1 ) ;
break ;
}
case OP_EXEC_METHOD2 :
{
execMethodCommon ( 2 ) ;
break ;
}
case OP_EXEC_METHOD3 :
{
execMethodCommon ( 3 ) ;
break ;
}
case OP_EXEC_METHOD4 :
{
execMethodCommon ( 4 ) ;
break ;
}
case OP_EXEC_METHOD5 :
{
execMethodCommon ( 5 ) ;
break ;
}
case OP_EXEC_METHOD_COUNT1 :
{
const op_parmNum_t numParms = fetchOpcodeValue < op_parmNum_t > ( ) ;
execMethodCommon ( numParms ) ;
break ;
}
case OP_FUNC :
{
execFunction ( Director ) ;
break ;
}
2023-10-01 22:47:25 +02:00
case OP_JUMP4 :
jump ( fetchOpcodeValue < unsigned int > ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
2023-10-01 22:47:25 +02:00
case OP_JUMP_BACK4 :
jumpBack ( fetchActualOpcodeValue < unsigned int > ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_LOAD_ARRAY_VAR :
a = & m_VMStack . Pop ( ) ;
b = & m_VMStack . Pop ( ) ;
c = & m_VMStack . Pop ( ) ;
b - > setArrayAt ( * a , * c ) ;
break ;
case OP_LOAD_FIELD_VAR :
a = & m_VMStack . Pop ( ) ;
try {
2023-11-14 00:16:09 +01:00
try {
listener = a - > listenerValue ( ) ;
2023-07-05 21:23:39 +02:00
2023-11-14 00:16:09 +01:00
if ( listener = = NULL ) {
fieldNameIndex = fetchActualOpcodeValue < op_name_t > ( ) ;
ScriptError (
" Field '%s' applied to NULL listener " , Director . GetString ( fieldNameIndex ) . c_str ( )
) ;
}
} catch ( . . . ) {
skipField ( ) ;
throw ;
2023-07-05 21:23:39 +02:00
}
2023-11-14 00:16:09 +01:00
loadTop ( listener ) ;
} catch ( . . . ) {
2023-07-05 21:23:39 +02:00
m_VMStack . Pop ( ) ;
2023-11-14 00:16:09 +01:00
throw ;
2023-07-05 21:23:39 +02:00
}
break ;
case OP_LOAD_CONST_ARRAY1 :
{
op_arrayParmNum_t numParms = fetchOpcodeValue < op_arrayParmNum_t > ( ) ;
ScriptVariable & pTop = m_VMStack . PopAndGet ( numParms - 1 ) ;
pTop . setConstArrayValue ( & pTop , numParms ) ;
break ;
}
case OP_LOAD_GAME_VAR :
loadTop ( & game ) ;
break ;
case OP_LOAD_GROUP_VAR :
loadTop ( m_ScriptClass ) ;
break ;
case OP_LOAD_LEVEL_VAR :
loadTop ( & level ) ;
break ;
case OP_LOAD_LOCAL_VAR :
loadTop ( m_Thread ) ;
break ;
case OP_LOAD_OWNER_VAR :
if ( ! m_ScriptClass - > m_Self ) {
m_VMStack . Pop ( ) ;
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self is NULL " ) ;
}
if ( ! m_ScriptClass - > m_Self - > GetScriptOwner ( ) ) {
m_VMStack . Pop ( ) ;
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self.owner is NULL " ) ;
}
loadTop ( m_ScriptClass - > m_Self - > GetScriptOwner ( ) ) ;
break ;
case OP_LOAD_PARM_VAR :
loadTop ( & parm ) ;
break ;
case OP_LOAD_SELF_VAR :
if ( ! m_ScriptClass - > m_Self ) {
m_VMStack . Pop ( ) ;
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self is NULL " ) ;
}
loadTop ( m_ScriptClass - > m_Self ) ;
break ;
case OP_LOAD_STORE_GAME_VAR :
2023-08-13 20:17:59 +02:00
loadStoreTop ( & game ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_LOAD_STORE_GROUP_VAR :
2023-08-13 20:17:59 +02:00
loadStoreTop ( m_ScriptClass ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_LOAD_STORE_LEVEL_VAR :
2023-08-13 20:17:59 +02:00
loadStoreTop ( & level ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_LOAD_STORE_LOCAL_VAR :
2023-08-13 20:17:59 +02:00
loadStoreTop ( m_Thread ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_LOAD_STORE_OWNER_VAR :
if ( ! m_ScriptClass - > m_Self ) {
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self is NULL " ) ;
}
if ( ! m_ScriptClass - > m_Self - > GetScriptOwner ( ) ) {
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self.owner is NULL " ) ;
}
2023-08-13 20:17:59 +02:00
loadStoreTop ( m_ScriptClass - > m_Self - > GetScriptOwner ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_LOAD_STORE_PARM_VAR :
2023-08-13 20:17:59 +02:00
loadStoreTop ( & parm ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_LOAD_STORE_SELF_VAR :
if ( ! m_ScriptClass - > m_Self ) {
ScriptError ( " self is NULL " ) ;
}
2023-08-13 20:17:59 +02:00
loadStoreTop ( m_ScriptClass - > m_Self ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_MARK_STACK_POS :
m_StackPos = & m_VMStack . GetTop ( ) ;
2024-06-22 19:03:27 +02:00
m_VMStack . m_bMarkStack = true ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_PARAM :
if ( fastEvent . dataSize ) {
m_VMStack . SetTop ( * ( fastEvent . data + + ) ) ;
fastEvent . dataSize - - ;
} else {
m_VMStack . SetTop ( * ( m_StackPos + 1 ) ) ;
m_VMStack . GetTop ( ) . Clear ( ) ;
}
break ;
case OP_RESTORE_STACK_POS :
m_VMStack . SetTop ( * m_StackPos ) ;
2024-06-22 19:03:27 +02:00
m_VMStack . m_bMarkStack = false ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_ARRAY :
m_VMStack . Pop ( ) ;
m_VMStack . GetTop ( ) . evalArrayAt ( * ( m_VMStack . GetTopPtr ( ) + 1 ) ) ;
break ;
case OP_STORE_ARRAY_REF :
m_VMStack . Pop ( ) ;
m_VMStack . GetTop ( ) . setArrayRefValue ( * ( m_VMStack . GetTopPtr ( ) + 1 ) ) ;
break ;
case OP_STORE_FIELD_REF :
2023-11-14 00:16:09 +01:00
try {
2023-10-01 22:47:25 +02:00
try {
2023-11-14 00:16:09 +01:00
listener = m_VMStack . GetTop ( ) . listenerValue ( ) ;
2023-10-01 22:47:25 +02:00
if ( listener = = nullptr ) {
2023-10-31 20:39:28 +01:00
fieldNameIndex = fetchActualOpcodeValue < op_name_t > ( ) ;
2023-11-01 16:52:30 +01:00
ScriptError (
" Field '%s' applied to NULL listener " , Director . GetString ( fieldNameIndex ) . c_str ( )
) ;
2023-08-17 16:07:38 +02:00
}
2023-10-01 22:47:25 +02:00
} catch ( . . . ) {
2023-11-14 00:05:41 +01:00
skipField ( ) ;
2024-03-03 18:54:22 +01:00
m_VMStack . GetTop ( ) . Clear ( ) ;
2023-10-01 22:47:25 +02:00
throw ;
2023-07-05 21:23:39 +02:00
}
2023-11-14 00:16:09 +01:00
ScriptVariable * const listenerVar = storeTop < true > ( listener ) ;
if ( listenerVar ) {
// having a listener variable means the variable was just created
m_VMStack . GetTop ( ) . setRefValue ( listenerVar ) ;
}
2023-10-01 22:47:25 +02:00
break ;
2023-11-14 00:16:09 +01:00
} catch ( . . . ) {
ScriptVariable * const pTop = m_VMStack . GetTopPtr ( ) ;
pTop - > setRefValue ( pTop ) ;
throw ;
2023-08-17 16:07:38 +02:00
}
2023-07-05 21:23:39 +02:00
2023-08-17 16:07:38 +02:00
case OP_STORE_FIELD :
2023-10-01 22:47:25 +02:00
try {
2023-11-14 00:16:09 +01:00
listener = m_VMStack . GetTop ( ) . listenerValue ( ) ;
2023-07-05 21:23:39 +02:00
2023-10-01 22:47:25 +02:00
if ( listener = = nullptr ) {
2023-10-31 20:39:28 +01:00
fieldNameIndex = fetchActualOpcodeValue < op_name_t > ( ) ;
2023-11-01 16:52:30 +01:00
ScriptError ( " Field '%s' applied to NULL listener " , Director . GetString ( fieldNameIndex ) . c_str ( ) ) ;
2023-08-17 16:07:38 +02:00
}
2023-10-01 22:47:25 +02:00
} catch ( . . . ) {
2023-08-17 16:07:38 +02:00
skipField ( ) ;
2024-03-03 18:54:22 +01:00
m_VMStack . GetTop ( ) . Clear ( ) ;
2023-08-17 16:07:38 +02:00
throw ;
2023-07-05 21:23:39 +02:00
}
2023-11-14 00:16:09 +01:00
storeTop < true > ( listener ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_FLOAT :
m_VMStack . Push ( ) ;
2023-11-13 23:28:42 +01:00
m_VMStack . GetTop ( ) . setFloatValue ( fetchOpcodeValue < float > ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_INT0 :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setIntValue ( 0 ) ;
break ;
case OP_STORE_INT1 :
m_VMStack . Push ( ) ;
2023-11-13 23:28:42 +01:00
m_VMStack . GetTop ( ) . setIntValue ( fetchOpcodeValue < byte > ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_INT2 :
m_VMStack . Push ( ) ;
2023-11-13 23:28:42 +01:00
m_VMStack . GetTop ( ) . setIntValue ( fetchOpcodeValue < short > ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_INT3 :
m_VMStack . Push ( ) ;
2023-11-13 23:28:42 +01:00
m_VMStack . GetTop ( ) . setIntValue ( fetchOpcodeValue < short3 > ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_INT4 :
m_VMStack . Push ( ) ;
2023-11-13 23:28:42 +01:00
m_VMStack . GetTop ( ) . setIntValue ( fetchOpcodeValue < int > ( ) ) ;
2023-07-05 21:23:39 +02:00
break ;
case OP_STORE_GAME_VAR :
storeTop ( & game ) ;
break ;
case OP_STORE_GROUP_VAR :
storeTop ( m_ScriptClass ) ;
break ;
case OP_STORE_LEVEL_VAR :
storeTop ( & level ) ;
break ;
case OP_STORE_LOCAL_VAR :
storeTop ( m_Thread ) ;
break ;
case OP_STORE_OWNER_VAR :
if ( ! m_ScriptClass - > m_Self ) {
m_VMStack . Push ( ) ;
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self is NULL " ) ;
}
if ( ! m_ScriptClass - > m_Self - > GetScriptOwner ( ) ) {
m_VMStack . Push ( ) ;
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self.owner is NULL " ) ;
}
storeTop ( m_ScriptClass - > m_Self - > GetScriptOwner ( ) ) ;
break ;
case OP_STORE_PARM_VAR :
storeTop ( & parm ) ;
break ;
case OP_STORE_SELF_VAR :
if ( ! m_ScriptClass - > m_Self ) {
m_VMStack . Push ( ) ;
m_CodePos + = sizeof ( unsigned int ) ;
ScriptError ( " self is NULL " ) ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
storeTop ( m_ScriptClass - > m_Self ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_STORE_GAME :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setListenerValue ( & game ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_STORE_GROUP :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setListenerValue ( m_ScriptClass ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_STORE_LEVEL :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setListenerValue ( & level ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_STORE_LOCAL :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setListenerValue ( m_Thread ) ;
break ;
case OP_STORE_OWNER :
m_VMStack . Push ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( ! m_ScriptClass - > m_Self ) {
m_VMStack . Push ( ) ;
ScriptError ( " self is NULL " ) ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_VMStack . GetTop ( ) . setListenerValue ( m_ScriptClass - > m_Self - > GetScriptOwner ( ) ) ;
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case OP_STORE_PARM :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setListenerValue ( & parm ) ;
break ;
case OP_STORE_SELF :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setListenerValue ( m_ScriptClass - > m_Self ) ;
break ;
case OP_STORE_NIL :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . Clear ( ) ;
break ;
case OP_STORE_NULL :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setListenerValue ( NULL ) ;
break ;
case OP_STORE_STRING :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setConstStringValue ( fetchOpcodeValue < unsigned int > ( ) ) ;
break ;
case OP_STORE_VECTOR :
m_VMStack . Push ( ) ;
m_VMStack . GetTop ( ) . setVectorValue ( fetchOpcodeValue < Vector > ( ) ) ;
break ;
case OP_SWITCH :
if ( ! Switch ( fetchActualOpcodeValue < StateScript * > ( ) , m_VMStack . Pop ( ) ) ) {
m_CodePos + = sizeof ( StateScript * ) ;
}
break ;
case OP_UN_CAST_BOOLEAN :
m_VMStack . GetTop ( ) . CastBoolean ( ) ;
break ;
case OP_UN_COMPLEMENT :
m_VMStack . GetTop ( ) . complement ( ) ;
break ;
case OP_UN_MINUS :
m_VMStack . GetTop ( ) . minus ( ) ;
break ;
case OP_UN_DEC :
m_VMStack . GetTop ( ) - - ;
break ;
case OP_UN_INC :
m_VMStack . GetTop ( ) + + ;
break ;
case OP_UN_SIZE :
m_VMStack . GetTop ( ) . setIntValue ( ( int ) m_VMStack . GetTop ( ) . size ( ) ) ;
break ;
case OP_UN_TARGETNAME :
2023-10-01 22:45:41 +02:00
// retrieve the target name
2025-01-15 18:29:35 +01:00
if ( world ) {
targetList = world - > GetExistingTargetList ( m_VMStack . GetTop ( ) . stringValue ( ) ) ;
} else {
// Added in OPM
// don't use the target list if the world is NULL
targetList = NULL ;
}
2023-07-05 21:23:39 +02:00
2024-10-22 20:05:53 +02:00
if ( ! targetList | | ! targetList - > list . NumObjects ( ) ) {
2024-02-16 23:50:57 +01:00
str targetname = m_VMStack . GetTop ( ) . stringValue ( ) ;
2023-10-01 22:45:41 +02:00
// the target name was not found
2023-07-05 21:23:39 +02:00
m_VMStack . GetTop ( ) . setListenerValue ( NULL ) ;
2024-04-10 23:42:09 +02:00
if ( ( * m_PrevCodePos > = OP_BIN_EQUALITY & & * m_PrevCodePos < = OP_BIN_GREATER_THAN_OR_EQUAL )
| | ( * m_PrevCodePos > = OP_BOOL_UN_NOT & & * m_PrevCodePos < = OP_UN_CAST_BOOLEAN ) ) {
2024-02-16 23:50:57 +01:00
ScriptError ( " Targetname '%s' does not exist. " , targetname . c_str ( ) ) ;
2023-07-05 21:23:39 +02:00
}
2024-10-22 20:05:53 +02:00
} else if ( targetList - > list . NumObjects ( ) = = 1 ) {
2023-10-01 22:45:41 +02:00
// single listener
2024-10-22 20:05:53 +02:00
m_VMStack . GetTop ( ) . setListenerValue ( targetList - > list . ObjectAt ( 1 ) ) ;
} else if ( targetList - > list . NumObjects ( ) > 1 ) {
2023-10-01 22:45:41 +02:00
// multiple listeners
2024-10-22 20:05:53 +02:00
m_VMStack . GetTop ( ) . setContainerValue ( ( Container < SafePtr < Listener > > * ) & targetList - > list ) ;
2023-07-05 21:23:39 +02:00
}
break ;
case OP_VAR_UN_NOT :
m_VMStack . GetTop ( ) . setIntValue ( m_VMStack . GetTop ( ) . booleanValue ( ) ) ;
break ;
case OP_DONE :
End ( ) ;
break ;
case OP_NOP :
break ;
default :
assert ( ! " Invalid opcode " ) ;
if ( * opcode < OP_MAX ) {
2024-08-24 18:49:36 +02:00
gi . DPrintf ( " unknown opcode %d ('%s') \n " , * opcode , OpcodeName ( * opcode ) ) ;
2023-07-05 21:23:39 +02:00
} else {
2024-08-24 18:49:36 +02:00
gi . DPrintf ( " unknown opcode %d \n " , * opcode ) ;
2023-07-05 21:23:39 +02:00
}
break ;
}
2024-08-24 18:49:36 +02:00
Director . cmdCount + + ;
if ( Director . cmdCount > = 15000 ) {
if ( ! Director . cmdTime ) {
Director . cmdTime = gi . Milliseconds ( ) ;
Director . cmdCount = 0 ;
continue ;
}
if ( gi . Milliseconds ( ) - Director . cmdTime < Director . maxTime ) {
Director . cmdCount = 0 ;
continue ;
}
// The maximum execution time was reached
if ( level . m_LoopProtection ) {
Director . cmdTime = gi . Milliseconds ( ) ;
GetScript ( ) - > PrintSourcePos ( m_CodePos , true ) ;
gi . DPrintf2 ( " \n " ) ;
state = STATE_EXECUTION ;
if ( level . m_LoopDrop ) {
ScriptException : : next_abort = - 1 ;
}
ScriptError ( " Command overflow. Possible infinite loop in thread. \n " ) ;
break ;
}
VM_DPrintf ( " Update of script position - This is not an error. \n " ) ;
VM_DPrintf ( " ================================================= \n " ) ;
m_ScriptClass - > GetScript ( ) - > PrintSourcePos ( opcode , true ) ;
VM_DPrintf ( " ================================================= \n " ) ;
Director . cmdCount = 0 ;
}
2023-07-05 21:23:39 +02:00
} catch ( ScriptException & exc ) {
HandleScriptException ( exc ) ;
}
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
Director . stackCount - - ;
2023-11-01 16:52:30 +01:00
if ( g_scripttrace - > integer & & CanScriptTracePrint ( ) ) {
gi . DPrintf2 (
" ---FRAME: %i (%p) ------------------------------------------------------------------- \n " ,
Director . stackCount ,
this
) ;
2023-07-05 21:23:39 +02:00
}
2023-01-29 20:59:31 +01:00
2023-11-01 16:52:30 +01:00
switch ( state ) {
case STATE_WAITING :
delete m_Thread ;
delete this ;
break ;
case STATE_SUSPENDED :
state = STATE_EXECUTION ;
break ;
case STATE_DESTROYED :
2023-07-05 21:23:39 +02:00
delete this ;
2023-11-01 16:52:30 +01:00
break ;
2023-07-05 21:23:39 +02:00
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
HandleScriptException
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : HandleScriptException ( ScriptException & exc )
{
2023-07-05 21:23:39 +02:00
if ( m_ScriptClass ) {
m_ScriptClass - > GetScript ( ) - > PrintSourcePos ( m_PrevCodePos , true ) ;
} else {
2024-08-24 18:49:36 +02:00
gi . DPrintf ( " unknown source pos " ) ;
2023-07-05 21:23:39 +02:00
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( exc . bAbort ) {
ScriptException e ( exc . string ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
e . bAbort = exc . bAbort ;
e . bIsForAnim = exc . bIsForAnim ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
state = STATE_EXECUTION ;
throw e ;
}
2023-01-29 20:59:31 +01:00
2023-08-16 02:43:22 +02:00
gi . DPrintf2 ( " ^~^~^ Script Error : %s \n \n " , exc . string . c_str ( ) ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( m_ScriptClass - > GetScript ( ) - > ScriptCheck ( ) ) {
if ( g_scriptcheck - > integer ! = 2 | | ! exc . bIsForAnim ) {
ScriptException e ( " Script check failed " ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
e . bAbort = exc . bAbort ;
e . bIsForAnim = exc . bIsForAnim ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
state = STATE_EXECUTION ;
throw e ;
}
}
Director . cmdCount + = 100 ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
SetFastData
Sets the starting virtual machine parameters
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
void ScriptVM : : SetFastData ( ScriptVariable * data , int dataSize )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
if ( fastEvent . data ) {
fastEvent . data = m_pOldData ;
fastEvent . dataSize = m_OldDataSize ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
fastEvent . Clear ( ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_pOldData = NULL ;
m_OldDataSize = 0 ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( dataSize ) {
fastEvent . data = new ScriptVariable [ dataSize ] ;
fastEvent . dataSize = dataSize ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
for ( int i = 0 ; i < dataSize ; i + + ) {
2023-08-19 20:47:36 +02:00
fastEvent . data [ i ] = std : : move ( data [ i ] ) ;
2023-07-05 21:23:39 +02:00
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_pOldData = fastEvent . data ;
m_OldDataSize = fastEvent . dataSize ;
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
NotifyDelete
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : NotifyDelete ( void )
{
2023-10-26 20:13:07 +02:00
if ( g_scripttrace - > integer & & CanScriptTracePrint ( ) ) {
2023-11-01 16:52:30 +01:00
gi . DPrintf2 ( " ---THREAD: %p \n " , this ) ;
2023-10-26 20:13:07 +02:00
}
2023-07-05 21:23:39 +02:00
switch ( state ) {
case STATE_RUNNING :
case STATE_SUSPENDED :
case STATE_WAITING :
state = STATE_DESTROYED ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( m_ScriptClass ) {
m_ScriptClass - > RemoveThread ( this ) ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
break ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
case STATE_EXECUTION :
state = STATE_DESTROYED ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( m_ScriptClass ) {
m_ScriptClass - > RemoveThread ( this ) ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
delete this ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
break ;
2023-10-26 20:17:42 +02:00
case STATE_DESTROYED :
ScriptError ( " Attempting to delete a dead thread. " ) ;
state = STATE_DESTROYED ;
if ( m_ScriptClass ) {
m_ScriptClass - > RemoveThread ( this ) ;
}
break ;
2023-07-05 21:23:39 +02:00
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
Resume
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : Resume ( qboolean bForce )
{
2023-07-05 21:23:39 +02:00
if ( state = = STATE_SUSPENDED | | ( bForce & & state ! = STATE_DESTROYED ) ) {
state = STATE_RUNNING ;
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
Suspend
= = = = = = = = = = = = = = = = = = = =
*/
void ScriptVM : : Suspend ( )
{
2023-07-05 21:23:39 +02:00
if ( state = = STATE_DESTROYED ) {
ScriptError ( " Cannot suspend a dead thread. " ) ;
2023-10-30 22:46:59 +01:00
} else if ( state = = STATE_RUNNING ) {
2023-07-05 21:23:39 +02:00
state = STATE_SUSPENDED ;
}
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
Switch
Switch statement
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
bool ScriptVM : : Switch ( StateScript * stateScript , ScriptVariable & var )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
unsigned char * pos ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
fastEvent . dataSize = 0 ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
pos = stateScript - > FindLabel ( var . stringValue ( ) ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( ! pos ) {
2023-08-19 00:57:29 +02:00
pos = stateScript - > FindLabel ( STRING_DEFAULT ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( ! pos ) {
return false ;
}
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_CodePos = pos ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
return true ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
Filename
= = = = = = = = = = = = = = = = = = = =
*/
2023-10-27 20:00:48 +02:00
str ScriptVM : : Filename ( void ) const
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
return m_ScriptClass - > Filename ( ) ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
Label
= = = = = = = = = = = = = = = = = = = =
*/
2023-10-27 20:00:48 +02:00
str ScriptVM : : Label ( void ) const
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
const_str label = m_ScriptClass - > NearestLabel ( m_CodePos ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( ! label ) {
return " " ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
return Director . GetString ( label ) ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
GetScriptClass
= = = = = = = = = = = = = = = = = = = =
*/
2023-10-27 20:00:48 +02:00
ScriptClass * ScriptVM : : GetScriptClass ( void ) const
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
return m_ScriptClass ;
2023-01-29 20:59:31 +01:00
}
2023-10-27 20:00:48 +02:00
/*
= = = = = = = = = = = = = = = = = = = =
GetScript
= = = = = = = = = = = = = = = = = = = =
*/
GameScript * ScriptVM : : GetScript ( ) const
{
return m_ScriptClass - > GetScript ( ) ;
}
2023-01-29 20:59:31 +01:00
/*
= = = = = = = = = = = = = = = = = = = =
IsSuspended
= = = = = = = = = = = = = = = = = = = =
*/
bool ScriptVM : : IsSuspended ( void )
{
2023-10-27 20:41:47 +02:00
return state = = STATE_EXECUTION ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
State
= = = = = = = = = = = = = = = = = = = =
*/
int ScriptVM : : State ( void )
{
2023-07-05 21:23:39 +02:00
return state ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
ThreadState
= = = = = = = = = = = = = = = = = = = =
*/
int ScriptVM : : ThreadState ( void )
{
2023-07-05 21:23:39 +02:00
return m_ThreadState ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
EventGoto
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
void ScriptVM : : EventGoto ( Event * ev )
2023-01-29 20:59:31 +01:00
{
2023-10-01 22:47:25 +02:00
unsigned char * codePos ;
2023-08-13 22:07:33 +02:00
const ScriptVariable & value = ev - > GetValue ( 1 ) ;
2023-10-01 22:47:25 +02:00
if ( value . type = = VARIABLE_CONSTSTRING ) {
2023-08-13 22:07:33 +02:00
const_str label = value . constStringValue ( ) ;
2023-10-01 22:47:25 +02:00
codePos = m_ScriptClass - > FindLabel ( label ) ;
if ( ! codePos ) {
ScriptError (
" ScriptVM::EventGoto: label '%s' does not exist in '%s'. " ,
value . stringValue ( ) . c_str ( ) ,
Filename ( ) . c_str ( )
) ;
}
2023-01-29 20:59:31 +01:00
2023-10-01 22:47:25 +02:00
} else {
2023-08-13 22:07:33 +02:00
str label = value . stringValue ( ) ;
2023-10-01 22:47:25 +02:00
codePos = m_ScriptClass - > FindLabel ( label ) ;
2023-08-13 22:07:33 +02:00
2023-10-01 22:47:25 +02:00
if ( ! codePos ) {
ScriptError ( " ScriptVM::EventGoto: label '%s' does not exist in '%s'. " , label . c_str ( ) , Filename ( ) . c_str ( ) ) ;
}
2023-08-13 22:07:33 +02:00
}
SetFastData ( ev - > data + 1 , ev - > dataSize - 1 ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_CodePos = codePos ;
2023-01-29 20:59:31 +01:00
}
/*
= = = = = = = = = = = = = = = = = = = =
EventThrow
Called when throwing an exception
= = = = = = = = = = = = = = = = = = = =
*/
2023-07-05 21:23:39 +02:00
bool ScriptVM : : EventThrow ( Event * ev )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
str label = ev - > GetString ( 1 ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
SetFastData ( ev - > data , ev - > dataSize ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
fastEvent . eventnum = ev - > eventnum ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
while ( 1 ) {
StateScript * stateScript = m_ScriptClass - > GetCatchStateScript ( m_PrevCodePos , m_PrevCodePos ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( ! stateScript ) {
break ;
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
m_CodePos = stateScript - > FindLabel ( label ) ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
if ( m_CodePos ) {
fastEvent . data + + ;
fastEvent . dataSize - - ;
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
return true ;
}
}
2023-01-29 20:59:31 +01:00
2023-07-05 21:23:39 +02:00
return false ;
2023-01-29 20:59:31 +01:00
}
2023-07-05 21:23:39 +02:00
bool ScriptVM : : CanScriptTracePrint ( void )
2023-01-29 20:59:31 +01:00
{
2023-07-05 21:23:39 +02:00
if ( g_scripttrace - > integer < 1 | | g_scripttrace - > integer > 4 ) {
return false ;
}
if ( g_scripttrace - > integer < = 2 ) {
return true ;
}
if ( ! m_ScriptClass ) {
return false ;
}
if ( ! * g_monitor - > string | | ! m_ScriptClass - > m_Self | | ! m_ScriptClass - > m_Self - > isInheritedBy ( & SimpleEntity : : ClassInfo )
| | ( ( SimpleEntity * ) m_ScriptClass - > m_Self . Pointer ( ) ) - > targetname ! = g_monitor - > string ) {
if ( g_monitorNum - > integer > = 0 ) {
if ( m_ScriptClass - > m_Self & & m_ScriptClass - > m_Self - > isInheritedBy ( & Entity : : ClassInfo )
& & ( ( Entity * ) m_ScriptClass - > m_Self . Pointer ( ) ) - > entnum = = g_monitorNum - > integer ) {
return true ;
}
}
return false ;
}
return true ;
2023-01-29 20:59:31 +01:00
}
2023-02-02 23:48:51 +01:00
2023-07-05 21:23:39 +02:00
void ScriptVM : : fetchOpcodeValue ( void * outValue , size_t size )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
Com_Memcpy ( outValue , m_CodePos , size ) ;
m_CodePos + = size ;
2023-02-02 23:48:51 +01:00
}
2023-07-05 21:23:39 +02:00
void ScriptVM : : fetchActualOpcodeValue ( void * outValue , size_t size )
2023-02-02 23:48:51 +01:00
{
2023-07-05 21:23:39 +02:00
Com_Memcpy ( outValue , m_CodePos , size ) ;
2023-02-02 23:48:51 +01:00
}