///////////////////////////////////////////////////////////////////////////////
// Doug Macdonald
// http://www.dougwillsave.us
//
// Rev.Eng drain beam: C++ implementation of the Lua function used to invoke the
// energy draining power of the Rev.Eng. This attack fires a continuous
// laser that, when striking an enemy, gives the player character a constant
// supply of whatever type of energy the enemy uses to attack.
//
// In Lua, the function takes two parameters: the Lua object representing Ava
// (the player character), and the rate at which energy is drained from enemies.
//
// Written as part of a senior game project at DigiPen Institute of Technology.
//
// © 2010 DigiPen (USA) Corporation
///////////////////////////////////////////////////////////////////////////////

int LUA_Drain(lua_State *L)
{
  // Only use the drain if Ava does not have an existing power.
  if (FSAva.power == ENERGY_NONE)
  {
    // Cast the player character Lua object to a CLua component.
  	CLua * component = reinterpret_cast<CLua *>(lua_tointeger(L, 1));
  	float drain_rate = lua_tofloat(L, 2);
  
  	// Ensure Ava's camera attribute is accessible by her Lua component; if not, acquire it.
  	if ( !component->m_aCamera ) { component->m_aCamera = static_cast<Graphics::ACamera *> ( component->m_parent->RequestAttribute( "ACamera" ) ); }
  
  	// Ready the camera data for ray casting
  	NxVec3 camera_pos(component->m_aCamera->m_View.Position.x, component->m_aCamera->m_View.Position.y, component->m_aCamera->m_View.Position.z);
  	NxVec3 camera_target = component->m_aCamera->m_View.Target;
  	NxVec3 view = camera_target - camera_pos;
  	view.normalize();
  
  	// Cast a ray from Ava through her targeting reticule
  	NxRay ray(camera_pos, view);
  	NxRaycastHit hit;
  	NxShape* closest_shape = FSPhysX.gScene->raycastClosestShape(ray, NX_ALL_SHAPES, hit, (NxU32)-1, 10000.0f);
  	
  	if (closest_shape)
  	{
  	  // If the ray hit something incredibly far away, ignore it
  	  if (hit.distance > 1000.0f)
    		return 0;
  
  	  // Identify if the ray hit an enemy
  	  NxActor& actor = closest_shape->getActor();
  	  Core::IObject* obj = static_cast<Core::IObject*>(actor.userData);
  	  if (obj != 0)
  	  {
    		Physics::AActions* actions = static_cast<Physics::AActions*>(obj->RequestAttribute("AActions"));
    		GameLogic::AGameData* data = static_cast<GameLogic::AGameData*>(obj->RequestAttribute("AGameData"));
    		if (actions->type == Physics::ENEMY)
    		{
    		  // The drain beam hit an enemy. Add some of its energy to Ava's reserves.
    		  if (data->energy_type != ENERGY_NONE)
      			FSAva.GetEnergy(drain_rate, data->energy_type);
    		}
  	  }
  	}
  }

  return 0;
}
