447 lines
7.7 KiB
C++
447 lines
7.7 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 );
|
|
}
|