Bladeren bron

Merge pull request #1342 from Areloch/SpawnObjectOverrideOverhaul

SpawnObject Override Overhaul
Brian Roberts 8 maanden geleden
bovenliggende
commit
8274bbbca4

+ 4 - 1
Engine/source/module/moduleDefinition.cpp

@@ -68,7 +68,8 @@ mModuleId(StringTable->EmptyString()),
     mLoadCount( 0 ),
     mLoadCount( 0 ),
     mScopeSet( 0 ),
     mScopeSet( 0 ),
     mLocked( false ),
     mLocked( false ),
-    mpModuleManager( NULL )
+    mpModuleManager( NULL ),
+    mPriority(0.0f)
 {
 {
     // Set Vector Associations.
     // Set Vector Associations.
     VECTOR_SET_ASSOCIATION( mDependencies );
     VECTOR_SET_ASSOCIATION( mDependencies );
@@ -111,6 +112,8 @@ void ModuleDefinition::initPersistFields()
 
 
     /// Misc.
     /// Misc.
     addProtectedField( "Signature", TypeString, 0, &defaultProtectedNotSetFn, &getSignature, &defaultProtectedNotWriteFn, "A unique signature of the module definition based upon its Id, version and build.  This is read-only and is available only after the module has been registered by a module manager." );
     addProtectedField( "Signature", TypeString, 0, &defaultProtectedNotSetFn, &getSignature, &defaultProtectedNotWriteFn, "A unique signature of the module definition based upon its Id, version and build.  This is read-only and is available only after the module has been registered by a module manager." );
+    addProtectedField( "Priority",  TypeF32, 0, &setPriority, &defaultProtectedGetFn, &defaultProtectedNotWriteFn, "A numeric value indicating execution priority for certain callback commands. 0 has the highest priority and is then sorted from there ascending in value.  This is read-only and is available only after the module has been registered by a module manager.");
+
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 6 - 0
Engine/source/module/moduleDefinition.h

@@ -115,6 +115,7 @@ private:
     SimObjectId                     mScopeSet;
     SimObjectId                     mScopeSet;
     bool                            mLocked;
     bool                            mLocked;
     ModuleManager*                  mpModuleManager;
     ModuleManager*                  mpModuleManager;
+    F32                             mPriority;
 
 
 private:
 private:
     inline bool             checkUnlocked( void ) const { if ( mLocked )        { Con::warnf("Ignoring changes for locked module definition."); } return !mLocked; }
     inline bool             checkUnlocked( void ) const { if ( mLocked )        { Con::warnf("Ignoring changes for locked module definition."); } return !mLocked; }
@@ -195,6 +196,9 @@ public:
     inline bool             getModuleLocked( void ) const                       { return mLocked; }
     inline bool             getModuleLocked( void ) const                       { return mLocked; }
     inline ModuleManager*   getModuleManager( void ) const                      { return mpModuleManager; }
     inline ModuleManager*   getModuleManager( void ) const                      { return mpModuleManager; }
 
 
+    inline void             setPriority(const F32 pPriority)                    { if (checkUnlocked()) { mPriority = pPriority; } }
+    inline F32              getPriority(void) const                             { return mPriority; }
+
     using Parent::save;
     using Parent::save;
     bool                    save( void );
     bool                    save( void );
 
 
@@ -332,6 +336,8 @@ protected:
     }
     }
     static bool             writeDependencies( void* obj, StringTableEntry pFieldName ) { return static_cast<ModuleDefinition*>(obj)->getDependencies().size() > 0; }
     static bool             writeDependencies( void* obj, StringTableEntry pFieldName ) { return static_cast<ModuleDefinition*>(obj)->getDependencies().size() > 0; }
     static const char*      getSignature(void* obj, const char* data)                   { return static_cast<ModuleDefinition*>(obj)->getSignature(); }
     static const char*      getSignature(void* obj, const char* data)                   { return static_cast<ModuleDefinition*>(obj)->getSignature(); }
+
+    static bool             setPriority(void* obj, const char* index, const char* data) { static_cast<ModuleDefinition*>(obj)->setPriority((F32)dAtof(data)); return false; }
 };
 };
 
 
 #endif // _MODULE_DEFINITION_H
 #endif // _MODULE_DEFINITION_H

