//-----------------------------------------------------------------------------
// Torque Game Engine
// 
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//  Functions that implement game-play
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------

function createGame()
{
   // Server::GameType is sent to the master server.
   // This variable should uniquely identify your game and/or mod.
   $Server::GameType = "Test App";

   // 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("./camera.cs");
   exec("./markers.cs"); 
   exec("./inventory.cs");
   exec("./triggers.cs");
   exec("./shapeBase.cs");
   exec("./item.cs");
   exec("./health.cs");
   exec("./weapon.cs");
   exec("./radiusDamage.cs");
   exec("./rifle.cs");
   exec("./crossbow.cs");
   //exec("./player.cs");
   exec($playerCSFile);
   exec("./soundTrigger.cs");
   exec("./rewardTrigger.cs");
   exec("./teleportTrigger.cs");
   exec("./multiTeleportTrigger.cs");
   exec("./targetTeleportTrigger.cs");
   exec("./aiPlayer.cs");
	//exec("./playerDataBlocks.cs"); // for player "editor", but crashes racing mod...
   exec("./pemitter.cs");   //df: add for basic particle effects
   exec("./weather.cs");   //df: add for rain/snow effects
   exec("./lightning.cs"); //df: add for random lightning effects
   exec("./Zodiac.cs");   // add for test boat
   exec("./ferrari.cs");
   exec("./buggy.cs");
   exec("./hoverVehicleTest.cs");
   exec("~/ParticleEditor/ParticleEditorStartup.cs");
   exec("./customParticles.cs");
   exec("./CheckPoint.cs");
   exec("./fxShapes.cs");
   //exec("./pathedInteriors.cs");
   exec("./spellExplosion.cs");

   // Conversation Editor
   exec("common/editor/TGEConEdStartup.cs");
   // Keep track of when the game started
   $Game::StartTime = $Sim::Time;
}

function destroyGame()
{
   // This function is called as part of a server shutdown.
}


//-----------------------------------------------------------------------------

function startGame()
{
   // Called once the mission has finished loading
}

function endGame()
{
   // Called as part of mission cleanup
}


//-----------------------------------------------------------------------------
// 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)
{
   echo("ServerType:" SPC $Server::ServerType);
   if(!%this.isAIControlled())
   {
      for(%i = 0; %i < $botCounter; %i++)
      {
         if(isObject($bots[%i])){
            $bots[%i].delete();

         }
      }
      $botCounter = 0;
      echo("BOTCOUNTER:" SPC $botCounter);
   }

   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.
   echo("You better turn around, dude!");
}

function GameConnection::onEnterMissionArea(%this)
{
   // The control objects invoked this method when they
   // move back into the mission area.
   echo("Much better, dude!");
}


//-----------------------------------------------------------------------------

function GameConnection::onDeath(%this, %sourceObject, %sourceClient, %damageType, %damLoc)
{
   if(%this.isAIControlled())
   {
      echo(%this.nameBase SPC "was killed!");
   }
   // 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);
   }
}


//-----------------------------------------------------------------------------

function GameConnection::spawnPlayer(%this)
{
   // Combination create player and drop him somewhere
   %botornot = %this.isAIControlled();
   echo("AI: " @ %botornot);
   %spawnPoint = pickSpawnPoint(%botornot);
   %this.createPlayer(%spawnPoint);
}


//-----------------------------------------------------------------------------

