UMS1_6
Class Director

source: e:\games\UnrealTournament\UMS1_6\Classes\Director.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--UMS1_6.UMS
         |
         +--UMS1_6.Director
Direct Known Subclasses:None

class Director
extends UMS1_6.UMS

//============================================================================= // Director. //=============================================================================
Variables
 int CurrentCommand
 int CurrentIterations
 class LoadedModuleClasses[20]
 UMSModule LoadedModules[20]
 name ScriptNames[50]
 rotator ScriptRotators[50]
 float ScriptVals2[50]
 float ScriptVals[50]
 vector ScriptVectors[50]
 string Script[50]
 string UMSModules[20]
 float WaitTime
 float WaitTimes[50]
 bool bDoneWithMovie
 bool bLoadedModules
 bool bRolling
 int numLoadedModules

States
Rolling, Waiting

Function Summary
 void CallCommand(string currentScript)
 void CallNewDirector(string DirectorName)
 string CutOutWord(string Word, string Message)
     
//Takes "word" out of "message" and returns the new string.
 void ExecuteChangeLevel(string Command)
     
//*******************************************************************
//ChangeLevel Stuff
//*******************************************************************
 void ExecuteLoop(string Command)
     
//*******************************************************************
//Loop Stuff
//*******************************************************************
 void ExecuteNextCommand()
     
//Grab the next command from the script and execute it.
 Actor FindActor(string ActorName)
 Pawn FindPawn(string PawnName)
     
//*******************************************************************
//Finding Stuff
//*******************************************************************
 string GetFirstWord(String Message)
     
//This returns the first word (everything before the first space) of 
//the string it is given.
 void GoBackToMyTrailer()
     
//This function is called when the Director has finished all the 
//commands for its script, but there is still stuff in the level
//that needs to occur.
 void GoBackToWaiting()
 void LoadModules()
 void postBeginPlay()
     
//States are kind of like subclasses of the current class.  When an
//object goes into a new state, its functions can be overridden, so
//its behavior can change tottally, even though it is still the same
//objet.  It also, starting at "Begin:" runs through a series of 
//sequential commands that can have more headers and be looped.
//
//In this case, the director starts out waiting for bRolling to be
//true so it can start executing commands.  When this happens it goes
//to state Rolling which does all the checks for waiting on pawns and
//cameras, and executes a command if possible.
 string tokenize(out string, string delim)


State Rolling Function Summary


State Waiting Function Summary



Source Code


