context: //------------------------------------------------------------------------------
  // Revenge Of The Cats: Ethernet
  // Copyright notices are in the file named COPYING.
  //------------------------------------------------------------------------------
  
  function PlayerData::onTrigger(%this, %obj, %triggerNum, %val)
  {
  	// This method is invoked when the player receives a trigger
  	// move event.  The player automatically triggers slot 0 and
  	// slot 1 off of triggers # 0 & 1.  Trigger # 2 is also used
  	// as the jump key.
  	
  	//--------------------------------------------------------------------------
  	// Primary fire
  	//--------------------------------------------------------------------------
  	if( %triggerNum == 0 )
  	{
  
  	}
  
  	//--------------------------------------------------------------------------
  	// Jump
  	//--------------------------------------------------------------------------
  	if( %triggerNum == 2 )
  	{
          if(%val)
          {
              %obj.schedule(0, "checkReJump");
          }
  	}
  	
  	//--------------------------------------------------------------------------
  	// Grenade
  	//--------------------------------------------------------------------------
  	if( %triggerNum == 3 )
  	{
  		%obj.setImageTrigger(2, %val);
  	}
  
  	//--------------------------------------------------------------------------
  	// Marching & Sliding
  	//--------------------------------------------------------------------------
  	if( %triggerNum == 4 || %triggerNum == 5 )
  	{
  		if(%val)
          {
              if(%triggerNum == 4)
      			%obj.nonSnipingBodyPose = $PlayerBodyPose::Marching;
              else if(%triggerNum == 5)
      			%obj.nonSnipingBodyPose = $PlayerBodyPose::Crouched;
          }
  		else
  			%obj.nonSnipingBodyPose = $PlayerBodyPose::Standard;
   
          if(!%obj.isSniping)
              %obj.setBodyPose(%obj.nonSnipingBodyPose);
  	}
  }
  
  //-----------------------------------------------------------------------------
  
  function Player::setSniping(%this, %sniping)
  {
      %this.isSniping = %sniping;
      if(%this.isSniping)
          %this.setBodyPose($PlayerBodyPose::Marching);
      else
          %this.setBodyPose(%this.nonSnipingBodyPose);
  }
  
  //-----------------------------------------------------------------------------
  
  function Player::updateSliding(%this)
  {
      %dtTime = 50;
      
      //%warnLevel = 0.15;
      //%hotLevel = 0.5;
  
      %slidingingDt = -0.01;
      %coolingDt = 0.02;
      %cooldownDelay = 1.0;
  
      if(%this.slidingThread !$= "")
          cancel(%this.slidingThread);
          
      %store   = %this.sliding;
      %storeDt = %this.slidingDt;
  
      if(%this.getBodyPose() == $PlayerBodyPose::Sliding)
      {
          %this.slidingDt = %slidingingDt;
          %this.slidingCooldownTime = %cooldownDelay;
      }
      else
      {
          %this.slidingCooldownTime -= %dtTime / 1000;
          if(%this.slidingCooldownTime >= 0)
              %this.slidingDt = 0;
          else
              %this.slidingDt = %coolingDt;
      }
      
      %this.sliding += %this.slidingDt;
      if(%this.sliding > 1)
      {
          %this.sliding = 1;
          %this.slidingDt = 0;
      }
      else if(%this.sliding <= 0)
      {
          %this.sliding = 0;
          %this.slidingDt = 0;
          %this.setBodyPose($PlayerBodyPose::Normal);
      }
      
      if(%this.client && %this.slidingDt !$= %storeDt)
         	messageClient(%this.client, 'MsgHeat', "", %this.sliding, %this.slidingDt);
  
      %this.slidingThread = %this.schedule(%dtTime, "updateSliding");
  }
  
  //-----------------------------------------------------------------------------
  
  function Player::numAttackingDiscs(%this)
  {
      return %this.attackingDiscs;
  }
  
  function Player::addAttackingDisc(%this, %disc)
  {
      %this.attackingDiscs += 1;
      
      %this.shapeFxSetTexture($PlayerShapeFxSlot::NoDisc, 2);
      %this.shapeFxSetBalloon($PlayerShapeFxSlot::NoDisc, 1.10);
      %this.shapeFxSetActive($PlayerShapeFxSlot::NoDisc, true, true);
  }
  
  function Player::removeAttackingDisc(%this, %disc)
  {
      %this.attackingDiscs -= 1;
      
      if(%this.attackingDiscs == 0)
          %this.shapeFxSetActive($PlayerShapeFxSlot::NoDisc, false, false);
  }
  
  //-----------------------------------------------------------------------------
  
  function Player::inNoDiscGracePeriod(%this)
  {
      return %this.noDiscGracePeriod;
  }
  
  function Player::startNoDiscGracePeriod(%this)
  {
      if(%this.endDiscGracePeriodThread !$= "")
          cancel(%this.endDiscGracePeriodThread);
  
      %gracePeriodTime = 3.0;
  
      %this.noDiscGracePeriod = true;
  
      %this.shapeFxSetTexture($PlayerShapeFxSlot::NoDisc, 2);
      %this.shapeFxSetFade($PlayerShapeFxSlot::NoDisc, 1.0, -1/%gracePeriodTime);
      %this.shapeFxSetActive($PlayerShapeFxSlot::NoDisc, true, true);
  
      %this.endDiscGracePeriodThread =
          %this.schedule(%gracePeriodTime*1000, "endNoDiscGracePeriod");
  }
  
  function Player::endNoDiscGracePeriod(%this)
  {
      %this.noDiscGracePeriod = false;
      %this.shapeFxSetActive($PlayerShapeFxSlot::NoDisc, false, false);
  }
  
  //-----------------------------------------------------------------------------
  
  function Player::checkReJump(%this)
  {
      %this.getDataBlock().checkReJump(%this);
  }
  
  function PlayerData::checkReJump(%this, %obj)
  {
      if(%obj.lastJumpTime != getSimTime() && %obj.getEnergyLevel() > %this.reJumpEnergyDrain)
      {
         	createExplosion(CatJumpExplosion, %obj.getPosition(), "0 0 1");
    		%impulseVec = VectorScale("0 0 1", %this.reJumpForce);
    		%obj.applyImpulse(%pos, %impulseVec);
          %obj.setEnergyLevel( %obj.getEnergyLevel() -  %this.reJumpEnergyDrain);
      }
  }
  
  //-----------------------------------------------------------------------------
  
  function PlayerData::onJump(%this, %obj)
  {
      %obj.lastJumpTime = getSimTime();
  }
  
  //-----------------------------------------------------------------------------
  
  function PlayerData::transformInto(%this,%obj,%into)
  {
  	%client = %obj.client;
  	%success = false;
  
  	//
  	// transform into flyer
  	//
  	if( %into == 1 )
  	{
  		// need some energy in order to transform...
  		if( %obj.getEnergyLevel() < 75 )
  			return false;
  
  		%pos = %obj.getTransform();
  		%vel = %obj.getVelocity();
  		%dmg = %obj.getDamageLevel();
  
  		//%obj.setInvisible(true);
  
  		%data = RedFlyer;
  
  		%newObj = new FlyingVehicle()
  		{
  			datablock = %data;
  			client = %client;
  			teamId = %client.team.teamId;
  		};
  
  		%effect = new FXShape()
  		{
  			datablock = Team1ScoutToFlyerEffect;
  		};
  		%effect.linkToObject(%newObj);
  
  		%newObj.setEnergyLevel($PLAYER_MAX_ENERGY/2);
  		%newObj.setDamageLevel(%dmg);
  		%newObj.setShapeName(%client.name);
  
  //		$aiTarget = %newObj;
  
  		%newObj.setTransform(%pos);
  		%newObj.applyImpulse(%pos, VectorScale(%vel,100));
  
  		MissionCleanup.add(%newObj);
  
  		%obj.setControlObject(%newObj);
  //		%client.player = %newObj;
  
  		// create a cool(tm) effect...
  		%newObj.startFade(100,900,false);
  		%effect.schedule(1000,"delete");
  		%newObj.playAudio(0,TransformSound);
  
  		%success = true;
  	}
  
  	return %success;
  }
  
  //-----------------------------------------------------------------------------
  // Player object methods
  //-----------------------------------------------------------------------------
  
  function Player::hasDisc(%this)
  {
  	return %this.numDiscs > 0;
  }
  
  function Player::setDiscs(%this, %numDiscs)
  {
  	%this.numDiscs = %numDiscs;
  
  	if(isObject(%this.client))
  		messageClient(%this.client, 'MsgNumDiscs', "", %this.numDiscs);
  
  	%hasDisc = %this.hasDisc();
  	%this.setImageLoaded(1, %hasDisc);
  	%this.setImageAmmo(1, %hasDisc);
  }
  
  function Player::incDiscs(%this)
  {
  	%this.numDiscs++;
  	%this.setDiscs(%this.numDiscs);
  }
  
  function Player::decDiscs(%this)
  {
  	%this.numDiscs--;
  	%this.setDiscs(%this.numDiscs);
  }
  
  function Player::hasGrenade(%this)
  {
  	return %this.grenadeAmmo >= 1;
  }
  
  function Player::incGrenadeAmmo(%this, %amount)
  {
      %this.setGrenadeAmmo(%this.grenadeAmmo + %amount);
  }
  
  function Player::decGrenadeAmmo(%this, %amount)
  {
      %this.setGrenadeAmmo(%this.grenadeAmmo - %amount);
  }
  
  function Player::setGrenadeAmmo(%this, %amount)
  {
      %store = %this.grenadeAmmo;
  
      if(%amount < 0)
          %this.grenadeAmmo = 0;
      else if(%amount > 1)
          %this.grenadeAmmo = 1;
      else
          %this.grenadeAmmo = %amount;
  
      if(%this.grenadeAmmo != %store)
      {
          if(isObject(%this.client))
              messageClient(%this.client, 'MsgGrenadeAmmo', "", %this.grenadeAmmo);
      }
  
  	%this.setImageAmmo(2, %this.hasGrenade());
  }
  
  function Player::setGrenadeAmmoDt(%this, %amount)
  {
      %this.grenadeAmmoDt = %amount;
  
      if(isObject(%this.client))
          messageClient(%this.client, 'MsgGrenadeAmmoDt', "", 250, %amount);
  
      %this.updateGrenadeAmmo();
  }
  
  function Player::updateGrenadeAmmo(%this)
  {
  	if(%this.grenadeAmmoThread !$= "")
      {
          cancel(%this.grenadeAmmoThread);
  		%this.grenadeAmmoThread = "";
  	}
   
      %this.grenadeAmmo += %this.grenadeAmmoDt/1000 * 250;
      
      if(%this.grenadeAmmo < 0)
          %this.grenadeAmmo = 0;
      else if(%this.grenadeAmmo > 1)
          %this.grenadeAmmo = 1;
  
  	%this.setImageAmmo(2, %this.hasGrenade());
   
      %this.grenadeAmmoThread = %this.schedule(250, "updateGrenadeAmmo");
  }
  
  function Player::mountVehicle(%this, %vehicle)
  {
  	%vehicleData = %vehicle.getDataBlock();
  
  	// Is the vehicle mountable?
  	if(%vehicleData.mountable == false)
  	{
  		echo("Sorry, the vehicle is not mountable.");
  		return;
  	}
  
  	// Check the speed of the vehicle. If it's moving, we can't mount it.
  	// Note there is a threshold that determines if the vehicle is moving.
  	%vel = %vehicle.getVelocity();
  	%speed = vectorLen(%vel);
  
  	if(%speed <= %vehicleData.maxMountSpeed)
  	{
  		// Find an empty seat
  		%seat = %vehicle.findEmptySeat();
  		if(%seat == -1)
  		{
  			echo("No free seat available");
  			return;
  		}
  
  		%this.mVehicle = %col;
  		%this.mSeat = %seat;
  		%this.isMounted = true;
  
  		echo("Mounting vehicle in seat " @ %seat);
  
  		// Now mount the vehicle.
  		%vehicle.mountObject(%this, %seat);
  		%this.setTransform(%vehicle.getSlotTransform(%seat));
  	}
  	else
  	{
  		echo("You cannot mount a moving vehicle.");
  	}
  }
  
  function Player::dismountVehicle(%this)
  {
  	if(!%this.isMounted())
  		return;
  
  	%vehicle = %this.getObjectMount();
  
  	%speed = vectorLen(%vehicle.getVelocity());
  	if(%speed > %vehicle.getDataBlock().maxDismountSpeed)
  		return;
  
  	// Find the position above dismount point.
  	%pos	 = getWords(%this.getTransform(), 0, 2);
  	%oldPos = %pos;
  	%vec[0] = " 2  0  0";
  	%vec[1] = " 0  -2  0";
  	%vec[2] = " 0  2  0";
  	%vec[3] = "-2  0  0";
  	%vec[4] = " 4  0  0";
  	%impulseVec  = "0 0 0";
  	%vec[0] = MatrixMulVector( %this.getTransform(), %vec[0]);
  
  	// Make sure the point is valid
  	%pos = "0 0 0";
  	%numAttempts = 5;
  	%success	  = -1;
  	for (%i = 0; %i < %numAttempts; %i++) {
  		%pos = VectorAdd(%oldPos, VectorScale(%vec[%i], 3));
  		if(%this.checkDismountPoint(%oldPos, %pos)) {
  			%success = %i;
  			%impulseVec = %vec[%i];
  			break;
  		}
  	}
  
  	if(%forced && %success == -1)
  		%pos = %oldPos;
  
  	%this.unmount();
  	%this.mountVehicle = false;
  
  	// Schedule the function to set the mount flag, so that the player
  	// can mount another vehicle in the future.
  	%this.schedule(4000, "MountVehicles", true);
  
  	// Position above dismount point
  	%this.setTransform(%pos);
  	%this.applyImpulse(%pos, VectorScale(%impulseVec, %this.getDataBlock().mass));
  
  	%this.setActionThread("run",true,true);
  	%this.setArmThread("look");
  
  	%this.client.setControlObject(%this);
  
  	// Command the client to display the correct movement map and
  	// activate the command menu.
  //	CommandToClient(%obj.client, 'PopActionMap', $Vehicle::moveMaps[%obj.mSeat]);
  //	CommandToClient(%obj.client, 'PushActionMap', moveMap);
  //	CommandToClient(%obj.client,'activateCommandMenu');
  }
  
  function Player::kill(%this, %damageType)
  {
  	%this.damage(0, %this.getPosition(), 10000, %damageType);
  }
  
  //----------------------------------------------------------------------------
  
  function Player::isPilot(%this)
  {
  	%vehicle = %this.getObjectMount();
  	// There are two "if" statements to avoid a script warning.
  	if (%vehicle)
  		if (%vehicle.getMountNodeObject(0) == %this)
  			return true;
  	return false;
  }
  
  //----------------------------------------------------------------------------
  
  function Player::playDeathCry( %this )
  {
  	%client = %this.client;
  	//playTargetAudio( %client.target, "replaceme", AudioClosest3d, false );
  }
  
  function Player::playPain( %this )
  {
  	%client = %this.client;
  	//playTargetAudio( %client.target, "replaceme", AudioClosest3d, false);
  }
  
  
  
  
  //----------------------------------------------------------------------------
  
  function Player::kill(%this, %damageType)
  {
  	%this.damage(0, %this.getPosition(), 10000, %damageType);
  }
  
  
  //----------------------------------------------------------------------------
  
  function Player::mountVehicles(%this,%bool)
  {
  	// If set to false, this variable disables vehicle mounting.
  	%this.mountVehicle = %bool;
  }
  
  function Player::isPilot(%this)
  {
  
gt: 	%vehicle = %this.getObjectMount();