function GameConnection::createPlayer(%this, %spawnPoint)
{
   if (%this.player > 0)  {
      // The client should not have a player currently
      // assigned.  Assigning a new one could result in 
      // a player ghost.
      error( "Attempting to create an angus ghost!" );
   }

   %botornot = %this.isAIControlled();
	if(%botornot)
	{
   		%player = new Player() {
      		dataBlock = $mainPlayerDatablock;
      		client = %this;
   		};
	}
	else
	{
   		%player = new Player() {
      		dataBlock = $mainPlayerDatablock;
      		client = %this;
   		};
	}

   // Create the player object
   //%player = new Player() {
   //   dataBlock = LightMaleHumanArmor;
   //   client = %this;
   //};

   MissionCleanup.add(%player);

   // Player setup...
   %player.setTransform(%spawnPoint);
   %player.setEnergyLevel(60);
   %player.setShapeName(%this.name);

   //Init Inventory to all Inventory-able objects
   %player.addInvItem("Rifle", "0","weapon","This is a glock.",2);
   %player.addInvItem("Crossbow", "0","weapon","This is a strange blue crossbow.",2);
   %player.addInvItem("RifleAmmo", "0","ammo","This is ammo for a rifle.",100);
   %player.addInvItem("CrossbowAmmo", "0","ammo","This is ammo for a crossbow.",50);
   %player.addInvItem("HealthKit", "0","healthKit","This heals you up real nice.",10);
   %player.addInvItem("HealthPatch", "0","healthPatch","This Health Patch heals you up real nice, too, I guess.",10);
   %player.addInvItem("Repair", "0","weapon","This is a Repair.",1);
   %player.addInvItem("RepairAmmo", "0","ammo","This is ammo for a Repair.",100);

   // Update the camera to start with the player
   %this.camera.setTransform(%player.getEyeTransform());

   // Give the client control of the player
   %this.player = %player;
   %this.setControlObject(%player);

   %player.incInvItem(Rifle,1);
   %player.incInvItem(RifleAmmo,RifleAmmo.maxInventory);
   %player.use(Rifle);

	if(!%botornot)
	{
      // add random vehicle for each player
      %rand = getRandom(3);
      switch$(%rand)
      {
         case 0:
            %randBlock = "Buggy";
         case 1:
            %randBlock = "Ferrari";
         case 2:
            %randBlock = "Buggy";
         default:
            %randBlock = "Ferrari";
      }
      %defaultVehicle = new WheeledVehicle() {
         dataBlock = %randBlock;
      };
      %pos = %player.getTransform();
      %x = getWord(%pos, 0);
      %y = getWord(%pos, 1);
      %z = getWord(%pos, 2);
      //%hoverVehicle.setTransform(%x @ " " @ %y @ " " @ %z);
      %defaultVehicle.setTransform(pickSpawnPoint(2));
      //%hoverVehicle.rotation = "1 0 0 0";
      //%hoverVehicle.scale = "1 1 1";
      %defaultVehicle.disableMove = "0";
      %defaultVehicle.mountable = "1";
      MissionCleanup.add(%defaultVehicle);
   }

   //$me = %this;
   //commandToClient(%this, 'StoreClient', %this);
   commandToServer('InitQuickInventory');

   // this does not work yet!
   //%player.setMainSkin("fps/data/shapes/player/player.dts","fps/data/shapes/player/playa1.png");

   // hide the players head :-)
   //%player.hideNode("Bip01 Head");

   // make player transparent ;-))
   //%player.setCloaked(true);
}


//-----------------------------------------------------------------------------
// Support functions
//-----------------------------------------------------------------------------
function getTerrainLevel(%pos,%rad)
{
	while(%retries < 500)
	{
		%x = getWord(%pos, 0) + mFloor(getRandom(%rad * 2) - %rad);
		%y = getWord(%pos, 1) + mFloor(getRandom(%rad * 2) - %rad);
		%z = getWord(%pos, 2) + mFloor(getRandom(%rad * 2) - %rad);

		%start 		= %x @ " " @ %y @ " 5000";
		%end 		= %x @ " " @ %y @ " -1";
		%ground 	= containerRayCast(%start, %end, $TypeMasks::TerrainObjectType, 0);
		%z 		= getWord(%ground, 3);

		error ("Spawn Position   : " @ %x SPC %y);
		error ("Ground Level     : " @ %z);

		%z += 3.5;

		%position = %x @ " " @ %y @ " " @ %z;

		%mask = ($TypeMasks::VehicleObjectType |
			$TypeMasks::MoveableObjectType |
			$TypeMasks::StaticShapeObjectType |
			$TypeMasks::ForceFieldObjectType |
			$TypeMasks::InteriorObjectType |
            $TypeMasks::WaterObjectType |
			$TypeMasks::ItemObjectType);

		if (ContainerBoxEmpty(%mask,%position,3.5))
		{
			error ("Spawn Position Is Good");
			return %position;
		}
		else
			%retries++;
	}
	return "0 0 300 1 0 0 0";
}

