bool CControlledLocator::GetProbableHit(EntityId weaponId, const IFireMode* pFireMode, Vec3& hit)
{
  bool ret = false;
  IEntity *entity = gEnv->pEntitySystem->GetEntity(weaponId);

  if (entity)
  {
    const Vec3 &dir = entity->GetForwardDir();
    hit = entity->GetWorldTM().GetTranslation() + dir * WEAPON_CONTROLLED_HIT_RANGE;
    ret = true;
  }

  return ret;
}
//--------------------------------------------------------------------------------------------------
// Name: DebugOnInputEvent
// Desc: Called when input events happen in debug builds
//--------------------------------------------------------------------------------------------------
void CExplosionGameEffect::DebugOnInputEvent(int keyId)
{
	// Initialise static version of effect
	static CExplosionGameEffect explosionGameEffect;
	if(!explosionGameEffect.IsFlagSet(GAME_EFFECT_INITIALISED))
	{
		explosionGameEffect.Initialise();
		explosionGameEffect.SetFlag(GAME_EFFECT_DEBUG_EFFECT,true);
		explosionGameEffect.SetFlag(GAME_EFFECT_AUTO_RELEASE,true);
		explosionGameEffect.SetActive(true);
	}

	// Get player pos
	Vec3 playerDir(0.0f,0.0f,0.0f);
	Vec3 playerPos(0.0f,0.0f,0.0f);
	EntityId localClientId = gEnv->pGame->GetIGameFramework()->GetClientActorId();
	if(localClientId != 0)
	{
		IEntity* playerEntity = g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(localClientId)->GetEntity();
		playerDir = playerEntity->GetForwardDir();
		playerPos = playerEntity->GetPos();
	}

	// Distance from player controlled by keyboard
	static float distFromPlayer = 0.0f;
	static float distStep = 1.0f;

	switch(keyId)
	{
		case eKI_NP_Multiply:
		{
			distFromPlayer += distStep;
			break;
		}
		case eKI_NP_Divide:
		{
			distFromPlayer -= distStep;
			break;
		}
		case eKI_NP_0:
		{
			distFromPlayer = 0.0f;
			break;
		}
		case eKI_NP_1:
		{
			// Frag
			SExplosionContainer explosionContainer;
			ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo;
			explosionInfo.pParticleEffect = gEnv->pParticleManager->FindEffect("Crysis2_weapon_explosives.frag.concrete");
			explosionInfo.pos = playerPos + (playerDir * distFromPlayer);
			explosionInfo.dir.Set(0.0f,-1.0f,0.0f);
			explosionInfo.effect_scale = 1.0f;
			explosionInfo.pressure = 1000.0f;
			explosionInfo.maxblurdistance = 10.0;
			explosionInfo.radius = 15.0;
			explosionInfo.blindAmount = 0.0f;
			explosionInfo.flashbangScale = 8.0f;
			explosionInfo.damage = 5.0f;
			explosionInfo.hole_size = 0.0f;
			explosionGameEffect.Explode(explosionContainer);
			break;
		}
		case eKI_NP_2:
		{
			// Flashbang
			SExplosionContainer explosionContainer;
			ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo;
			explosionInfo.pParticleEffect = gEnv->pParticleManager->FindEffect("Crysis2_weapon_explosives.grenades.flash_explosion");
			explosionInfo.pos = playerPos + (playerDir * distFromPlayer);
			explosionInfo.dir.Set(0.0f,-1.0f,0.0f);
			explosionInfo.effect_scale = 1.0f;
			explosionInfo.pressure = 1000.0f;
			explosionInfo.maxblurdistance = 10.0;
			explosionInfo.radius = 15.0;
			explosionInfo.blindAmount = 0.66f;
			explosionInfo.flashbangScale = 8.0f;
			explosionInfo.damage = 5.0f;
			explosionInfo.hole_size = 0.0f;
			explosionGameEffect.Explode(explosionContainer);
			break;
		}
		case eKI_NP_3:
		{
			// L-Tag
			SExplosionContainer explosionContainer;
			ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo;
			explosionInfo.pParticleEffect = gEnv->pParticleManager->FindEffect("Crysis2_weapon_fx.l-tag.rico_explosion");
			explosionInfo.pos = playerPos + (playerDir * distFromPlayer);
			explosionInfo.dir.Set(0.0f,-1.0f,0.0f);
			explosionInfo.effect_scale = 1.0f;
			explosionInfo.pressure = 1000.0f;
			explosionInfo.maxblurdistance = 10.0;
			explosionInfo.radius = 15.0;
			explosionInfo.blindAmount = 0.0f;
			explosionInfo.flashbangScale = 8.0f;
			explosionInfo.damage = 5.0f;
			explosionInfo.hole_size = 0.0f;
			explosionGameEffect.Explode(explosionContainer);
			break;
		}
		case GAME_FX_INPUT_ReleaseDebugEffect:
		{
			explosionGameEffect.Release();
			break;
		}
	}
}//-------------------------------------------------------------------------------------------------
/// Used to update any time dependent state (such as timeouts)
void CFlowNode_FeatureTest::Update(float deltaTime)
{
	if(m_running)
	{
		m_timeRunning += deltaTime;
		CryWatch("$7[FG FeatureTest]$o Running test '%s'", Name());

		const string &description = GetPortString(&m_actInfo, eInputPorts_Description);

		if(!description.empty())
			CryWatch("$7[FG FeatureTest]$o %s", description.c_str());

		const float maxTime = GetPortFloat(&m_actInfo, eInputPorts_MaxTime);

		IEntity *pFollowEntity = NULL;

		// Firstly, attempt to get the camera entity (index: -1)
		bool bHasEntry = GetEntityAtIndex(-1, pFollowEntity);

		if(!bHasEntry && !pFollowEntity)
		{
			// If there's an entity being tested, force the view camera to follow it (if no camera entity defined)
			// This needs to be implemented in a cleaner way and allow other options for non-entity based tests.
			bHasEntry = GetEntityAtIndex(m_entitySeqIndex, pFollowEntity);

			// If no sequence entity defined
			if(!bHasEntry && !pFollowEntity)
			{
				// Look for another suitable (active) entity to follow
				for(int i = 0; i < SEQ_ENTITY_COUNT; ++i)
				{
					GetEntityAtIndex(i, pFollowEntity);

					if(pFollowEntity && pFollowEntity->IsActive())
					{
						break;
					}
				}
			}
		}

		if(pFollowEntity)
		{
			CCamera &viewCamera = gEnv->pSystem->GetViewCamera();

			Vec3 vPos(0,0,0);
			Vec3 vDir(0,0,0);

			AABB bounds;
			pFollowEntity->GetWorldBounds(bounds);

			Vec3 vTarget;
			vTarget = bounds.GetCenter();

			vPos = vTarget + (pFollowEntity->GetForwardDir().GetNormalizedSafe() * -2.5f) + Vec3(0.0f, 0.0f, 1.0f);
			vDir = (vTarget - vPos).GetNormalizedSafe();

			float	fRoll(0.0f);

			viewCamera.SetMatrix(CCamera::CreateOrientationYPR(CCamera::CreateAnglesYPR(vDir, fRoll)));
			viewCamera.SetPosition(vPos);
		}

		// If a valid max time has been set
		if(maxTime > 0.0f)
		{
			// If test has exceeded max time
			if(m_timeRunning >= maxTime)
			{
				OnTestResult(false, string().Format("Test failed: Test exceeded maximum time (%f).", maxTime).c_str());
			}
		}
	}
}