+ 18 - 1
Engine/source/module/moduleManager_ScriptBinding.h

@@ -150,8 +150,14 @@ DefineEngineMethod(ModuleManager, findModuleByFilePath, String, (const char* fil
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
+static S32 QSORT_CALLBACK _findModulesSortByPriority(ModuleDefinition* const* a, ModuleDefinition* const* b)
+{
+   F32 diff = (*a)->getPriority() - (*b)->getPriority();
+   return diff > 0 ? 1 : diff < 0 ? -1 : 0;
+}
 
 
-DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly), (true),
+
+DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly, bool sortByPriority, const char* moduleGroup), (true, false, ""),
    "Find all the modules registered with the specified loaded state.\n"
    "Find all the modules registered with the specified loaded state.\n"
    "@param loadedOnly Whether to return only modules that are loaded or not.\n"
    "@param loadedOnly Whether to return only modules that are loaded or not.\n"
    "@return A list of space - separated module definition object Ids.\n")
    "@return A list of space - separated module definition object Ids.\n")
@@ -174,12 +180,23 @@ DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly), (true)
     char* pReturnBuffer = Con::getReturnBuffer( bufferSize );
     char* pReturnBuffer = Con::getReturnBuffer( bufferSize );
     char* pBufferWrite = pReturnBuffer;
     char* pBufferWrite = pReturnBuffer;
 
 
+    if (sortByPriority)
+       moduleDefinitions.sort(_findModulesSortByPriority);
+
+    StringTableEntry moduleGroupStr = StringTable->insert(moduleGroup);
+
     // Iterate module definitions.
     // Iterate module definitions.
     for ( ModuleManager::typeConstModuleDefinitionVector::const_iterator moduleDefinitionItr = moduleDefinitions.begin(); moduleDefinitionItr != moduleDefinitions.end(); ++moduleDefinitionItr )
     for ( ModuleManager::typeConstModuleDefinitionVector::const_iterator moduleDefinitionItr = moduleDefinitions.begin(); moduleDefinitionItr != moduleDefinitions.end(); ++moduleDefinitionItr )
     {
     {
         // Fetch module definition.
         // Fetch module definition.
         const ModuleDefinition* pModuleDefinition = *moduleDefinitionItr;
         const ModuleDefinition* pModuleDefinition = *moduleDefinitionItr;
 
 
+        if(moduleGroupStr != StringTable->EmptyString())
+        {
+           if (pModuleDefinition->getModuleGroup() != moduleGroupStr)
+              continue;
+        }
+
         // Format module definition.
         // Format module definition.
         const U32 offset = dSprintf( pBufferWrite, bufferSize, "%d ", pModuleDefinition->getId() );
         const U32 offset = dSprintf( pBufferWrite, bufferSize, "%d ", pModuleDefinition->getId() );
         pBufferWrite += offset;
         pBufferWrite += offset;

+ 4 - 4
Templates/BaseGame/game/core/clientServer/Core_ClientServer.tscript

@@ -27,10 +27,10 @@ function Core_ClientServer::finishMapLoad(%this)
     Core_ClientServer.GetEventManager().postEvent( "mapLoadComplete" );
     Core_ClientServer.GetEventManager().postEvent( "mapLoadComplete" );
 }
 }
 
 
-function Core_ClientServer::FailMapLoad(%this, %moduleName, %isFine)
+function Core_ClientServer::FailMapLoad(%this, %moduleName, %canContinueOnFail)
 {    
 {    
     Core_ClientServer.failedModuleName = %moduleName;
     Core_ClientServer.failedModuleName = %moduleName;
-    Core_ClientServer.GetEventManager().postEvent( "mapLoadFail", %isFine );
+    Core_ClientServer.GetEventManager().postEvent( "mapLoadFail", %canContinueOnFail );
 }
 }
 
 
 function Core_ClientServerListener::onMapLoadComplete(%this)
 function Core_ClientServerListener::onMapLoadComplete(%this)
@@ -50,9 +50,9 @@ function Core_ClientServerListener::onMapLoadComplete(%this)
     }
     }
 }
 }
 
 
