var speed = 8.0;
var runSpeed = 16.0;
var gravity = 10.0; 
var maxVelocityChange = 10.0; 
var inAirControl = 0.1; 
var canJump = true; 
var jumpHeight = 2.0;
var canMove = true;
var canClimb = true;
var isClimbing = false;
private var grounded = true;
private var groundVelocity : Vector3; 
private var capsule : CapsuleCollider; 
  
@script RequireComponent(Rigidbody, CapsuleCollider) 
  
function Awake () 
{ 
   rigidbody.freezeRotation = true; 
   rigidbody.useGravity = false; 
   capsule = GetComponent(CapsuleCollider); 
} 

function Update() {
	if(Input.GetButtonDown("Jump")){
		isClimbing = false;
		targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); 
    	targetVelocity = transform.TransformDirection(targetVelocity) * inAirControl;
    	rigidbody.AddForce(targetVelocity, ForceMode.VelocityChange);
	}
}

function FixedUpdate () 
{
	GetComponent("MouseLook").active = canMove;
	if(canMove && !isClimbing){
	if (grounded){ 
    	  // Calculate how fast we should be moving
			var targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); 
			targetVelocity = transform.TransformDirection(targetVelocity); 
			targetVelocity *= Input.GetButton("Run") ?  runSpeed : speed; 

      		// Apply a force that attempts to reach our target velocity 
     	 	var velocity = rigidbody.velocity; 
     	 	var velocityChange = (targetVelocity - velocity) + groundVelocity; 
     	 	velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange); 
     	 	velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange); 
     	 	velocityChange.y = 0; 
     	 	rigidbody.AddForce(velocityChange, ForceMode.VelocityChange); 
    	 	// Jump 
    	 	 if (canJump && Input.GetButton("Jump")) 
    	 	 { 
    	 	    rigidbody.velocity = Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
    	 	    grounded = false;
    	 	 }
	} else { 
	    	// Add in air
    	targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); 
    	targetVelocity = transform.TransformDirection(targetVelocity) * inAirControl;
    	rigidbody.AddForce(targetVelocity, ForceMode.VelocityChange);
   	}	 
    	
   // We apply gravity manually for more tuning control
	  	rigidbody.AddForce(Vector3 (0, -gravity * rigidbody.mass * 2, 0));
	} else {
		if(Input.GetButton("Jump")){
			rigidbody.velocity = (transform.forward * speed);
		}
	}
} 

function TrackGrounded (col : Collision) 
{ 
   var minimumHeight = capsule.bounds.min.y + capsule.radius; 
   for (var c : ContactPoint in col.contacts) 
   { 
      if (c.point.y < minimumHeight) 
      { 
         if (col.rigidbody) 
            groundVelocity = col.rigidbody.velocity; 
         else 
            groundVelocity = Vector3.zero; 
         grounded = true; 
      } 
   }    
} 

function OnCollisionStay (col : Collision) 
{ 
   TrackGrounded (col); 
} 

function OnCollisionEnter (col : Collision) 
{ 
   TrackGrounded (col);
   
   if(col.gameObject.CompareTag("Rope")){
   		isClimbing = true;
   }
}

function OnTriggerEnter(col : Collider){
	if(col.gameObject.CompareTag("Rope")){
   		isClimbing = true;
   		rigidbody.velocity = Vector3.zero;
   	}
} 

  
function CalculateJumpVerticalSpeed () 
{ 
   // From the jump height and gravity we deduce the upwards speed 
   // for the character to reach at the apex. 
   return Mathf.Sqrt(2 * jumpHeight * gravity); 
}

function Grounded() {
	return grounded;
}