476 lines
7.3 KiB
C++
476 lines
7.3 KiB
C++
// 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 "g_local.h"
|
|
#include "script.h"
|
|
#include "gamescript.h"
|
|
|
|
ScriptLibrarian ScriptLib;
|
|
|
|
CLASS_DECLARATION( Class, GameScriptMarker, NULL );
|
|
|
|
ResponseDef GameScriptMarker::Responses[] =
|
|
{
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
CLASS_DECLARATION( Class, ScriptLibrarian, NULL );
|
|
|
|
ResponseDef ScriptLibrarian::Responses[] =
|
|
{
|
|
{ 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
|
|
(
|
|
str scriptname
|
|
)
|
|
{
|
|
dialog_script = scriptname;
|
|
}
|
|
|
|
void ScriptLibrarian::SetGameScript
|
|
(
|
|
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 );
|
|
scr = FindScript( n.c_str() );
|
|
if ( !scr && ( gi.LoadFile( name, NULL, 0 ) != -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;
|
|
|
|
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 );
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
CLASS_DECLARATION( Script, GameScript, NULL );
|
|
|
|
ResponseDef GameScript::Responses[] =
|
|
{
|
|
{ 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( 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 && 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 );
|
|
}
|
|
|
|
EXPORT_FROM_DLL qboolean GameScript::labelExists
|
|
(
|
|
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 )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
EXPORT_FROM_DLL 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;
|
|
}
|
|
|
|
EXPORT_FROM_DLL void GameScript::Mark
|
|
(
|
|
GameScriptMarker *mark
|
|
)
|
|
|
|
{
|
|
assert( mark );
|
|
assert( sourcescript );
|
|
|
|
mark->filename = sourcescript->Filename();
|
|
MarkPosition( &mark->scriptmarker );
|
|
}
|
|
|
|
EXPORT_FROM_DLL 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 );
|
|
}
|