-function Core_ClientServerListener::onmapLoadFail(%this, %isFine)
+function Core_ClientServerListener::onMapLoadFail(%this, %canContinueOnFail)
 {   
 {   
-    if (%isFine) 
+    if (%canContinueOnFail) 
     {
     {
         %this.onMapLoadComplete();
         %this.onMapLoadComplete();
         return;
         return;

+ 187 - 12
Templates/BaseGame/game/core/clientServer/scripts/server/connectionToClient.tscript

@@ -27,7 +27,7 @@
 // anything else will be sent back as an error to the client.
 // anything else will be sent back as an error to the client.
 // All the connect args are passed also to onConnectRequest
 // All the connect args are passed also to onConnectRequest
 //
 //
-function GameConnection::onConnectRequest( %client, %netAddress, %name )
+function GameConnection::onConnectRequest( %this, %netAddress, %name )
 {
 {
    echo("Connect request from: " @ %netAddress);
    echo("Connect request from: " @ %netAddress);
    if($Server::PlayerCount >= $pref::Server::MaxPlayers)
    if($Server::PlayerCount >= $pref::Server::MaxPlayers)
@@ -47,11 +47,11 @@ function GameConnection::onConnect( %this, %clientData )
 	sendLoadInfoToClient(%this);
 	sendLoadInfoToClient(%this);
 	
 	
 	// Simulated client lag for testing...
 	// Simulated client lag for testing...
-	// %client.setSimulatedNetParams(0.1, 30);
+	// %this.setSimulatedNetParams(0.1, 30);
 	
 	
 	// Get the client's unique id:
 	// Get the client's unique id:
-	// %authInfo = %client.getAuthInfo();
-	// %client.guid = getField(%authInfo, 3);
+	// %authInfo = %this.getAuthInfo();
+	// %this.guid = getField(%authInfo, 3);
 	%this.guid = 0;
 	%this.guid = 0;
 	addToServerGuidList(%this.guid);
 	addToServerGuidList(%this.guid);
 	
 	
@@ -81,19 +81,194 @@ function GameConnection::onConnect( %this, %clientData )
 	
 	
 	%this.connectData = %clientData;
 	%this.connectData = %clientData;
 	
 	
+	//Signal and listener logic for the spawn config/processing here
+	%this.GetEventManager().registerEvent("setSpawnObjectTypeComplete");
+   %this.GetEventManager().registerEvent("setSpawnObjectTypeFailed");
+   %this.GetEventManager().registerEvent("setSpawnPointComplete");
+   %this.GetEventManager().registerEvent("setSpawnPointFailed");
+   %this.GetEventManager().registerEvent("postSpawnComplete");
+   
+   %this.listener = new ScriptMsgListener() {
+      class = GameConnectionListener;
+   }; 
+   %this.GetEventManager().subscribe( %this.listener, "setSpawnObjectTypeComplete" ); 
+   %this.GetEventManager().subscribe( %this.listener, "setSpawnObjectTypeFailed" ); 
+   %this.GetEventManager().subscribe( %this.listener, "setSpawnPointComplete" );
+   %this.GetEventManager().subscribe( %this.listener, "setSpawnPointFailed" );
+   %this.GetEventManager().subscribe( %this.listener, "postSpawnComplete" );
+	
 	callGamemodeFunction("onClientConnect", %this);
 	callGamemodeFunction("onClientConnect", %this);
 	
 	
 	$Server::PlayerCount++;
 	$Server::PlayerCount++;
 }
 }
 
 
+function GameConnection::GetEventManager(%this)
+{
+   if( !isObject( %this.eventManager ) )
+      %this.eventManager = new EventManager() { 
+         queue = "GameConnectionEventManager";
+      };
+      
+   return %this.eventManager;
+}
+
+function GameConnection::spawnControlObject( %this )
+{
+    //baseline controlObject spawn type with extention points
+    %this.spawnClass = "Camera";
+    %this.spawnDBType = "CameraData";
+    %this.spawnDataBlock = "Observer";
+    
+    %this.numModsNeedingLoaded = 0;
+    %this.moduleLoadedDone = 0;
+    %modulesIDList = getModulesAndGameModesList(true, "Game");
+    
+    %this.numModsNeedingLoaded = getNumCanCallOnObjectList("setSpawnObjectType", %modulesIDList);
+    
+    if (%this.numModsNeedingLoaded)
+       callOnObjectList("setSpawnObjectType", %modulesIdList, %this);
+    else
+        %this.GetEventManager().onSetSpawnObjectTypeComplete(); //just jump to progress
+}
+
+function GameConnectionListener::onSetSpawnObjectTypeComplete( %this, %client )
+{
+    %client.moduleLoadedDone++;
+
+    if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
+        return; //continue to wait  
+    
+    if (isObject(%client.player))
+    {
+        // The client should not already have a player. Assigning
+        // a new one could result in an uncontrolled player object.
+        error("Attempting to create a player for a client that already has one!");
+    }
+   
+    // Spawn with the engine's Sim::spawnObject() function
+    %client.player = spawnObject(%client.spawnClass, %client.spawnDataBlock);
+    
+    if (!%client.player.isMemberOfClass(%client.spawnClass))
+        warn("Trying to spawn a class that does not derive from "@ %client.spawnClass);
+
+    // Add the player object to MissionCleanup so that it
+    // won't get saved into the level files and will get
+    // cleaned up properly
+    MissionCleanup.add(%client.player);
+   
+    // Store the client object on the player object for
+    // future reference
+    %client.player.client = %client;
+   
+    %client.setSpawnPoint();
+    
+   // Give the client control of the camera if in the editor
+   if( $startWorldEditor )
+   {
+      %control = %client.camera;
+      %control.mode = "Fly";
+      EditorGui.syncCameraGui();
+   }
+   else
+      %control = %client.player;
+      
+   // Allow the player/camera to receive move data from the GameConnection.  Without this
+   // the user is unable to control the player/camera.
+   if (!isDefined("%noControl"))
+      %client.setControlObject(%control);
+}
+
+function GameConnectionListener::onSetSpawnObjectTypeFailed( %this, %client, %canContinueOnFail )
+{
+   errorf("Failed to properly set Spawn Object Type for client: " @ %client);
+}
+
+function GameConnection::setSpawnPoint( %this )
+{
+    //baseline spawn point config rules with extention points
+    %this.playerSpawnGroups = "PlayerSpawnPoints PlayerDropPoints";
+    %this.spawnPoint = "";
+    %this.spawnLocation = "0 0 0";
+    
+    %this.numModsNeedingLoaded = 0;
+    %this.moduleLoadedDone = 0;
+    %modulesIDList = getModulesAndGameModesList(true, "Game");
+    
+    %this.numModsNeedingLoaded = getNumCanCallOnObjectList("setSpawnPoint", %modulesIDList);
+    
+    if (%this.numModsNeedingLoaded)
+        callOnObjectList("setSpawnPoint", %modulesIdList, %this);
+    else
+        %this.GetEventManager().onSetSpawnPointComplete();   
+}
+
+function GameConnectionListener::onSetSpawnPointComplete( %this, %client )
+{
+    %client.moduleLoadedDone++;
+    if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
+        return; //continue to wait 
+    
+    if (isObject(%client.player))
+        %client.player.setTransform(%client.spawnLocation);
+    else
+    {
+        // If we weren't able to create the player object then warn the user
+        // When the player clicks OK in one of these message boxes, we will fall through
+        // to the "if (!isObject(%player))" check below.
+        if (isDefined("%this.spawnDataBlock"))
+        {
+            MessageBoxOK("Spawn Failed",
+                "Unable to create a player with class " @ %client.spawnClass @
+                " and datablock " @ %client.spawnDataBlock @ ".\n\nStarting as an Observer instead.",
+                "");
+        }
+        else
+        {
+            MessageBoxOK("Spawn Failed",
+                "Unable to create a player with class " @ %client.spawnClass @
+                ".\n\nStarting as an Observer instead.",
+                "");
+        }
+    }
+    %client.onPostSpawn();
+}
+
+function GameConnectionListener::onSetSpawnPointFailed( %this, %client, %canContinueOnFail )
+{
+   errorf("Failed to properly set Spawn Object Type for client: " @ %client);
+}
+
+function GameConnection::onPostSpawn( %this )
+{
+    %this.numModsNeedingLoaded = 0;
+    %this.moduleLoadedDone = 0;
+    %modulesIDList = getModulesAndGameModesList(true, "Game");
+    
+    %this.numModsNeedingLoaded = getNumCanCallOnObjectList("onPostSpawn", %modulesIDList);
+    
+    if (%this.numModsNeedingLoaded)
+        callOnObjectList("onPostSpawn", %modulesIdList, %this);
+    else
+        %this.GetEventManager().onPostSpawnComplete();    
+}
+
+function GameConnectionListener::onPostSpawnComplete(%this, %client)
+{
+    %client.moduleLoadedDone++;
+    if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
+        return; //continue to wait 
+        
+    //Continue on. Room for special handling here if needbe but not expressly required
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // A player's name could be obtained from the auth server, but for
 // A player's name could be obtained from the auth server, but for
 // now we use the one passed from the client.
 // now we use the one passed from the client.
 // %realName = getField( %authInfo, 0 );
 // %realName = getField( %authInfo, 0 );
 //
 //
-function GameConnection::setPlayerName(%client,%name)
+function GameConnection::setPlayerName(%this,%name)
 {
 {
-   %client.sendGuid = 0;
+   %this.sendGuid = 0;
 
 
    // Minimum length requirements
    // Minimum length requirements
    %name = trim( strToPlayerName( %name ) );
    %name = trim( strToPlayerName( %name ) );
@@ -112,8 +287,8 @@ function GameConnection::setPlayerName(%client,%name)
    }
    }
 
 
    // Tag the name with the "smurf" color:
    // Tag the name with the "smurf" color:
-   %client.nameBase = %name;
-   %client.playerName = addTaggedString("\cp\c8" @ %name @ "\co");
+   %this.nameBase = %name;
+   %this.playerName = addTaggedString("\cp\c8" @ %name @ "\co");
 }
 }
 
 
 function isNameUnique(%name)
 function isNameUnique(%name)
@@ -132,7 +307,7 @@ function isNameUnique(%name)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // This function is called when a client drops for any reason
 // This function is called when a client drops for any reason
 //
 //
-function GameConnection::onDrop(%client, %reason)
+function GameConnection::onDrop(%this, %reason)
 {
 {
    %entityIds = parseMissionGroupForIds("Entity", "");
    %entityIds = parseMissionGroupForIds("Entity", "");
    %entityCount = getWordCount(%entityIds);
    %entityCount = getWordCount(%entityIds);
@@ -148,15 +323,15 @@ function GameConnection::onDrop(%client, %reason)
             %entityIds = %entityIds SPC %child.getID();  
             %entityIds = %entityIds SPC %child.getID();  
       }
       }
       
       
-      %entity.notify("onClientDisconnect", %client);
+      %entity.notify("onClientDisconnect", %this);
    }
    }
    
    
    if($missionRunning)
    if($missionRunning)
    {
    {
-      %hasGameMode = callGamemodeFunction("onClientLeaveGame", %client);
+      %hasGameMode = callGamemodeFunction("onClientLeaveGame", %this);
    }
    }
    
    
-   removeFromServerGuidList( %client.guid );
+   removeFromServerGuidList( %this.guid );
 
 
    $Server::PlayerCount--;
    $Server::PlayerCount--;
 }
 }

