/*************************************************************************
  Crytek Source File.
  Copyright (C), Crytek Studios, 2001-2004.
 -------------------------------------------------------------------------
  $Id$
  $DateTime$
  
 -------------------------------------------------------------------------
  History:
  - 7:10:2004   14:19 : Created by Márcio Martins

*************************************************************************/
#include "StdAfx.h"
#include "ScriptBind_Actor.h"
#include "Actor.h"
#include "IMovementController.h"
#include "Item.h"
#include "HUD/HUD.h"

#include <IGameFramework.h>
#include <IVehicleSystem.h>
#include <IGameObject.h>
#include <Cry_Geo.h>
#include <Cry_GeoDistance.h>
#include <IEntitySystem.h>

//------------------------------------------------------------------------
CScriptBind_Actor::CScriptBind_Actor(ISystem *pSystem)
: m_pSystem(pSystem),
	m_pGameFW(pSystem->GetIGame()->GetIGameFramework())
{
	Init(pSystem->GetIScriptSystem(), pSystem, 1);

	//////////////////////////////////////////////////////////////////////////
	// Init tables.
	//////////////////////////////////////////////////////////////////////////
	m_pStats.Create(m_pSS);
	m_pParams.Create(m_pSS);

#undef SCRIPT_REG_CLASSNAME
#define SCRIPT_REG_CLASSNAME &CScriptBind_Actor::

	SCRIPT_REG_FUNC(SetViewAngleOffset);
	SCRIPT_REG_FUNC(GetViewAngleOffset);
	SCRIPT_REG_FUNC(Revive);
	SCRIPT_REG_FUNC(RagDollize);
	SCRIPT_REG_FUNC(SetStats);
	SCRIPT_REG_FUNC(GetStats);
	SCRIPT_REG_FUNC(SetParams);
	SCRIPT_REG_FUNC(GetParams);
	SCRIPT_REG_FUNC(GetHeadPos);
	SCRIPT_REG_FUNC(GetHeadDir);
	SCRIPT_REG_FUNC(PostPhysicalize);
	SCRIPT_REG_TEMPLFUNC(Freeze, "frozen, mass, material");
	SCRIPT_REG_FUNC(GetChannel);
	SCRIPT_REG_FUNC(IsPlayer);
	SCRIPT_REG_FUNC(LinkToVehicle);
	SCRIPT_REG_FUNC(LinkToVehicleRemotely);
  SCRIPT_REG_FUNC(IsGhostPit);
	SCRIPT_REG_TEMPLFUNC(SetAngles,"vAngles");
	SCRIPT_REG_FUNC(GetAngles);
	SCRIPT_REG_TEMPLFUNC(AddAngularImpulse,"vAngular,deceleration,duration");
	SCRIPT_REG_TEMPLFUNC(SetViewLimits,"dir,rangeH,rangeV");
	SCRIPT_REG_TEMPLFUNC(PlayAction,"action,extension");
	SCRIPT_REG_TEMPLFUNC(SimulateOnAction,"action,mode,value");
	SCRIPT_REG_TEMPLFUNC(SetMovementTarget,"pos,target,up,speed");
	SCRIPT_REG_TEMPLFUNC(CameraShake,"amount,duration,frequency,pos");
	SCRIPT_REG_FUNC(VectorToLocal);
	SCRIPT_REG_TEMPLFUNC(EnableAspect, "aspects, enable");
	SCRIPT_REG_TEMPLFUNC(SetExtensionActivation,"extension,bActivate");
	SCRIPT_REG_TEMPLFUNC(SetExtensionParams,"extension,params");
	SCRIPT_REG_TEMPLFUNC(GetExtensionParams,"extension,params");
	SCRIPT_REG_TEMPLFUNC(SetHealth,"health");
	SCRIPT_REG_TEMPLFUNC(SetMaxHealth,"health");
	SCRIPT_REG_FUNC(GetHealth);
	SCRIPT_REG_FUNC(GetMaxHealth);
  SCRIPT_REG_FUNC(GetFrozenAmount);

	SCRIPT_REG_TEMPLFUNC(SetPhysicalizationProfile, "profile");

  SCRIPT_REG_TEMPLFUNC(AttachVulnerabilityEffect, "characterSlot, partid, hitPos, effect");
  SCRIPT_REG_TEMPLFUNC(ResetVulnerabilityEffects, "characterSlot");
  SCRIPT_REG_TEMPLFUNC(GetCloseColliderParts, "characterSlot, hitPos, radius");
	SCRIPT_REG_TEMPLFUNC(QueueAnimationState,"animationState");
	SCRIPT_REG_TEMPLFUNC(ChangeAnimGraph,"graph");
	SCRIPT_REG_TEMPLFUNC(CreateCodeEvent,"params");
	SCRIPT_REG_FUNC(GetCurrentAnimationState);
	SCRIPT_REG_TEMPLFUNC(SetAnimationInput,"name,value");

	//------------------------------------------------------------------------
	// NETWORK
	//------------------------------------------------------------------------
	SCRIPT_REG_TEMPLFUNC(HolsterItem, "holster");
	SCRIPT_REG_TEMPLFUNC(DropItem, "itemId");
	SCRIPT_REG_TEMPLFUNC(PickUpItem, "itemId");

	SCRIPT_REG_TEMPLFUNC(SelectItemByName, "");
	SCRIPT_REG_TEMPLFUNC(SelectItem, "");
	SCRIPT_REG_TEMPLFUNC(SelectLastItem, "");

  	
	//------------------------------------------------------------------------
	
	SCRIPT_REG_TEMPLFUNC(CreateIKLimb,"slot,limbName,rootBone,midBone,endBone,flags");

	SCRIPT_REG_TEMPLFUNC(RenderScore, "");
			
	m_pSS->SetGlobalValue("STANCE_PRONE", STANCE_PRONE);
	m_pSS->SetGlobalValue("STANCE_CROUCH", STANCE_CROUCH);
	m_pSS->SetGlobalValue("STANCE_STAND", STANCE_STAND);
	m_pSS->SetGlobalValue("STANCE_RELAXED", STANCE_RELAXED);
	m_pSS->SetGlobalValue("STANCE_STEALTH", STANCE_STEALTH);

	m_pSS->SetGlobalValue("ZEROG_AREA_ID", ZEROG_AREA_ID);
}

