context: //-----------------------------------------------------------------------------
  // Torque Game Engine 
  // Copyright (C) GarageGames.com, Inc.
  //-----------------------------------------------------------------------------
  
  // Game duration in secs, no limit if the duration is set to 0
  $Game::Duration = 20 * 60;
  
  // When a client score reaches this value, the game is ended.
  $Game::EndGameScore = 30;
  
  // Pause while looking over the end game screen (in secs)
  $Game::EndGamePause = 10;
  
  
  //-----------------------------------------------------------------------------
  //  Functions that implement game-play
  //-----------------------------------------------------------------------------
  
  //-----------------------------------------------------------------------------
  
  function onServerCreated()
  {
     // Server::GameType is sent to the master server.
     // This variable should uniquely identify your game and/or mod.
     $Server::GameType = "FPS Starter Kit";
  
     // Server::MissionType sent to the master server.  Clients can
     // filter servers based on mission type.
     $Server::MissionType = "Deathmatch";
  
     // GameStartTime is the sim time the game started. Used to calculated
     // game elapsed time.
     $Game::StartTime = 0;
  
     // Load up all datablocks, objects etc.  This function is called when
     // a server is constructed.
     exec("./audioProfiles.cs");
     exec("./envAudioProfiles.cs");
     exec("./camera.cs");
     exec("./markers.cs"); 
     exec("./triggers.cs"); 
     exec("./inventory.cs");
     exec("./shapeBase.cs");
     exec("./item.cs");
     exec("./environment.cs");
     exec("./health.cs");
     exec("./staticShape.cs");
     exec("./weapon.cs");
     exec("./radiusDamage.cs");
     exec("./crossbow.cs");
     exec("./environment.cs");
     
     exec("common/serverScripts/lightingSystem.cs");
     
     exec("./player.cs");
     exec("./chimneyfire.cs");
     exec("./aiPlayer.cs");
     
     exec("./sgExamples.cs");
     
     // Load up any custom light data
     lightLoadDataBlocks(expandFileName("~/server/scripts/sgCustomLights/"));
  
     // Keep track of when the game started
     $Game::StartTime = $Sim::Time;
  }
  
  function onServerDestroyed()
  {
     // This function is called as part of a server shutdown.
  }
  
  
  //-----------------------------------------------------------------------------
  
  function onMissionLoaded()
  {
     // Called by loadMission() once the mission is finished loading.
     // Nothing special for now, just start up the game play.
     startGame();
  }
  
  function onMissionEnded()
  {
     // Called by endMission(), right before the mission is destroyed
  
     // Normally the game should be ended first before the next
     // mission is loaded, this is here in case loadMission has been
     // called directly.  The mission will be ended if the server
     // is destroyed, so we only need to cleanup here.
     cancel($Game::Schedule);
     $Game::Running = false;
     $Game::Cycling = false;
  }
  
  
  //-----------------------------------------------------------------------------
  
  function startGame()
  {
     if ($Game::Running) {
        error("startGame: End the game first!");
        return;
     }
  
     // Inform the client we're starting up
     for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) {
        %cl = ClientGroup.getObject( %clientIndex );
        commandToClient(%cl, 'GameStart');
  
        // Other client specific setup..
        %cl.score = 0;
     }
  
     // Start the game timer
     if ($Game::Duration)
        $Game::Schedule = schedule($Game::Duration * 1000, 0, "onGameDurationEnd" );
     $Game::Running = true;
     
     // Start the AIManager
     new ScriptObject(AIManager) {};
     MissionCleanup.add(AIManager);
     AIManager.think();
  }
  
  function endGame()
  {
     if (!$Game::Running)  {
        error("endGame: No game running!");
        return;
     }
     
     // Stop the AIManager
     AIManager.delete();
  
     // Stop any game timers
     cancel($Game::Schedule);
  
     // Inform the client the game is over
     for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) {
        %cl = ClientGroup.getObject( %clientIndex );
        commandToClient(%cl, 'GameEnd');
     }
  
     // Delete all the temporary mission objects
     resetMission();
     $Game::Running = false;
  }
  
  function onGameDurationEnd()
  {
     // This "redirect" is here so that we can abort the game cycle if
     // the $Game::Duration variable has been cleared, without having
     // to have a function to cancel the schedule.
     if ($Game::Duration && !isObject(EditorGui))
        cycleGame();
  }
  
  
  //-----------------------------------------------------------------------------
  
  function cycleGame()
  {
     // This is setup as a schedule so that this function can be called
     // directly from object callbacks.  Object callbacks have to be
     // carefull about invoking server functions that could cause
     // their object to be deleted.
     if (!$Game::Cycling) {
        $Game::Cycling = true;
        $Game::Schedule = schedule(0, 0, "onCycleExec");
     }
  }
  
  function onCycleExec()
  {
     // End the current game and start another one, we'll pause for a little
     // so the end game victory screen can be examined by the clients.
     endGame();
     $Game::Schedule = schedule($Game::EndGamePause * 1000, 0, "onCyclePauseEnd");
  }
  
  function onCyclePauseEnd()
  {
     $Game::Cycling = false;
  
     // Just cycle through the missions for now.
     %search = $Server::MissionFileSpec;
     for (%file = findFirstFile(%search); %file !$= ""; %file = findNextFile(%search)) {
        if (%file $= $Server::MissionFile) {
           // Get the next one, back to the first if there
           // is no next.
           %file = findNextFile(%search);
           if (%file $= "")
             %file = findFirstFile(%search);
           break;
        }
     }
     loadMission(%file);
  }
  
  
  //-----------------------------------------------------------------------------
  // GameConnection Methods
  // These methods are extensions to the GameConnection class. Extending
  // GameConnection make is easier to deal with some of this functionality,
  // but these could also be implemented as stand-alone functions.
  //-----------------------------------------------------------------------------
  
  //-----------------------------------------------------------------------------
  
  function GameConnection::onClientEnterGame(%this)
  {
     commandToClient(%this, 'SyncClock', $Sim::Time - $Game::StartTime);
  
     // Create a new camera object.
     %this.camera = new Camera() {
        dataBlock = Observer;
     };
     MissionCleanup.add( %this.camera );
     %this.camera.scopeToClient(%this);
  
     // Setup game parameters, the onConnect method currently starts
     // everyone with a 0 score.
     %this.score = 0;
  
     // Create a player object.
     %this.spawnPlayer();
  }
  
  function GameConnection::onClientLeaveGame(%this)
  {
     if (isObject(%this.camera))
        %this.camera.delete();
     if (isObject(%this.player))
        %this.player.delete();
  }
  
  
  //-----------------------------------------------------------------------------
  
  function GameConnection::onLeaveMissionArea(%this)
  {
     // The control objects invoked this method when they
     // move out of the mission area.
  }
  
  function GameConnection::onEnterMissionArea(%this)
  {
     // The control objects invoked this method when they
     // move back into the mission area.
  }
  
  
  //-----------------------------------------------------------------------------
  
  function GameConnection::onDeath(%this, %sourceObject, %sourceClient, %damageType, %damLoc)
  {
     // Clear out the name on the corpse
     %this.player.setShapeName("");
  
     // Switch the client over to the death cam and unhook the player object.
     if (isObject(%this.camera) && isObject(%this.player)) {
        %this.camera.setMode("Corpse",%this.player);
        %this.setControlObject(%this.camera);
     }
     %this.player = 0;
  
     // Doll out points and display an appropriate message
     if (%damageType $= "Suicide" || %sourceClient == %this) {
        %this.incScore(-1);
        messageAll('MsgClientKilled','%1 takes his own life!',%this.name);
     }
     else {
        %sourceClient.incScore(1);
        messageAll('MsgClientKilled','%1 gets nailed by %2!',%this.name,%sourceClient.name);
        if (%sourceClient.score >= $Game::EndGameScore)
           cycleGame();
     }
  }
  
  
  //-----------------------------------------------------------------------------
  
  function GameConnection::spawnPlayer(%this)
  {
     // Combination create player and drop him somewhere
  
gt:    %spawnPoint = pickSpawnPoint();