+ 2 - 0
Templates/BaseGame/game/core/clientServer/scripts/server/levelDownload.tscript

@@ -178,6 +178,8 @@ function serverCmdMissionStartPhase3Ack(%client, %seq)
    %client.currentPhase = 3;
    %client.currentPhase = 3;
    
    
    %hasGameMode = callGamemodeFunction("onClientEnterGame", %client);
    %hasGameMode = callGamemodeFunction("onClientEnterGame", %client);
+
+   %client.spawnControlObject();
    
    
    //if that also failed, just spawn a camera
    //if that also failed, just spawn a camera
    if(%hasGameMode == 0)
    if(%hasGameMode == 0)

+ 84 - 0
Templates/BaseGame/game/core/utility/scripts/helperFunctions.tscript

@@ -698,4 +698,88 @@ function playSoundAsset(%soundAssetId,%pos)
   }
   }
   AssetDatabase.releaseAsset(%soundAssetId);
   AssetDatabase.releaseAsset(%soundAssetId);
   return %handle;
   return %handle;
+}
+
+//------------------------------------------------------------------------------
+function getModulesAndGameModesList(%usePriority, %group)
+{
+   %modulesList = ModuleDatabase.findModules(true, %usePriority, %group);
+   %modulesIDList = "";
+    
+   for(%i=0; %i < getWordCount(%modulesList); %i++)
+   {
+      %module = getWord(%modulesList, %i);
+      
+      %modulesIDList = %modulesIDList SPC %module.ModuleId;
+   }    
+   
+   %gamemodeList = getGameModesList();
+   %gameModeCount = %gamemodeList.count();
+   for(%i=0; %i < %gameModeCount; %i++)
+   {
+      %gameModeObj = %gamemodeList.getKey(%i);
+      %active = %gamemodeList.getValue(%i);
+      
+      if(!isObject(%gameModeObj) || !%active)
+         continue;
+         
+      %modulesIDList = %modulesIDList SPC %gameModeObj;
+   }
+   
+   %modulesIDList = strreplace(%modulesIDList, "  "," ");
+   %modulesIDList = trim(%modulesIDList);
+   return %modulesIDList;
+}
+
+function callOnObjectList(%functionName, %objectsList, %var0, %var1, %var2, %var3, %var4, %var5, %var6)
+{   
+   //Get our modules so we can exec any specific client-side loading/handling
+   %echoList = "Called List:";
+   for(%i=0; %i < getWordCount(%objectsList); %i++)
+   {
+      %obj = getWord(%objectsList, %i);
+      %objName = %obj.getName();
+      
+      if(!isObject(%obj))
+      {
+         //could be a moduleID we're trying to call against, so try a lookup
+         %module = ModuleDatabase.findModule(%obj);
+         if(isObject(%module))
+         {
+            %obj = %module.scopeSet;  
+            %objName = %module.ModuleId;
+         }
+      }
+      
+      %echoList = %echoList SPC %objName;
+
+      // match this to i/o signature
+      if(isObject(%obj) && %obj.isMethod(%functionName))
+       %obj.call(%functionName, %var0, %var1, %var2, %var3, %var4, %var5, %var6);
+   }
+   
+   if ($reportModuleOrder)
+      warn(%echoList);  
+}
+
+function getNumCanCallOnObjectList(%functionName, %objectsList)
+{ 
+   %numberWithFunction = 0;
+   for(%i=0; %i < getWordCount(%objectsList); %i++)
+   {
+      %obj = getWord(%objectsList, %i);
+      if(!isObject(%obj))
+      {
+         //could be a moduleID we're trying to call against, so try a lookup
+         %module = ModuleDatabase.findModule(%obj);
+         if(isObject(%module))
+            %obj = %module.scopeSet;  
+      }
+      
+      // match this to i/o signature
+      if(isObject(%obj) && %obj.isMethod(%functionName))
+         %numberWithFunction++;
+   }
+   
+   return %numberWithFunction;
 }
 }