//------------------------------------------------------------------------
CScriptBind_Actor::~CScriptBind_Actor()
{
}

//------------------------------------------------------------------------
void CScriptBind_Actor::AttachTo(CActor *pActor)
{
	IScriptTable *pScriptTable = pActor->GetEntity()->GetScriptTable();

	if (pScriptTable)
	{
		SmartScriptTable thisTable(m_pSS);

		thisTable->SetValue("__this", ScriptHandle(pActor->GetEntityId()));
		thisTable->Delegate(GetMethodsTable());

		pScriptTable->SetValue("actor", thisTable);
	}
}

//------------------------------------------------------------------------
CActor *CScriptBind_Actor::GetActor(IFunctionHandler *pH)
{
	void *pThis = pH->GetThis();

	if (pThis)
	{
		IActor *pActor = m_pGameFW->GetIActorSystem()->GetActor((EntityId)(UINT_PTR)pThis);
		if (pActor)
			return static_cast<CActor *>(pActor);
	}

	return 0;
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SetViewAngleOffset(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	Vec3 offset(0,0,0);
	pH->GetParam(1, offset);

	pActor->SetViewAngleOffset(offset);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetViewAngleOffset(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	return pH->EndFunction(pActor->GetViewAngleOffset());
}

//------------------------------------------------------------------------
int CScriptBind_Actor::Revive(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->Revive();

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::RagDollize(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->GetGameObject()->SetPhysicalizationProfile( eAP_Ragdoll );
	//pActor->RagDollize();

	return pH->EndFunction();
}

//------------------------------------------------------------------------
//set some status of the actor
int CScriptBind_Actor::SetStats(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
	{
		SmartScriptTable params;

		if (pH->GetParamType(1) != svtNull && pH->GetParam(1, params))
			pActor->SetStats(params);
	}
	
	return pH->EndFunction();
}

//------------------------------------------------------------------------
//get some infos from the actor
int CScriptBind_Actor::GetStats(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor && pActor->GetStats(m_pStats))
	{
		return pH->EndFunction(m_pStats);
	}
	else
	{
		return pH->EndFunction();
	}
}

//------------------------------------------------------------------------
//set the actor params, pass the params table to the actor
int CScriptBind_Actor::SetParams(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
	{
		SmartScriptTable params;

		if (pH->GetParamType(1) != svtNull && pH->GetParam(1, params))
			pActor->SetParams(params);
	}
	
	return pH->EndFunction();
}

//------------------------------------------------------------------------
//get some infos from the actor
int CScriptBind_Actor::GetParams(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor && pActor->GetParams(m_pParams))
	{
		return pH->EndFunction(m_pParams);
	}
	else
	{
		return pH->EndFunction();
	}
}

// has to be changed! (maybe bone position)
//------------------------------------------------------------------------
int CScriptBind_Actor::GetHeadDir(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	Vec3 headDir = FORWARD_DIRECTION;

	if (IMovementController * pMC = pActor->GetMovementController())
	{
		SMovementState ms;
		pMC->GetMovementState( ms );
		headDir = ms.eyeDirection;
	}

	return pH->EndFunction(Script::SetCachedVector( headDir, pH, 1 ));
}

// has to be changed! (maybe bone position)
//------------------------------------------------------------------------
int CScriptBind_Actor::GetHeadPos(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();
	
	//FIXME:dir is not used
	//	Vec3 dir(0,0,0);
	//	Vec3 pos(0,0,0);
	//	pActor->GetActorInfo(pos,dir);

	Vec3 headPos(0,0,0);

	if (IMovementController * pMC = pActor->GetMovementController())
	{
		SMovementState ms;
		pMC->GetMovementState( ms );
		headPos = ms.eyePosition;
	}

	return pH->EndFunction(Script::SetCachedVector( headPos, pH, 1 ));	
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetChannel(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	return pH->EndFunction( (int)pActor->GetChannelId() );
}

//------------------------------------------------------------------------
int CScriptBind_Actor::IsPlayer(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor && pActor->IsPlayer())
		return pH->EndFunction(1);
	else
		return pH->EndFunction();
} 

//------------------------------------------------------------------------
int CScriptBind_Actor::PostPhysicalize(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->PostPhysicalize();

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::Freeze(IFunctionHandler *pH, bool frozen, float mass, const char *material)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->Freeze(frozen, mass, material);

	return pH->EndFunction();
}


//------------------------------------------------------------------------
int CScriptBind_Actor::LinkToVehicle(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
	{
		IVehicle *pVehicle(NULL);
		ScriptHandle vehicleId;

		vehicleId.n = 0;
		if (pH->GetParamType(1) != svtNull)
			pH->GetParam(1, vehicleId);
	
		pActor->LinkToVehicle(vehicleId.n);
	}

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::LinkToVehicleRemotely(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
	{
		IVehicle *pVehicle(NULL);
		ScriptHandle vehicleId;

		vehicleId.n = 0;
		if (pH->GetParamType(1) != svtNull)
			pH->GetParam(1, vehicleId);

		pActor->LinkToVehicleRemotely(vehicleId.n);
	}

	return pH->EndFunction();
}

//------------------------------------------------------------------------
//TOFIX:rendundant with CScriptBind_Entity::SetAngles
int CScriptBind_Actor::SetAngles(IFunctionHandler *pH,Ang3 vAngles)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->SetAngles(vAngles);

	return pH->EndFunction();
}

int CScriptBind_Actor::GetAngles(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	Ang3 angles(0,0,0);

	if (pActor)
		angles = pActor->GetAngles();

	return pH->EndFunction( Script::SetCachedVector( (Vec3)angles, pH, 1 ) );
}

int CScriptBind_Actor::AddAngularImpulse(IFunctionHandler *pH,Ang3 vAngular,float deceleration,float duration)
{
	CActor *pActor = GetActor(pH);
	if (pActor)
		pActor->AddAngularImpulse(vAngular,deceleration,duration);

	return pH->EndFunction();
}

int CScriptBind_Actor::SetViewLimits(IFunctionHandler *pH,Vec3 dir,float rangeH,float rangeV)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->SetViewLimits(dir,rangeH,rangeV);

	return pH->EndFunction();
}