function pickSpawnPoint(%val)
{
    if(%val == 1)
    {
        echo("AI is in the house...!");
        %groupName = "MissionGroup/BotDropPoints";
    }
    else if(%val == 0)
    {
        %groupName = "MissionGroup/PlayerDropPoints";
    }
    else if(%val == 2)
    {
        %groupName = "MissionGroup/CarDropPoints";
    }
	%group = nameToID(%groupName);
    // check if BotDropPoints sphere really exists...
    if(%val &! isObject(%group))
    {
        error("Group BotDropPoints doesn't exist!");
        %groupName = "MissionGroup/PlayerDropPoints";
	    %group = nameToID(%groupName);
    }

	if (%group != -1)
	{
		%count = %group.getCount();
		if (%count != 0)
		{
         %index = getRandom(%count-1);
			%spawn = %group.getObject(%index);
			return getTerrainLevel(%spawn.position,%spawn.radius);
		}
		else
			error("No spawn points found in " @ %groupName);
	}
	else
		error("Missing spawn points group " @ %groupName);

	// Could be no spawn points, in which case we'll stick the
	// player at the center of the world.
	return "0 0 300 1 0 0 0";
}

function doSpell(%radius,%client,%type)
{
   %pos = %client.player.getTransform();
   %x = getWord(%pos, 0);
   %y = getWord(%pos, 1);
   %z = getWord(%pos, 2);
   // adjust z value a bit...
   %z += 2.0;
   %finalPos = %x SPC %y SPC %z;

   %eye = %client.player.getEyeVector();
   %vec = vectorScale(%eye, 20);
   %finalPos = vectorAdd(%finalPos, %vec);

   switch$(%type)
   {
      case "1":
         // EXPLOSION
         %p = new explosion() {
            dataBlock = "SpellExplosion";
            position = %finalPos;
         };
         MissionCleanup.add(%p);
         // Radius damage is a support scripts defined in radiusDamage.cs
         radiusDamage(%p,%finalPos,%radius,8.0,"SpellBolt",0);
      case "2":
         // PARTICLES WITH SOUND
         %p = new ParticleEmitterNode() {
            position = %finalPos;
            rotation = "1 0 0 0";
            scale = "1 1 1";
            dataBlock = "defaultParticleEmitterNode";
            emitter = "BlueSpellEmitter";
            velocity = "1";
         };
         serverPlay3D(SpellSound,%client.player);
         radiusDamage(%p,%finalPos,%radius,8.0,"SpellBolt",0);
         %p.schedule(2000,"delete");
      default:
         // EXPLOSION
         %p = new explosion() {
            dataBlock = "SpellExplosion";
            position = %finalPos;
         };
         MissionCleanup.add(%p);
         // Radius damage is a support scripts defined in radiusDamage.cs
         radiusDamage(%p,%finalPos,%radius,8.0,"SpellBolt",0);
      }
}

function blowup(%obj)
{
   %pos = %obj.getposition();
   %dblock = %obj.getdatablock();

   %p = new explosion() {
      dataBlock = "CrossbowExplosion";
      position = %pos;
   };
   MissionCleanup.add(%p);
   // Radius damage is a support scripts defined in radiusDamage.cs
   radiusDamage(%p,%pos,%dblock.damageRadius,%dblock.radiusDamage,"CrossbowBolt",0);
   %obj.delete();
}