+ 0 - 96
Templates/BaseGame/game/data/ExampleModule/scripts/shared/ExampleGameMode.tscript

@@ -51,16 +51,6 @@ function ExampleGameMode::onMissionReset(%this)
 
 
 function ExampleGameMode::initGameVars(%this)
 function ExampleGameMode::initGameVars(%this)
 {
 {
-   //-----------------------------------------------------------------------------
-   // What kind of "camera" is spawned is either controlled directly by the
-   // SpawnSphere or it defaults back to the values set here. This also controls
-   // which SimGroups to attempt to select the spawn sphere's from by walking down
-   // the list of SpawnGroups till it finds a valid spawn object.
-   // These override the values set in core/scripts/server/spawn.cs
-   //-----------------------------------------------------------------------------
-   %this.defaultCameraClass = "Camera";
-   %this.defaultCameraDataBlock = "Observer";
-   %this.defaultCameraSpawnGroups = "CameraSpawnPoints PlayerSpawnPoints PlayerDropPoints";
 }
 }
 
 
 function ExampleGameMode::onGameDurationEnd(%this)
 function ExampleGameMode::onGameDurationEnd(%this)
@@ -82,15 +72,6 @@ function ExampleGameMode::onClientEnterGame(%this, %client)
    //Set the player name based on the client's connection data
    //Set the player name based on the client's connection data
    %client.setPlayerName(%client.connectData);
    %client.setPlayerName(%client.connectData);
 
 
