quake4-sdk/source/mpgame/script/ScriptFuncUtility.cpp

470 lines
9.1 KiB
C++

#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
/*
================
rvScriptFuncUtility::rvScriptFuncUtility
================
*/
rvScriptFuncUtility::rvScriptFuncUtility() {
func = NULL;
parms.Clear();
}
/*
================
rvScriptFuncUtility::rvScriptFuncUtility
================
*/
rvScriptFuncUtility::rvScriptFuncUtility( const rvScriptFuncUtility* sfu ) {
Assign( sfu );
}
/*
================
rvScriptFuncUtility::rvScriptFuncUtility
================
*/
rvScriptFuncUtility::rvScriptFuncUtility( const rvScriptFuncUtility& sfu ) {
Assign( &sfu );
}
/*
================
rvScriptFuncUtility::rvScriptFuncUtility
================
*/
rvScriptFuncUtility::rvScriptFuncUtility( const char* source ) {
Init( source );
}
/*
================
rvScriptFuncUtility::rvScriptFuncUtility
================
*/
rvScriptFuncUtility::rvScriptFuncUtility( const idCmdArgs& args ) {
Init( args );
}
/*
================
rvScriptFuncUtility::Init
================
*/
sfuReturnType rvScriptFuncUtility::Init( const char* source ) {
Clear();
if( !source || !source[0] ) {
return SFU_NOFUNC;
}
idStr::Split( source, parms, ' ' );
return Init();
}
/*
================
rvScriptFuncUtility::Init
================
*/
sfuReturnType rvScriptFuncUtility::Init( const idCmdArgs& args ) {
Clear();
//Start at index 1 so we ignore 'call'
for( int ix = 1; ix < args.Argc(); ++ix ) {
InsertString( args.Argv(ix), ix );
}
return Init();
}
/*
================
rvScriptFuncUtility::Init
================
*/
sfuReturnType rvScriptFuncUtility::Init() {
assert( parms.Num() );
func = FindFunction( GetParm(0) );
if( func ) {
RemoveIndex( 0 );// remove Function name
returnKey.Clear();
} else if( parms.Num() >= 2 ) {
returnKey = GetParm( 0 );
RemoveIndex( 0 );// remove key name
func = FindFunction( GetParm(0) );
RemoveIndex( 0 );// remove Function name
} else {
gameLocal.Warning( "Unable to find function %s in rvScriptFuncUtility::Init\n", parms[0].c_str() );
}
return func != NULL ? SFU_OK : SFU_ERROR;
}
/*
================
rvScriptFuncUtility::Clear
================
*/
void rvScriptFuncUtility::Clear() {
func = NULL;
parms.Clear();
}
/*
================
rvScriptFuncUtility::Save
================
*/
void rvScriptFuncUtility::Save( idSaveGame *savefile ) const {
bool validFunc = GetFunc() != NULL;
savefile->WriteBool( validFunc );
if( !validFunc ) {
return;
}
savefile->WriteString( GetReturnKey() );
savefile->WriteString( GetFunc()->Name() );
savefile->WriteInt( NumParms() );
for( int ix = 0; ix < NumParms(); ++ix ) {
savefile->WriteString( func->Name() );
}
}
/*
================
rvScriptFuncUtility::Restore
================
*/
void rvScriptFuncUtility::Restore( idRestoreGame *savefile ) {
idStr value;
idStr element;
int numParms = 0;
bool validFunc = false;
savefile->ReadBool( validFunc );
if( !validFunc ) {
return;
}
savefile->ReadString( element );
if( element.Length() ) {
value += element;
value += ' ';
}
savefile->ReadString( element );
if( element.Length() ) {
value += element;
value += ' ';
}
savefile->ReadInt( numParms );
for( int ix = 0; ix < numParms; ++ix ) {
savefile->ReadString( element );
value += element;
value += ' ';
}
value.StripTrailing( ' ' );
sfuReturnType status = Init(value.c_str());
if ( status != SFU_OK ) {
assert( 0 );
}
}
/*
================
rvScriptFuncUtility::NumParms
================
*/
int rvScriptFuncUtility::NumParms() const {
return (func && func->type) ? func->type->NumParameters() : 0;
}
/*
================
rvScriptFuncUtility::ReturnsAVal
================
*/
bool rvScriptFuncUtility::ReturnsAVal() const {
return GetReturnType() != &type_void;
}
/*
================
rvScriptFuncUtility::GetParm
================
*/
idTypeDef* rvScriptFuncUtility::GetParmType( int index ) const {
return (func && func->type) ? func->type->GetParmType( index ) : NULL;
}
/*
================
rvScriptFuncUtility::GetReturnType
================
*/
idTypeDef* rvScriptFuncUtility::GetReturnType() const {
return (func && func->type) ? func->type->ReturnType() : &type_void;
}
/*
================
rvScriptFuncUtility::SetFunction
================
*/
void rvScriptFuncUtility::SetFunction( const function_t* func ) {
this->func = func;
}
/*
================
rvScriptFuncUtility::SetParms
================
*/
void rvScriptFuncUtility::SetParms( const idList<idStr>& parms ) {
this->parms = parms;
}
/*
================
rvScriptFuncUtility::GetParm
================
*/
const char* rvScriptFuncUtility::GetParm( int index ) const {
return parms[ index ].c_str();
}
/*
================
rvScriptFuncUtility::GetFuncName
================
*/
const char* rvScriptFuncUtility::GetFuncName() const {
if( !func ) {
return NULL;
}
return func->Name();
}
/*
================
rvScriptFuncUtility::InsertInt
================
*/
void rvScriptFuncUtility::InsertInt( int parm, int index ) {
InsertString( va("%d", parm), index );
}
/*
================
rvScriptFuncUtility::InsertFloat
================
*/
void rvScriptFuncUtility::InsertFloat( float parm, int index ) {
InsertString( va("%f", parm), index );
}
/*
================
rvScriptFuncUtility::InsertVec3
================
*/
void rvScriptFuncUtility::InsertVec3( const idVec3& parm, int index ) {
InsertString( parm.ToString(), index );
}
/*
================
rvScriptFuncUtility::InsertEntity
================
*/
void rvScriptFuncUtility::InsertEntity( const idEntity* parm, int index ) {
assert( parm );
InsertString( parm->GetName(), index );
}
/*
================
rvScriptFuncUtility::InsertString
================
*/
void rvScriptFuncUtility::InsertString( const char* parm, int index ) {
assert( parm );
parms.Insert( parm, index );
}
/*
================
rvScriptFuncUtility::InsertBool
================
*/
void rvScriptFuncUtility::InsertBool( bool parm, int index ) {
InsertInt( (int)parm, index );
}
/*
================
rvScriptFuncUtility::RemoveIndex
================
*/
void rvScriptFuncUtility::RemoveIndex( int index ) {
parms.RemoveIndex( index );
}
/*
================
rvScriptFuncUtility::FindFunction
================
*/
const function_t* rvScriptFuncUtility::FindFunction( const char* name ) const {
idTypeDef* type = gameLocal.program.FindType( name );
if( type ) {//Find based on type
return gameLocal.program.FindFunction( name, type );
}
//Find based on scope
return gameLocal.program.FindFunction( name );
}
/*
================
rvScriptFuncUtility::CallFunc
================
*/
void rvScriptFuncUtility::CallFunc( idDict* returnDict ) const {
idTypeDef* type = NULL;
if( !Valid() ) {
return;
}
idThread* thread = new idThread();
if( !thread ) {
return;
}
thread->ClearStack();
for( int ix = 0; ix < NumParms(); ++ix ) {
type = GetParmType( ix );
type->PushOntoStack( thread, GetParm(ix) );
}
thread->CallFunction( func, false );
if( thread->Execute() && returnDict && ReturnsAVal() ) {
returnDict->Set( GetReturnKey(), GetReturnType()->GetReturnedValAsString(gameLocal.program) );
}
}
/*
================
rvScriptFuncUtility::Valid
================
*/
bool rvScriptFuncUtility::Valid() const {
//#if _DEBUG
idTypeDef* type = NULL;
if( !GetFunc() ) {
return false;
}
if( GetFunc()->eventdef ) {
gameLocal.Warning( "Function, %s, is an event\n", GetFunc()->Name() );
return false;
}
// FIXME: designers call functions with no parms even though parms are pushed on stack
//if( NumParms() != parms.Num() ) {
// gameLocal.Warning( "Number of parms doesn't equal the num required by function %s\n", func->Name() );
// return false;
//}
for( int ix = 0; ix < NumParms(); ++ix ) {
type = GetParmType( ix );
if( !type->IsValid( GetParm(ix) ) ) {
gameLocal.Warning( "(Func: %s) Parm '%s' doesn't match expected type '%s'\n", GetFunc()->Name(), GetParm(ix), type->Name() );
return false;
}
}
if( returnKey.Length() && !ReturnsAVal() ) {
gameLocal.Warning( "Expecting return val from function %s which doesn't return one\n", func->Name() );
return false;
}
//#endif
return true;
}
/*
================
rvScriptFuncUtility::Assign
================
*/
rvScriptFuncUtility& rvScriptFuncUtility::Assign( const rvScriptFuncUtility* sfu ) {
assert( sfu );
func = sfu->func;
parms = sfu->parms;
returnKey = sfu->returnKey;
return *this;
}
/*
================
rvScriptFuncUtility::operator=
================
*/
rvScriptFuncUtility& rvScriptFuncUtility::operator=( const rvScriptFuncUtility* sfu ) {
return Assign( sfu );
}
/*
================
rvScriptFuncUtility::operator=
================
*/
rvScriptFuncUtility& rvScriptFuncUtility::operator=( const rvScriptFuncUtility& sfu ) {
return Assign( &sfu );
}
/*
================
rvScriptFuncUtility::IsEqualTo
================
*/
bool rvScriptFuncUtility::IsEqualTo( const rvScriptFuncUtility* sfu ) const {
assert( sfu );
return GetFunc() == sfu->GetFunc();
}
/*
================
rvScriptFuncUtility::operator==
================
*/
bool rvScriptFuncUtility::operator==( const rvScriptFuncUtility* sfu ) const {
return IsEqualTo( sfu );
}
/*
================
rvScriptFuncUtility::operator==
================
*/
bool rvScriptFuncUtility::operator==( const rvScriptFuncUtility& sfu ) const {
return IsEqualTo( &sfu );
}