ef2gamesource/dlls/game/gamescript.cpp

448 lines
7.3 KiB
C++

//-----------------------------------------------------------------------------
//
// $Logfile:: /Code/DLLs/game/gamescript.cpp $
// $Revision:: 5 $
// $Author:: Steven $
// $Date:: 10/08/02 1:37p $
//
// Copyright (C) 1997 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source is may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
//
// DESCRIPTION:
// Subclass of script that preprocesses labels
//
#include "_pch_cpp.h"
#include "script.h"
#include "gamescript.h"
ScriptLibrarian ScriptLib;
CLASS_DECLARATION( Class, GameScriptMarker, NULL )
{
{ NULL, NULL }
};
CLASS_DECLARATION( Class, ScriptLibrarian, NULL )
{
{ NULL, NULL }
};
ScriptLibrarian::~ScriptLibrarian()
{
int i;
int num;
num = scripts.NumObjects();
for( i = 1; i <= num; i++ )
{
delete scripts.ObjectAt( i );
}
}
void ScriptLibrarian::CloseScripts( void )
{
int i;
int num;
GameScript *scr;
// Clear out the game and dialog scripts
SetGameScript( "" );
SetDialogScript( "" );
num = scripts.NumObjects();
for( i = num; i > 0; i-- )
{
scr = scripts.ObjectAt( i );
scripts.RemoveObjectAt( i );
delete scr;
}
}
void ScriptLibrarian::SetDialogScript( const str &scriptname )
{
dialog_script = scriptname;
}
void ScriptLibrarian::SetGameScript( const str &scriptname )
{
game_script = scriptname;
}
const char *ScriptLibrarian::GetGameScript( void )
{
return game_script.c_str();
}
GameScript *ScriptLibrarian::FindScript( const char *name )
{
int i;
int num;
GameScript *scr;
str n;
// Convert all forward slashes to back slashes
n = G_FixSlashes( name );
num = scripts.NumObjects();
for( i = 1; i <= num; i++ )
{
scr = scripts.ObjectAt( i );
if ( scr->Filename() == n )
{
return scr;
}
}
return NULL;
}
GameScript *ScriptLibrarian::GetScript( const char *name )
{
GameScript *scr;
str n;
n = G_FixSlashes( name );
if ( !n.length() )
{
return NULL;
}
// see if we have an absolute path specified,
// if we don't use the same path as the map file
if ( !strchr( n.c_str(), '/' ) )
{
int i;
str mapname;
mapname = "maps/";
mapname += level.mapname;
for( i = mapname.length() - 1; i >= 0; i-- )
{
if ( mapname[ i ] == '/' )
{
// skip back over the '/'
i++;
mapname[ i ] = 0;
break;
}
}
mapname += n;
// copy it back into the write string
n = mapname;
}
scr = FindScript( n.c_str() );
if ( !scr && ( gi.FS_ReadFile( n.c_str(), NULL, false ) != -1 ) )
{
scr = new GameScript();
scr->LoadFile( n.c_str() );
scripts.AddObject( scr );
}
return scr;
}
qboolean ScriptLibrarian::Goto( GameScript *scr, const char *name )
{
const char *p;
GameScript *s;
str n;
p = strstr( name, "::" );
if ( !p )
{
return scr->Goto( name );
}
else
{
n = str( name, 0, p - name );
if ( n == str( "dialog" ) )
{
n = dialog_script;
}
s = GetScript( n.c_str() );
if ( !s )
{
return false;
}
p += 2;
if ( s->labelExists( p ) )
{
scr->SetSourceScript( s );
return scr->Goto( p );
}
}
return false;
}
qboolean ScriptLibrarian::labelExists( GameScript *scr, const char *name )
{
const char *p;
GameScript *s;
str n;
// if we got passed a NULL than that means just run the script so of course it exists
if ( !name )
{
return true;
}
p = strstr( name, "::" );
if ( !p )
{
return scr->labelExists( name );
}
else
{
n = str( name, 0, p - name );
if ( n == str( "dialog" ) )
{
n = dialog_script;
}
s = GetScript( n.c_str() );
if ( !s )
{
return false;
}
p += 2;
return s->labelExists( p );
}
}
CLASS_DECLARATION( Script, GameScript, NULL )
{
{ NULL, NULL }
};
GameScript::GameScript()
{
sourcescript = this;
labelList = NULL;
crc = 0;
}
GameScript::GameScript( GameScript *scr )
{
crc = 0;
labelList = NULL;
SetSourceScript( scr );
}
GameScript::~GameScript()
{
Close();
}
void GameScript::Close( void )
{
FreeLabels();
Script::Close();
sourcescript = this;
crc = 0;
}
void GameScript::SetSourceScript( GameScript *scr )
{
if ( scr != this )
{
Close();
sourcescript = scr->sourcescript;
crc = sourcescript->crc;
Parse( scr->buffer, scr->length, scr->Filename() );
}
}
void GameScript::FreeLabels( void )
{
int i;
int num;
if ( labelList )
{
num = labelList->NumObjects();
for( i = 1; i <= num; i++ )
{
delete labelList->ObjectAt( i );
}
delete labelList;
}
labelList = NULL;
}
void GameScript::LoadFile( const char *name )
{
str n;
// Convert all forward slashes to back slashes
n = G_FixSlashes( name );
sourcescript = this;
Script::LoadFile( n.c_str() );
FindLabels();
crc = gi.CalcCRC( (const unsigned char *)buffer, length );
}
void GameScript::FindLabels( void )
{
scriptmarker_t mark;
const char *tok;
script_label_t *label;
int len;
FreeLabels();
labelList = new Container<script_label_t *>;
MarkPosition( &mark );
Reset();
while( TokenAvailable( true ) )
{
tok = GetToken( true );
// see if it is a label
if ( tok )
{
len = strlen( tok );
if ( ( len > 1 ) && ( tok[ len - 1 ] == ':' ) )
{
if ( !labelExists( tok ) )
{
label = new script_label_t;
MarkPosition( &label->pos );
label->labelname = tok;
labelList->AddObject( label );
}
else
{
warning( "FindLabels", "Duplicate labels %s\n", tok );
}
}
}
}
RestorePosition( &mark );
}
qboolean GameScript::labelExists( const char *name )
{
str labelname;
script_label_t *label;
int i;
int num;
// if we got passed a NULL than that means just run the script so of course it exists
if ( !name )
{
return true;
}
if ( !sourcescript->labelList )
{
return false;
}
labelname = name;
if ( !labelname.length() )
{
return false;
}
if ( labelname[ labelname.length() - 1 ] != ':' )
{
labelname += ":";
}
num = sourcescript->labelList->NumObjects();
for( i = 1; i <= num; i++ )
{
label = sourcescript->labelList->ObjectAt( i );
if ( labelname == label->labelname )
{
return true;
}
}
return false;
}
qboolean GameScript::Goto( const char *name )
{
str labelname;
script_label_t *label;
int i;
int num;
if ( !sourcescript->labelList )
{
return false;
}
labelname = name;
if ( !labelname.length() )
{
return false;
}
if ( labelname[ labelname.length() - 1 ] != ':' )
{
labelname += ":";
}
num = sourcescript->labelList->NumObjects();
for( i = 1; i <= num; i++ )
{
label = sourcescript->labelList->ObjectAt( i );
if ( labelname == label->labelname )
{
RestorePosition( &label->pos );
return true;
}
}
return false;
}
void GameScript::Mark( GameScriptMarker *mark )
{
assert( mark );
assert( sourcescript );
mark->filename = sourcescript->Filename();
MarkPosition( &mark->scriptmarker );
}
void GameScript::Restore( GameScriptMarker *mark )
{
// If we change this function, we must update the unarchive function as well
GameScript *scr;
assert( mark );
scr = ScriptLib.FindScript( mark->filename.c_str() );
if ( scr )
{
SetSourceScript( scr );
}
else
{
LoadFile( mark->filename.c_str() );
}
RestorePosition( &mark->scriptmarker );
}