-   // Find a spawn point for the camera
-   // This function currently relies on some helper functions defined in
-   // core/scripts/server/spawn.cs. For custom spawn behaviors one can either
-   // override the properties on the SpawnSphere's or directly override the
-   // functions themselves.
-   %cameraSpawnPoint = %this.pickCameraSpawnPoint(%this.DefaultCameraSpawnGroups);
-   // Spawn a camera for this client using the found %spawnPoint
-   %this.spawnCamera(%client, %cameraSpawnPoint);
-
    // Inform the client of all the other clients
    // Inform the client of all the other clients
    %count = ClientGroup.getCount();
    %count = ClientGroup.getCount();
    for (%cl = 0; %cl < %count; %cl++)
    for (%cl = 0; %cl < %count; %cl++)
@@ -175,81 +156,4 @@ function ExampleGameMode::onSubsceneUnloaded(%this)
 {
 {
    echo("===================================");
    echo("===================================");
    echo("ExampleGameMode - Subscene is unloaded");  
    echo("ExampleGameMode - Subscene is unloaded");  
-}
-
-function ExampleGameMode::spawnCamera(%this, %client, %spawnPoint)
-{
-   // Set the control object to the default camera
-   if (!isObject(%client.camera))
-   {
-      if (%this.defaultCameraClass !$= "")
-         %client.camera = spawnObject(%this.defaultCameraClass, %this.defaultCameraDataBlock);
-   }
-
-   // If we have a camera then set up some properties
-   if (isObject(%client.camera))
-   {
-      MissionCleanup.add( %client.camera );
-      %client.camera.scopeToClient(%client);
-
-      %client.setControlObject(%client.camera);
-      
-      if(!isObject(%spawnPoint))
-         %spawnPoint = %this.pickCameraSpawnPoint(%this.defaultCameraSpawnGroups);
-
-      if (isObject(%spawnPoint))
-      {
-         // Attempt to treat %spawnPoint as an object
-         if (getWordCount(%spawnPoint) == 1 && isObject(%spawnPoint))
-         {
-            %client.camera.setTransform(%spawnPoint.getTransform());
-         }
-         else
-         {
-            // Treat %spawnPoint as an AxisAngle transform
-            %client.camera.setTransform(%spawnPoint);
-         }
-      }
-   }
-}
-
-//-----------------------------------------------------------------------------
-// pickCameraSpawnPoint() is responsible for finding a valid spawn point for a
-// camera.
-//-----------------------------------------------------------------------------
-function ExampleGameMode::pickCameraSpawnPoint(%this, %spawnGroups)
-{
-   // Walk through the groups until we find a valid object
-   for (%i = 0; %i < getWordCount(%spawnGroups); %i++)
-   {
-      %group = getWord(%spawnGroups, %i);
-      
-      %count = getWordCount(%group);
-
-      if (isObject(%group))
-         %spawnPoint = %group.getRandom();
-
-      if (isObject(%spawnPoint))
-         return %spawnPoint;
-   }
-
-   // Didn't find a spawn point by looking for the groups
-   // so let's return the "default" SpawnSphere
-   // First create it if it doesn't already exist
-   if (!isObject(DefaultCameraSpawnSphere))
-   {
-      %spawn = new SpawnSphere(DefaultCameraSpawnSphere)
-      {
-         dataBlock      = "SpawnSphereMarker";
-         spawnClass     = $Game::DefaultCameraClass;
-         spawnDatablock = $Game::DefaultCameraDataBlock;
-      };
-
-      // Add it to the MissionCleanup group so that it
-      // doesn't get saved to the Mission (and gets cleaned
-      // up of course)
-      MissionCleanup.add(%spawn);
-   }
-
-   return DefaultCameraSpawnSphere;
 }
 }