int CScriptBind_Actor::PlayAction(IFunctionHandler *pH,const char *action,const char *extension)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->PlayAction(action,extension);

	return pH->EndFunction();
}

int CScriptBind_Actor::SimulateOnAction(IFunctionHandler *pH,const char *action,int mode,float value)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->OnAction(action,mode,value);
		
	return pH->EndFunction();
}

int CScriptBind_Actor::SetMovementTarget(IFunctionHandler *pH, Vec3 pos, Vec3 target, Vec3 up, float speed )
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->SetMovementTarget(pos,target,up,speed);
		
	return pH->EndFunction();
}

int CScriptBind_Actor::CameraShake(IFunctionHandler *pH,float amount,float duration,float frequency,Vec3 pos)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->CameraShake(amount,0,duration,frequency,pos,0);
		
	return pH->EndFunction();
}

int CScriptBind_Actor::VectorToLocal(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	Vec3 vector;
	if (!pH->GetParam(1, vector))
		return pH->EndFunction();

	if (pActor)
		pActor->VectorToLocal(vector);
	else
		vector.Set(0,0,0);
		
	return pH->EndFunction(Script::SetCachedVector( vector, pH, 2 ));
}

//------------------------------------------------------------------------
int CScriptBind_Actor::EnableAspect(IFunctionHandler *pH, const char *aspect, bool enable)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	uint8 aspectbit = 0;

	if (!stricmp(aspect, "physics"))
		aspectbit |= eEA_Physics;
	else if (!stricmp(aspect, "gameobject"))
		aspectbit |= eEA_GameClientDynamic | eEA_GameServerDynamic | eEA_GameClientStatic | eEA_GameServerStatic;
	else if (!stricmp(aspect, "script"))
		aspectbit |= eEA_Script;
	else if (!stricmp(aspect, "volatile"))
		aspectbit |= eEA_Volatile;

	if (pActor)
		pActor->GetGameObject()->EnableAspect(aspectbit, enable);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SetExtensionActivation(IFunctionHandler *pH, const char *extension, bool activation)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();
	bool ok = false;
	if (pActor)
	{
		if (activation)
			ok = pActor->GetGameObject()->ActivateExtension(extension);
		else
		{
			pActor->GetGameObject()->DeactivateExtension(extension);
			ok = true;
		}
	}
	if (!ok)
		pH->GetIScriptSystem()->RaiseError("Failed to %s extension %s", activation? "enable" : "disable", extension);
	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SetExtensionParams(IFunctionHandler* pH, const char *extension, SmartScriptTable params)
{
	CActor * pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();
	bool ok = false;
	if (pActor)
		ok = pActor->GetGameObject()->SetExtensionParams(extension, params);
	if (!ok)
		pH->GetIScriptSystem()->RaiseError("Failed to set params for extension %s", extension);
	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetExtensionParams(IFunctionHandler* pH, const char *extension, SmartScriptTable params)
{
	CActor * pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();
	bool ok = false;
	if (pActor)
		ok = pActor->GetGameObject()->GetExtensionParams(extension, params);
	if (!ok)
		pH->GetIScriptSystem()->RaiseError("Failed to set params for extension %s", extension);
	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SetHealth(IFunctionHandler *pH, float health)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->SetHealth((int)health);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SetMaxHealth(IFunctionHandler *pH, float health)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->SetMaxHealth((int)health);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetHealth(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		return pH->EndFunction(pActor->GetHealth());

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetMaxHealth(IFunctionHandler *pH)
{
  CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

  if (pActor)
    return pH->EndFunction(pActor->GetMaxHealth());

  return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::QueueAnimationState(IFunctionHandler *pH, const char *animationState)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->QueueAnimationState(animationState);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::ChangeAnimGraph(IFunctionHandler *pH, const char *graph)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->ChangeAnimGraph(graph);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::CreateCodeEvent(IFunctionHandler *pH,SmartScriptTable params)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->CreateCodeEvent(params);
			
	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetCurrentAnimationState(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	const char * value = "<no state>";
	if (IAnimationGraphState * pState = pActor->GetAnimationGraphState())
		value = pState->GetCurrentStateName();

	return pH->EndFunction(value);
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SetAnimationInput( IFunctionHandler *pH, const char * inputID, const char * value )
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (IAnimationGraphState * pState = pActor->GetAnimationGraphState())
		pState->SetInput( pState->GetInputId(inputID), value );

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SetPhysicalizationProfile(IFunctionHandler *pH, const char *profile)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();
	
	uint p = 0;
	if (!stricmp(profile, "alive"))
		p = eAP_Alive;
	else if (!stricmp(profile, "ragdoll"))
		p = eAP_Ragdoll;
	else
		return pH->EndFunction();

	pActor->GetGameObject()->SetPhysicalizationProfile(p);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::AttachVulnerabilityEffect(IFunctionHandler *pH, int characterSlot, int partid, Vec3 hitPos, const char* effect)
{
  CActor *pActor = GetActor(pH);  
	if (!pActor)
		return pH->EndFunction();

  IEntity* pEntity = pActor->GetEntity();

  ICharacterInstance* pChar = pEntity->GetCharacter(characterSlot);

  if (!pChar || !effect)  
    return pH->EndFunction();

  //fallback: use nearest attachment
  float minDiff = 10000.f;  
  IAttachment* pClosestAtt = 0;
  
  IAttachmentManager* pMan = pChar->GetIAttachmentManager();
  for (int i=0; i<pMan->GetAttachmentCount(); ++i)
  {
    IAttachment* pAtt = pMan->GetInterfaceByIndex(i);
    string attName(pAtt->GetName());

    // name identified by "vulnerable"
    if (attName.find("vulnerable") == -1)
      continue;
    
    float diff = (hitPos - pAtt->GetWMatrix().GetTranslation()).len2();    
    
    if (diff < minDiff)
    {
      minDiff = diff; 
      pClosestAtt = pAtt;      
    }   
    //CryLog("diff: %.2f, att: %s", diff, attName.c_str());
  }

  if (!pClosestAtt)
    return pH->EndFunction();
  
  CEffectAttachment *pEffectAttachment = new CEffectAttachment(effect, Vec3(ZERO), Vec3(0,1,0), 1.f);

  pClosestAtt->AddBinding(pEffectAttachment);
  pClosestAtt->HideAttachment(0);
  
  return pH->EndFunction(pClosestAtt->GetName());    
}

//------------------------------------------------------------------------
int CScriptBind_Actor::ResetVulnerabilityEffects(IFunctionHandler *pH, int characterSlot)
{
  CActor *pActor = GetActor(pH);  
	if (!pActor)
		return pH->EndFunction();

  IEntity* pEntity = pActor->GetEntity();

  ICharacterInstance* pChar = pEntity->GetCharacter(characterSlot);

  if (pChar)  
  {
    IAttachmentManager* pMan = pChar->GetIAttachmentManager();
    for (int i=0; i<pMan->GetAttachmentCount(); ++i)
    {
      IAttachment* pAtt = pMan->GetInterfaceByIndex(i);
      if (strstr(pAtt->GetName(), "vulnerable"))
        pAtt->ClearBinding();
    }
  }
  return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetCloseColliderParts(IFunctionHandler *pH, int characterSlot, Vec3 hitPos, float radius)
{
  // find nearest physic. parts to explosion center
  // for now we just return the closest part (using the AABB)  
  
  CActor *pActor = GetActor(pH);  
	if (!pActor)
		return pH->EndFunction();

  IEntity* pEntity = pActor->GetEntity();

  ICharacterInstance* pChar = pEntity->GetCharacter(characterSlot);

  if (pChar && pChar->GetCharacterPhysics())  
  { 
    IPhysicalEntity* pPhysics = pChar->GetCharacterPhysics();
    
    pe_status_nparts nparts;
    int numParts = pPhysics->GetStatus(&nparts);    

    float minLenSq = radius*radius + 0.1f;
    int minLenPart = -1;
    
    pe_status_pos status;

    for (int i=0; i<numParts; ++i)
    {
      status.ipart = i;
      if (pPhysics->GetStatus(&status))
      { 
        AABB box(status.pos+status.BBox[0], status.pos+status.BBox[1]);
             
        // if hitpos inside AABB, return
        if (box.IsContainPoint(hitPos))
        {
          minLenPart = i;          
          break;
        }

        // else find closest distance 
        float lenSq = Distance::Point_AABBSq(hitPos, box);
        if (lenSq < minLenSq)
        {
          minLenSq = lenSq;
          minLenPart = i;          
        }
      }      
    }

    // get material from selected part
    static ISurfaceTypeManager* pSurfaceMan = GetISystem()->GetI3DEngine()->GetMaterialManager()->GetSurfaceTypeManager();

    if (minLenPart != -1)
    {
      const char* mat = "";

      pe_params_part params;
      params.ipart = minLenPart;
      if (pPhysics->GetParams(&params))
      { 
        phys_geometry* pGeom = params.pPhysGeomProxy ? params.pPhysGeomProxy : params.pPhysGeom;
        if (pGeom->surface_idx > 0 &&  pGeom->surface_idx < params.nMats)
           mat = pSurfaceMan->GetSurfaceType(pGeom->pMatMapping[pGeom->surface_idx])->GetName();        
      }

      if (strstr(mat, "mat_") == mat)
        mat = mat + 4;

      // return partid, matName
      return pH->EndFunction(params.partid, mat);
    }    
  }
  return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::CreateIKLimb( IFunctionHandler *pH, int slot, const char *limbName, const char *rootBone, const char *midBone, const char *endBone, int flags)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	if (pActor)
		pActor->CreateIKLimb(slot,limbName,rootBone,midBone,endBone,flags);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::RenderScore(IFunctionHandler *pH, const char* player, int kills, int deaths)
{
	CActor *pActor = (CActor*)(GetISystem()->GetIGame()->GetIGameFramework()->GetClientActor());
	if(!pActor)
		return pH->EndFunction();

	CHUD* pHud = (CHUD*)(pActor->GetGameObject()->QueryExtension("HUD"));
	if(!pHud)
		return pH->EndFunction();

	pHud->AddToScoreBoard(player, kills, deaths);

	return pH->EndFunction();
}


//------------------------------------------------------------------------
int CScriptBind_Actor::HolsterItem(IFunctionHandler *pH, bool holster)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->HolsterItem(holster);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::DropItem(IFunctionHandler *pH, ScriptHandle itemId)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->DropItem((EntityId)itemId.n);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::PickUpItem(IFunctionHandler *pH, ScriptHandle itemId)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->PickUpItem((EntityId)itemId.n, true);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SelectLastItem(IFunctionHandler *pH)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->SelectLastItem(true);

	return pH->EndFunction();
}


//------------------------------------------------------------------------
int CScriptBind_Actor::SelectItemByName(IFunctionHandler *pH, const char *name)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->SelectItemByName(name, true);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::SelectItem(IFunctionHandler *pH, ScriptHandle itemId)
{
	CActor *pActor = GetActor(pH);
	if (!pActor)
		return pH->EndFunction();

	pActor->SelectItem(itemId.n, true);

	return pH->EndFunction();
}

//------------------------------------------------------------------------
int CScriptBind_Actor::GetFrozenAmount(IFunctionHandler *pH)
{
  CActor *pActor = GetActor(pH);
  if (!pActor)
    return pH->EndFunction();

  return pH->EndFunction(pActor->GetFrozenAmount());   
}

//------------------------------------------------------------------------
int CScriptBind_Actor::IsGhostPit(IFunctionHandler *pH)
{
  CActor *pActor = GetActor(pH);
  if (!pActor)
    return pH->EndFunction();
	 
  if (IVehicle* pVehicle = pActor->GetLinkedVehicle())
  {
    IVehicleSeat* pSeat = pVehicle->GetSeat(pActor->GetEntityId());

    if (pSeat && pSeat->GetCurrentView())
    { 
      bool hidden = pSeat->GetCurrentView()->IsPassengerHidden();
      return pH->EndFunction(hidden);    
    }
  }

  return pH->EndFunction();   
}
