⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scriptmaster.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 5 页
字号:

		   assert( ent );

		   sendevent = new Event( *ev );

			if ( !updateList.ObjectInList( ent->entnum ) )
			   {
			   updateList.AddObject( ent->entnum );

			   // Tell the object that we're about to send it some orders
			   ent->ProcessEvent( EV_Script_NewOrders );
			   }

		   // Send the command
		   ent->ProcessEvent( sendevent );
         }
      }
   //
   // free up the event
   //
   delete ev;
	}

qboolean ScriptThread::FindEvent
	(
	const char *name
	)

	{
   if ( !Event::Exists( name ) )
		{
		ScriptError( "Unknown command '%s'\n", name );
		script.SkipToEOL();
		return false;
		}

	return true;
	}

EXPORT_FROM_DLL void ScriptThread::ProcessCommand
	(
	int argc,
	const char **argv
	)

	{
	ScriptVariableList *vars;
	ScriptVariable		 *var;
	str		command;
	str		name;
	Event		*event;
	Entity	*ent;

	if ( argc < 1 )
		{
		return;
		}

	name = argv[ 0 ];
	if ( argc > 1 )
		{
		command = argv[ 1 ];
		}

	// Check for variable commands
	vars = Director.GetVarGroup( name.c_str() );
	if ( vars )
		{
		var = Director.GetVariable( name.c_str() );
		if ( var->isVariableCommand( command.c_str() ) )
			{
			event = new Event( command );
			event->SetSource( EV_FROM_SCRIPT );
			event->SetThread( this );
			event->SetLineNumber( linenumber );
			event->AddTokens( argc - 2, &argv[ 2 ] );
			var->ProcessEvent( event );
			return;
			}

		name = var->stringValue();
		if ( !name.length() )
			{
			ScriptError( "Uninitialized variable '%s' used for command '%s'", var->getName(), command.c_str() );
			return;
			}
		else if ( name[ 0 ] != '$' && name[ 0 ] != '@' && name[ 0 ] != '%' && name[ 0 ] != '*' )
			{
			ScriptError( "Invalid variable command '%s'", command.c_str() );
			return;
			}
		}

	// Check for object commands
	if ( name[ 0 ] == '$' )
		{
		if ( FindEvent( command.c_str() ) )
			{
			event = new Event( command );
			event->SetSource( EV_FROM_SCRIPT );
			event->SetThread( this );
			event->SetLineNumber( linenumber );
			event->AddTokens( argc - 2, &argv[ 2 ] );
			SendCommandToSlaves( name.c_str(), event );
			}
		return;
		}

	// Check for surface commands
	if ( name[ 0 ] == '@' )
		{
		if ( FindEvent( command.c_str() ) )
			{
			event = new Event( command );
			event->SetSource( EV_FROM_SCRIPT );
			event->SetThread( this );
			event->SetLineNumber( linenumber );
			event->AddToken( &name[ 1 ] );
			event->AddTokens( argc - 2, &argv[ 2 ] );
			surfaceManager.ProcessEvent( event );
			}
		return;
		}

 	// Check for console commands
	if ( name[ 0 ] == '%' )
		{
		if ( FindEvent( command.c_str() ) )
			{
			event = new Event( command );
			event->SetSource( EV_FROM_SCRIPT );
			event->SetThread( this );
			event->SetLineNumber( linenumber );
			event->AddToken( &name[ 1 ] );
			event->AddTokens( argc - 2, &argv[ 2 ] );
			consoleManager.ProcessEvent( event );
			}
		return;
		}

   // Check for entnum commands
   if ( name[ 0 ] == '*' )
      {
		if ( !IsNumeric( &name[ 1 ] ) )
			{
			ScriptError( "Expecting numeric value for * command, but found '%s'\n", &name[ 1 ] );
			}
		else if ( FindEvent( command.c_str() ) )
         {
         ent = G_GetEntity( atoi( &name[ 1 ] ) );
         if ( ent )
            {
            event = new Event( command );
				event->SetSource( EV_FROM_SCRIPT );
				event->SetThread( this );
				event->SetLineNumber( linenumber );
            event->AddTokens( argc - 2, &argv[ 2 ] );
            ent->ProcessEvent( event );
            }
         else
            {
            ScriptError( "Entity not found for * command\n" );
            }
         }
      return;   
      }

	// Handle global commands
	if ( FindEvent( name.c_str() ) )
		{
		event = new Event( name );
		event->SetSource( EV_FROM_SCRIPT );
		event->SetThread( this );
		event->SetLineNumber( linenumber );
		event->AddTokens( argc - 1, &argv[ 1 ] );
		if ( !ProcessEvent( event ) )
			{
			ScriptError( "Invalid global command '%s'\n", name.c_str() );
			}
		}
	}