00001	//=============================================================================
00002	// Director.
00003	//=============================================================================
00004	class Director expands UMS;
00005	
00006	//Whether or not the Director has started issuing commands.  Set this
00007	//property to true if you want the Director to start as soon as the
00008	//level loads.
00009	var() bool bRolling;
00010	//The Director follows this Script and issues its commands to objects.
00011	//The Script is an array of strings--each string is a single command.
00012	var() string Script[50];
00013	//These are values that certian script commands need to function.
00014	//They match the command number they are used with.  For example: if 
00015	//command #19 is a 'Wait Time' command, ScriptValsOne[19] is the
00016	//amount of time to wait
00017	//
00018	//Contains times, the amount of time to wait after processing this
00019	//command before doing something else.
00020	var() float WaitTimes[50];
00021	//Contains floats, used for commands which use float values.
00022	var() float ScriptVals[50];
00023	var() float ScriptVals2[50];
00024	//Contains vectors, used for commands which use vectors.
00025	var() vector ScriptVectors[50];
00026	//Contains rotators used for commands that use rotators.
00027	var() rotator ScriptRotators[50];
00028	//Contains names used for commands that need names and not strings.
00029	var() name ScriptNames[50];
00030	
00031	//Contains the modules to load on run.
00032	var() string UMSModules[20];
00033	var class<UMSModule> LoadedModuleClasses[20];
00034	var UMSModule LoadedModules[20];
00035	var int numLoadedModules;
00036	
00037	var bool bLoadedModules;
00038	//
00039	//This is the number of the Script command that is currently being
00040	//executed.
00041	var int CurrentCommand;
00042	//This is how long the Director must wait until the next command
00043	//can be issued.
00044	var float WaitTime;
00045	//Used to count iterations when looping withing a Director's script
00046	var int CurrentIterations;
00047	
00048	var bool bDoneWithMovie;
00049	
00050	
00051	//Director will start using the script if triggered.  This is great if
00052	//you want the script to wait until a certian action is preformed to
00053	//start.  Also means you can have multiple directors in a level, who
00054	//trigger each other when done.
00055	
00056	//Grab the next command from the script and execute it.
00057	function ExecuteNextCommand()
00058	{
00059		bDoneWithMovie = false;
00060		
00061		if (CurrentCommand > 50)
00062			GoBackToMyTrailer();	// We dont want to access out of bounds.
00063			
00064		
00065		CallCommand(Script[CurrentCommand]);
00066		
00067	   
00068	    //Now wait the appropriate amount of time before doing the next
00069	    //command.
00070	    WaitTime = WaitTimes[CurrentCommand];
00071	    GotoState('Waiting');
00072	    
00073	    CurrentCommand++;
00074	}
00075	
00076	function CallCommand(string currentScript)
00077	{
00078		local string thisScript[20];
00079		local int i;
00080		
00081		i = 0;
00082		
00083		log(self@": Running command:"@currentScript);
00084	
00085		while(Len(currentScript) != 0)
00086		{
00087			thisScript[i] = tokenize(currentScript, " ");
00088			i++;
00089		}
00090	
00091	    switch(thisScript[0])    
00092	    {
00093	        case "ChangeLevel":				// Go to another level.
00094	            ExecuteChangeLevel(thisScript[1]);
00095	            break;
00096	        case "Loop":					// ?
00097	            ExecuteLoop(thisScript[1]);
00098	            break;
00099	        case "Done":					// 
00100	            GoBackToMyTrailer();		// -- Done: Kills director.
00101	            break;						//
00102	        case "Reset":					//
00103				GoBackToWaiting();			// -- Reset: Resets and suspends Director.
00104				break;						//
00105			case "Restart":					//
00106				CurrentCommand = -1;		// -- Restart: Causes director to loop.
00107				break;						//
00108			case "Director":
00109				CallNewDirector(thisScript[1]);
00110				break;
00111			case "":
00112				GoBackToMyTrailer();
00113	            break;
00114	        default:
00115	        	RunModuleCommand(thisScript);
00116	        	break;
00117	    }
00118	}
00119	
00120	function string tokenize(out string origString, string delim)
00121	{
00122	    local int lcv, stringLength;
00123	    local String Parser, FirstWord;
00124	    
00125	    stringLength = Len(origString);
00126	    
00127	    for(lcv = 0; lcv < stringLength; lcv++)
00128	    {
00129	        Parser = Mid(origString, lcv, 1);
00130	        
00131	        if(Parser == " ")
00132	            break;
00133	    }
00134	    
00135	    FirstWord = Mid(origString, 0, lcv);
00136	    
00137	    for(lcv = lcv; lcv < stringLength; lcv++)
00138	    {
00139	    	Parser = Mid(origString, lcv, 1);
00140	    	
00141	    	if(Parser != " ")
00142	    		break;
00143	    }
00144	    
00145	    origString = Mid(origString, lcv, stringLength - lcv);
00146	    
00147	    return FirstWord;
00148	}
00149	
00150	function RunModuleCommand(string thisScript[20])
00151	{
00152		local int i;
00153		local bool bDone;
00154		
00155		bDone = false;
00156		
00157		for(i = 0; i < numLoadedModules; i++)
00158		{
00159			if(LoadedModules[i].runModuleCommand(thisScript, ScriptVals[CurrentCommand], ScriptVals2[CurrentCommand], ScriptNames[CurrentCommand], ScriptVectors[CurrentCommand], ScriptRotators[CurrentCommand], self))
00160			{
00161				bDone = true;
00162				break;
00163			}
00164		}
00165		
00166		if(!bDone)
00167		{
00168			log(self$": Command failed to execute:"@Script[CurrentCommand]);
00169		}
00170	}
00171	
00172	function startRunning(UMSModule oldLoadedModules[20], int numOldLoadedModules)
00173	{
00174		local int i;
00175	
00176		numLoadedModules = numOldLoadedModules;
00177		log(self$": Copying module references...");
00178		
00179		for(i = 0; i < numLoadedModules; i++)
00180		{
00181			log(self$": Copying"@oldLoadedModules[i]);
00182			LoadedModules[i] = oldLoadedModules[i];
00183			log(self$": Copied"@LoadedModules[i]);
00184		}
00185		
00186	  	bLoadedModules = true;
00187	  	bRolling = true;
00188		bDoneWithMovie = false;
00189		Log ("I have been started! "$Self);
00190		CurrentCommand = 0;
00191	}
00192	
00193	function CallNewDirector(string DirectorName)
00194	{
00195		local Director D;
00196		
00197	    foreach AllActors(class 'Director', D)
00198	        if (DirectorName ~= string(D.Tag) || DirectorName ~= string(D.Name))
00199	               D.startRunning(LoadedModules, numLoadedModules);
00200	}
00201	
00202	//This function is called when the Director has finished all the 
00203	//commands for its script, but there is still stuff in the level
00204	//that needs to occur.
00205	function GoBackToMyTrailer()
00206	{
00207		local int i;
00208	
00209		// Cort added me, to return to interactive mode after movie ends
00210		local PlayerPawn P;
00211		foreach AllActors(class 'PlayerPawn', P)
00212	        P.ViewTarget = P;
00213		/*
00214		for(i = 0; i < numLoadedModules; i++)
00215		{
00216			LoadedModules[i].Destroy();
00217		}
00218		Log ("Destroying Self ("$Self$"). Save me Yoda!");
00219		Destroy();
00220		*/
00221	}
00222	
00223	
00224	function GoBackToWaiting()
00225	{
00226		bRolling = false;
00227		CurrentCommand = 0;          
00228		bDoneWithMovie = true;
00229		WaitTime = 0.1;
00230		GotoState('Waiting');
00231	}
00232	
00233	//States are kind of like subclasses of the current class.  When an
00234	//object goes into a new state, its functions can be overridden, so
00235	//its behavior can change tottally, even though it is still the same
00236	//objet.  It also, starting at "Begin:" runs through a series of 
00237	//sequential commands that can have more headers and be looped.
00238	//
00239	//In this case, the director starts out waiting for bRolling to be
00240	//true so it can start executing commands.  When this happens it goes
00241	//to state Rolling which does all the checks for waiting on pawns and
00242	//cameras, and executes a command if possible.
00243	
00244	function postBeginPlay()
00245	{
00246		if(bRolling)
00247		{
00248			LoadModules();
00249		}
00250	}
00251	
00252	function LoadModules()
00253	{
00254		local int i, j;
00255		local string thisModuleName;
00256		
00257		i = 0;
00258		j = 0;
00259	
00260		while(UMSModules[j] != "")
00261		{
00262			log(self$": About to load module"@UMSModules[j]);
00263	
00264			if(instr(UMSModules[j], ".") == -1)
00265				thisModuleName = UMSModules[j]$"."$UMSModules[j];
00266			else
00267				thisModuleName = UMSModules[j];
00268	
00269			log(self$": Loading module"@thisModuleName);
00270			LoadedModuleClasses[i] = class<UMSModule>(DynamicLoadObject(thisModuleName, class'Class'));
00271			LoadedModules[i] = spawn(LoadedModuleClasses[i]);
00272			j++;
00273			if(LoadedModules[i] != none)
00274			{
00275				log(self$": Loaded module"@LoadedModules[i]);
00276				i++;
00277			}
00278			else
00279			{
00280				log(self$": Failed to load module");
00281			}
00282		}
00283		numLoadedModules = i;
00284		bLoadedModules = true;
00285		
00286		log(self$": Loaded"@i@"modules out of a possible"@j);
00287	}
00288	
00289	
00290	auto state Waiting
00291	{
00292	Begin:
00293	StartWaiting:
00294	    Sleep(WaitTime);
00295	    GotoState('Rolling');
00296	}
00297	
00298	state Rolling
00299	{
00300	Begin:
00301		if(!bRolling)
00302		{
00303	        GotoState('Waiting');
00304		}
00305	ExecuteCommand:
00306	    if(bRolling)
00307	    {
00308	    	if(bLoadedModules)
00309	    	{
00310	        	ExecuteNextCommand();
00311	        }
00312		}
00313	CheckForWait:
00314	    Goto'Begin';
00315	}
00316	
00317	
00318	//*******************************************************************
00319	//ChangeLevel Stuff
00320	//*******************************************************************
00321	
00322	function ExecuteChangeLevel(string Command)
00323	{
00324	    local string URL;
00325	    local GameInfo NewGame;
00326	    local class<GameInfo> GameClass;
00327	    local PlayerPawn M;
00328	    
00329	    // Reset the game class.
00330	    GameClass.Static.ResetGame();
00331	
00332	    URL = Command; //$"?Game="$GameType$"?Mutator="$MutatorList;
00333	
00334	    //ParentWindow.Close();
00335	    //Root.Console.CloseUWindow();
00336	    
00337	    foreach AllActors(class 'PlayerPawn', M)
00338	    {
00339	        M.ClientTravel(URL, TRAVEL_Absolute, false);
00340	    }
00341	}
00342	
00343	
00344	//*******************************************************************
00345	//Loop Stuff
00346	//*******************************************************************
00347	
00348	function ExecuteLoop(string Command)
00349	{
00350	    local int NewCommandLine;
00351	    local float DesiredIterations;
00352	    
00353	    NewCommandLine = int(Command);
00354	    DesiredIterations = ScriptVals[CurrentCommand];
00355	    
00356	    if(DesiredIterations > 0)
00357	    {
00358	        CurrentIterations++;
00359	    }
00360	    
00361	    if(CurrentIterations <= DesiredIterations)
00362	    {
00363	        //We change it to NewCommandLine - 1 so that the increment that
00364	        //occurs after this command is performed will set it to the
00365	        //desired command line number.
00366	        CurrentCommand = NewCommandLine - 1;
00367	    }
00368	    else
00369	    {
00370	        //Do nothing
00371	        CurrentIterations = 0;
00372	    }
00373	}
00374	
00375	
00376	
00377	//*******************************************************************
00378	//Finding Stuff
00379	//*******************************************************************
00380	
00381	function Pawn FindPawn(string PawnName)
00382	{
00383	    local Pawn P;
00384	
00385	    foreach AllActors(class'Pawn', P)
00386	        if (PawnName ~= string(P.Tag) || PawnName ~= string(P.Name))
00387	               return P;
00388	    //If there is no matching pawn, return none.
00389	    return NONE;
00390	}
00391	
00392	function Actor FindActor(string ActorName)
00393	{
00394	    local Actor A;
00395	
00396	    foreach AllActors(class 'Actor', A)
00397	        if (ActorName ~= string(A.Tag) || ActorName ~= string(A.Name))
00398	               return A;
00399	    //If there is no matching actor, return none.
00400	    return NONE;
00401	}
00402	
00403	//*******************************************************************
00404	//String Stuff
00405	//*******************************************************************
00406	
00407	//This returns the first word (everything before the first space) of 
00408	//the string it is given.
00409	function string GetFirstWord(String Message)
00410	{
00411	    local int lcv, MessLength;
00412	    local String Parser, FirstWord;
00413	    
00414	    MessLength = Len(Message);
00415	    
00416	    for(lcv = 0; lcv < MessLength; lcv++)
00417	    {
00418	        Parser = Mid(Message, lcv, 1);
00419	        
00420	        if(Parser == " ")
00421	            break;
00422	    }
00423	    
00424	    FirstWord = Mid(Message, 0, lcv);
00425	    
00426	    return FirstWord;
00427	}
00428	
00429	//Takes "word" out of "message" and returns the new string.
00430	function string CutOutWord(string Word, string Message)
00431	{
00432	    local int Pos, WordLength, MessageLength;
00433	    local String NewMessage;
00434	    
00435	    WordLength = Len(Word);
00436	    MessageLength = Len(Message);
00437	    Pos = InStr(Message, Word);
00438	    
00439	    //if Word is not in Message, then return a blank string
00440	    if(Pos < 0)
00441	        return "";
00442	    
00443	    //If we are at the end of the message, just get what is before
00444	    //the word, but not the space before it.  If not, get what is
00445	    //before and after, and get rid of the space after the word.
00446	    if((Pos + WordLength) >= MessageLength)
00447	        NewMessage = Mid(Message,0,Pos);
00448	    else
00449	        NewMessage = Mid(Message,0,Pos) $ Mid(Message, (Pos + WordLength + 1));
00450	
00451	    return NewMessage;
00452	}
00453	
00454	defaultproperties
00455	{
00456	     UMSModules(0)="UMSCamera"
00457	     UMSModules(1)="UMSPawn"
00458	     UMSModules(2)="UMSEffects"
00459	     UMSModules(3)="UMSHud"
00460	}

End Source Code