EXPORT_FROM_DLL void ScriptThread::ProcessCommandFromEvent
	(
	Event *ev,
	int startarg
	)
	
	{
	int			argc;
	int			numargs;
	const char	*argv[ MAX_COMMANDS ];
	str			args[ MAX_COMMANDS ];
	int			i;

	numargs = ev->NumArgs();
	if ( numargs < startarg )
		{
		ev->Error( "Expecting statement after conditional", MAX_COMMANDS );
		return;
		}

	argc = numargs - startarg + 1;

	if ( argc >= MAX_COMMANDS )
		{
		ev->Error( "Line exceeds %d command limit", MAX_COMMANDS );
		return;
		}

	for( i = 0; i < argc; i++ )
		{
		args[ i ] = ev->GetToken( startarg + i );
		argv[ i ] = args[ i ].c_str();
		}

	ProcessCommand( argc, argv );
	}

EXPORT_FROM_DLL void ScriptThread::Start
	(
   float delay
	)
	{
	CancelEventsOfType( EV_ScriptThread_Execute );
   if ( delay < 0 )
      ProcessEvent( EV_ScriptThread_Execute );
   else 
      PostEvent( EV_ScriptThread_Execute, delay );
   }

EXPORT_FROM_DLL void ScriptThread::Execute
	(
	Event *ev
	)

	{
	int num;
	ScriptThread *oldthread;
	int argc;
	const char *argv[ MAX_COMMANDS ];
	char args[ MAX_COMMANDS ][ MAXTOKEN ];
	ScriptVariable	*var;

	if ( threadDying )
		{
		return;
		}

	// set the current game time
	if ( !GameTime )
		{
		GameTime = gameVars.CreateVariable( "time", 0 );
		}

	GameTime->setFloatValue( level.time );

	// clear the updateList so that all objects moved this frame are notified before they receive any commands
	// we have to do this here as well as in DoMove, since DoMove may not be called
	updateList.ClearObjectList();

	oldthread = Director.CurrentThread();
	Director.SetCurrentThread( this );

	// if we're not being called from another thread, clear the parm variables
	if ( !oldthread )
		{
		parmVars.ClearList();
		}

	ClearWaitFor();

	var = Director.GetVariable( "parm.previousthread" );
	if ( oldthread )
		{
		var->setIntValue( oldthread->ThreadNum() );
		}
	else
		{
		var->setIntValue( 0 );
		}

	var = Director.GetVariable( "parm.currentthread" );

	doneProcessing = false;

	num = 0;
	while( ( num++ < 10000 ) && !doneProcessing && !threadDying )
		{
		// keep our thread number up to date
		var->setIntValue( threadNum );

		script.SkipNonToken( true );

		// save the line number for errors
		linenumber = script.GetLineNumber();

		argc = 0;
		while( script.TokenAvailable( false ) )
			{
			if ( argc >= MAX_COMMANDS )
				{
				ScriptError( "Line exceeds %d command limit", MAX_COMMANDS );
				script.SkipToEOL();
				break;
				}
			strcpy( args[ argc ], script.GetToken( false ) );
			argv[ argc ] = args[ argc ];
			argc++;
			}

		assert( argc > 0 );

		// Ignore labels
		if ( args[ 0 ][ strlen( args[ 0 ] ) - 1 ] != ':' )
			{
			ProcessCommand( argc, argv );
			}
		}

	if ( !doneProcessing )
		{
		gi.error( "Command overflow.  Possible infinite loop in thread '%s'.\n"
			"Stopping on line %d of %s\n", threadName.c_str(), script.GetLineNumber(), script.Filename() );
		}

	Director.SetCurrentThread( oldthread );

	// Set the thread number on exit, in case we were called by someone who wants to know our thread
	var = Director.GetVariable( "parm.previousthread" );
	var->setIntValue( threadNum );
	}

EXPORT_FROM_DLL void ScriptThread::ScriptError
	(
	const char *fmt,
	...
	)

	{
	va_list	argptr;
	char		text[ 1024 ];

	va_start( argptr, fmt );
	vsprintf( text, fmt, argptr );
	va_end( argptr );

	gi.dprintf( "%s(%d):: %s\n", Filename(), linenumber, text );
	}

//****************************************************************************************
//
// global commands
// 
//****************************************************************************************

EXPORT_FROM_DLL qboolean ScriptThread::WaitingFor
	(
	Entity *obj
	)

	{
	assert( obj );

	if ( waitingFor.length() )
		{
		if ( ( ( waitingFor[ 0 ] == '*' ) && ( atoi( &waitingFor.c_str()[ 1 ] ) == obj->entnum ) ) ||
			( waitingFor == obj->TargetName() ) )
			{
			return true;
			}
		}

	return false;
	}

EXPORT_FROM_DLL void ScriptThread::ObjectMoveDone
	(
	Event *ev
	)

	{
	Entity *obj;

	obj = ev->GetEntity( 1 );
	assert( obj );

#if 0
	gi.dprintf( "Move done %d:'%s'\n", obj->entnum, obj->TargetName() );
#endif

	if ( WaitingFor( obj ) )
		{
      waitingNumObjects--;
      if ( waitingNumObjects <= 0 )
         {
		   ClearWaitFor();
         // start right away
         Start( -1 );
         }
		}
	}

void ScriptThread::CreateThread
	(
	Event *ev
	)

	{
   ScriptThread * pThread;

	pThread = Director.CreateThread( &script, ev->GetToken( 1 ) );
   if ( pThread )
      {
      // start right away
      pThread->Start( -1 );
      }
	}

void ScriptThread::TerminateThread
	(
	Event *ev
	)

	{
   int threadnum;
   ScriptThread *thread;

   threadnum = 0;
   // we specified the thread to kill
   if ( ev->NumArgs() > 0 )
      {
      threadnum = ev->GetInteger( 1 );
      }
   else
      {
   	thread = ev->GetThread();
	   if ( thread )
		   {
		   threadnum = thread->ThreadNum();
		   }
      }

   if ( threadnum != 0 )
      {
      thread = Director.GetThread( threadnum );
      if ( thread && ( thread->GetType() == MODEL_SCRIPT ) && ( ev->GetSource() == EV_FROM_SCRIPT ) )
         {
         ev->Error( "Can't terminate an actor's thread via script." );
         return;
         }
      Director.KillThread( threadnum );
      }
	}

void ScriptThread::ControlObject
	(
	Event *ev
	)

	{
	ev->GetEntity( 1 );
	}

void ScriptThread::EventGoto
	(
	Event *ev
	)

	{
	const char *label;

	label = ev->GetToken( 1 );
	if ( !Goto( label ) )
		{
		ev->Error( "Label '%s' not found", label );
		}
	}

void ScriptThread::EventPause
	(
	Event *ev
	)

	{
	ClearWaitFor();
	doneProcessing = true;
	}

void ScriptThread::EventWait
	(
	Event *ev
	)

	{
	DoMove();

	ClearWaitFor();

	waitUntil = ev->GetFloat( 1 ) + level.time;
	
	Start( ev->GetFloat( 1 ) );
	doneProcessing = true;
	}

void ScriptThread::EventWaitFor
   (
   Event *ev
   )

   {
   Entity *ent;
   const char *objname;
   const char *tname;

   ClearWaitFor();
   doneProcessing = true;

   ent = ev->GetEntity( 1 );
   if ( ent )
      {
      objname = ev->GetString( 1 );
      tname = ent->TargetName();
      if ( objname && objname[ 0 ] == '*' )
         {
         if ( !IsNumeric( &objname[ 1 ] ) )
            {
            ScriptError( "Expecting *-prefixed numeric value for waitFor command, but found '%s'\n", objname );
            return;
            }

         waitingFor = objname;
         }
      else if ( !tname || !tname[ 0 ] )
         {
         // Probably won't happen, but check for it anyway.
         ScriptError( "Entity doesn't have a targetname.\n" );
         return;
         }
      else
         {
         TargetList  *tlist;
         waitingFor = tname;
         //
         // set the number of objects that belong to this targetname
         //
         tlist = GetTargetList( waitingFor );
         waitingNumObjects = tlist->list.NumObjects();
         if ( waitingNumObjects <= 0 )
            {
            waitingNumObjects = 1;
            ScriptError( "no objects of targetname %s found.\n", tname );
            }
         else
            {
            Entity * tent;
            int i;
            //
            // make sure all these objects are in the update list
            //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -