Beispiel #1
0
CFrogBoid::CFrogBoid( SBoidContext &bc )
: CBoidBird( bc )
{
	m_maxIdleTime = 2.0f + cry_frand()*MAX_REST_TIME;
	m_maxFlightTime = cry_frand()*MAX_WALK_TIME;
	m_avoidanceAccel.Set(0,0,0);
	m_bThrown = false;
	m_fTimeToNextJump = 0;
	m_alignHorizontally = 1.0f;
}
Beispiel #2
0
CChickenBoid::CChickenBoid( SBoidContext &bc )
: CBoidBird( bc )
{
	m_maxIdleTime = 2.0f + cry_frand()*MAX_REST_TIME;
	m_maxNonIdleTime = cry_frand()*MAX_WALK_TIME;

	m_avoidanceAccel.Set(0,0,0);
	m_bThrown = false;
	m_alignHorizontally = 1;
	m_bScared = false;
}
Beispiel #3
0
CFrogBoid::CFrogBoid( SBoidContext &bc )
: CBoidBird( bc )
{
	m_maxIdleTime = 2.0f + cry_frand()*MAX_REST_TIME;
	m_maxActionTime = cry_frand()*MAX_WALK_TIME;
	m_avoidanceAccel.Set(0,0,0);
	m_bThrown = false;
	m_fTimeToNextJump = 0;
	m_alignHorizontally = 1.0f;
	m_bIsInsideWater = false;
	m_pOnWaterSplashFunc = NULL;
}
Beispiel #4
0
	void CalcFiringPosition(SActivationInfo* pActInfo, IWeapon* pWeapon)
	{
		Vec3 realTargetPos = GetTargetPos( pActInfo );
		m_firingPos = realTargetPos;
		
		float acc = GetPortFloat( pActInfo, IN_ACCURACY );
		if (acc<1)
		{
			bool itHits = cry_frand() < acc;
			if (!itHits)
			{
				// what this code does is: 
				// - in the plane perpendicular to the shooting vector, and located at the target, it builds a vector, centered in the target, and rotates it to point in a random direction, but always in the plane
				// - then it moves along that vector, a random distance (error distance)
				// - and that is the final to-fire position
			
				const float MAX_ERROR_LENGTH = 6.f;  // meters
				const float MIN_ERROR_ANGLE = 2.f; // degrees
				const float MAX_ERROR_ANGLE = 5.f; // degrees

				// error angle from weapon to target				
				float errorAngle = MIN_ERROR_ANGLE + (MAX_ERROR_ANGLE-MIN_ERROR_ANGLE) * cry_frand();
				
				// 2d angle, in the plane normal to the vector from weapon to target.
				float dirErrorAngle = cry_frand() * 360;
				
				// could be done with just 1 sqrt instead 2, but is not really worth it here.
				Vec3 vecToTarget = pActInfo->pEntity->GetPos() - realTargetPos;
				Vec3 vecToTargetNorm = vecToTarget.GetNormalizedSafe();
				Vec3 dirError2D = vecToTargetNorm.GetOrthogonal();
				dirError2D = dirError2D.GetRotated( vecToTargetNorm, DEG2RAD(dirErrorAngle) );
				
				float dist = vecToTarget.len();
				float errorLen = std::min( dist * tanf( DEG2RAD(errorAngle) ), MAX_ERROR_LENGTH );
				
				m_firingPos = realTargetPos + ( dirError2D * errorLen );
				
				#ifdef DEBUG_NODEFIREWEAPON
				posTarget = realTargetPos;
				posOrig = pActInfo->pEntity->GetPos();
				posShot = m_firingPos;
				#endif
			}
		}
		if (GetPortBool( pActInfo, IN_ALIGNTOTARGET ))
		{     
			UpdateWeaponTM( pActInfo, m_firingPos );
			m_lastPos = pActInfo->pEntity->GetWorldPos();
			m_lastRotation = pActInfo->pEntity->GetWorldRotation();
		}
		pWeapon->SetDestination( m_firingPos );
	}
Beispiel #5
0
CBoidBird::CBoidBird( SBoidContext &bc )
: CBoidObject( bc )
{
	m_actionTime = 0;
	m_lastThinkTime = 0;
	m_maxActionTime = 0;

	m_fNoCenterAttract	= 0.f;
	m_fNoKeepHeight			= 0.f;
	m_fAttractionFactor	= 0.f;

//	m_landing = false;
//	m_takingoff = true;
//	m_onGround = false;
	m_attractedToPt = false;
	m_spawnFromPt = false;
	m_floorCollisionInfo.Reset();

	SetStatus(Bird::FLYING);

	m_maxActionTime = bc.flightTime *(1.2f +Boid::Frand()* 0.2f);// /2*(MAX_FLIGHT_TIME-MIN_FLIGHT_TIME);
	m_desiredHeigh = bc.MinHeight + cry_frand()*(bc.MaxHeight - bc.MinHeight) + bc.flockPos.z;
	m_birdOriginPos = bc.flockPos;
	m_birdOriginPosTrg = m_birdOriginPos;
	m_takeOffStartTime = gEnv->pTimer->GetFrameStartTime();
	m_orientation.zero();
	m_walkSpeed = bc.walkSpeed > 0 ? bc.walkSpeed * (1 + Boid::Frand()*0.2f) :0;
}
void CRecoilOffset::TriggerRecoil(bool firstFire)
{
	m_fireTime = m_staticParams.fireRecoilTime;

	m_fireDirection = Vec3(0.0f, -1.0f, 0.0f);
	m_fireDirection.x = (cry_frand() * 2.0f - 1.0f) * m_staticParams.randomness;
	m_fireDirection.z = (cry_frand() * 2.0f - 1.0f) * m_staticParams.randomness;

	Vec3 randAng;
	randAng.x = std::abs(m_fireDirection.x);
	randAng.y = (cry_frand() * 2.0f - 1.0f) * m_staticParams.randomness * 0.5f;
	randAng.z = -m_fireDirection.z * 0.2f;

	m_fireDirection.Normalize();
	randAng.Normalize();

	m_angleDirection = Ang3(randAng);

	m_firstFire = firstFire;
}
Beispiel #7
0
void CLightningArc::Update(SEntityUpdateContext& ctx, int updateSlot)
{
	if (!m_enabled || !m_inGameMode)
		return;

	m_timer -= ctx.fFrameTime;

	if (m_timer < 0.0f)
	{
		TriggerSpark();
		m_timer += m_delay + (cry_frand()*0.5f+0.5f)*m_delayVariation;
	}
}
EntityId CSpammer::GetNextLockOnTarget() const
{
	EntityId result = 0;

	if (!m_potentialTargets.m_potentialTargets.empty())
	{
		float randomProbability = cry_frand() * m_potentialTargets.m_totalProbability;
		int selectedIdx;
		for (selectedIdx = 0; randomProbability > 0.0f; ++selectedIdx)
			randomProbability -= m_potentialTargets.m_potentialTargets[selectedIdx].m_probability;
		--selectedIdx;
		result = m_potentialTargets.m_potentialTargets[selectedIdx].m_target;
	}

	return result;
}
Beispiel #9
0
void CTurtleBoid::Think(float dt,SBoidContext &bc)
{
	bc.fMaxTurnRatio = 0.05f;

	if(m_bScared)
	{
		m_landing = false;
		m_actionTime = 0;
		dt = 0;
	}

	bool bWasScared = m_bScared;
	CChickenBoid::Think(dt,bc);

	if(m_bThrown)
	{
		m_pos.z = bc.engine->GetTerrainElevation(m_pos.x,m_pos.y) + bc.fBoidRadius*0.5f;
	}

	if(m_bScared && !m_bThrown)
	{
		// When scared will not move
		m_accel.Set(0,0,0);

		// If first frame scared play scared animation.
		if(!bWasScared)
			PlayAnimationId(CHICKEN_IDLE_ANIM+1,false,1.0f);

		m_landing = true;
		m_actionTime = 0;
	}
	else if(bWasScared)
	{
		// Not scared anymore, resume idle anim.
		m_maxNonIdleTime = cry_frand()*MAX_WALK_TIME;
		PlayAnimationId(CHICKEN_WALK_ANIM,true);
		m_landing = false;
		m_actionTime = 0;
	}
}
Beispiel #10
0
void CFrogBoid::Think( float dt,SBoidContext &bc )
{
	Vec3 flockHeading(0,0,0);

	m_accel(0,0,0);

	bool bScaredJump = false;
	//////////////////////////////////////////////////////////////////////////
	// Scare points also scare chicken off.
	//////////////////////////////////////////////////////////////////////////
	if (bc.scareRatio > 0)
	{
		float sqrScareDist = m_pos.GetSquaredDistance(bc.scarePoint);
		if (sqrScareDist < bc.scareRadius*bc.scareRadius)
		{
			bScaredJump = true;
		}
	}
	//////////////////////////////////////////////////////////////////////////

	m_fTimeToNextJump -= dt;
	if (m_onGround)
	{
		float fScareDist = MAX_FROG_SCARE_DISTANCE;
		float sqrPlayerDist = m_pos.GetSquaredDistance(bc.playerPos);
		if (m_fTimeToNextJump <= 0 || sqrPlayerDist < fScareDist*fScareDist || bScaredJump)
		{
			PlaySound(FROG_SOUND_JUMP);
			PlayAnimationId( FROG_JUMP_ANIM,false,0 );
			
			m_fTimeToNextJump = 2.0f + cry_frand()*5.0f; // about every 5-6 second.
			//m_fTimeToNextJump = 0;

			// Scared by player or random jump.
			m_onGround = false;
			m_heading = m_pos - bc.playerPos;
			
			if (bScaredJump)
			{
				// Jump from scare point.
				m_heading = Vec3(m_pos - bc.scarePoint).GetNormalized();
			}
			else if (sqrPlayerDist < fScareDist*fScareDist)
			{
				// Jump from player.
				m_heading = Vec3(m_pos - bc.playerPos).GetNormalized();
			}
			else
			{
				if (m_heading != Vec3(0,0,0))
				{
					m_heading = m_heading.GetNormalized();
				}
				else
					m_heading = Vec3(Boid::Frand(),Boid::Frand(),Boid::Frand()).GetNormalized();

				if (m_pos.GetSquaredDistance(bc.flockPos) > bc.fSpawnRadius)
				{
					// If we are too far from spawn radius, jump back.
					Vec3 jumpToOrigin = Vec3(	bc.flockPos.x+Boid::Frand()*bc.fSpawnRadius,bc.flockPos.y+Boid::Frand()*bc.fSpawnRadius,bc.flockPos.z+Boid::Frand()*bc.fSpawnRadius );
					m_heading = Vec3(jumpToOrigin-m_pos).GetNormalized();
				}
			}
			
			m_heading += Vec3(Boid::Frand()*0.4f,Boid::Frand()*0.4f,0 );
			m_heading.Normalize();
			m_heading.z = 0.5f + (Boid::Frand()+1.0f)*0.3f;
			m_heading.Normalize();

			if (bc.avoidObstacles)
			{
				int retries = 4;
				bool bCollision;
				do 
				{
					bCollision = false;
					// Avoid obstacles & terrain.
					IPhysicalWorld *physWorld = bc.physics;

					Vec3 vPos = m_pos + Vec3(0,0,bc.fBoidRadius*0.5f);
					Vec3 vDir = m_heading*(bc.fBoidRadius*5) + Vec3(0,0,bc.fBoidRadius*1.0f);

					int objTypes = ent_all|ent_no_ondemand_activation;
					int flags = rwi_stop_at_pierceable|rwi_ignore_terrain_holes;
					ray_hit hit;
					int col = physWorld->RayWorldIntersection( vPos,vDir,objTypes,flags,&hit,1 );
					if (col != 0 && hit.dist > 0)
					{
						bCollision = true;
						m_heading = Vec3(Boid::Frand(),Boid::Frand(),0 ); // Pick some random jump vector.
						m_heading.Normalize();
						m_heading.z = 0.5f + (Boid::Frand()+1.0f)*0.3f;
						m_heading.Normalize();
					}
				} while (!bCollision && retries-- > 0);
			}

			m_speed = bc.MinSpeed + cry_frand()*(bc.MaxSpeed-bc.MinSpeed);
		}
	}

	bc.terrainZ = bc.engine->GetTerrainElevation(m_pos.x,m_pos.y) + bc.fBoidRadius*0.5f;

	float range = bc.MaxAttractDistance;

	Vec3 origin = bc.flockPos;

	if (bc.followPlayer)
	{
		origin = bc.playerPos;
	}

	// Keep in range.
	if (bc.followPlayer)
	{
		bool bChanged = false;
		if (m_pos.x < origin.x - range)
		{
			m_pos.x = origin.x + range;
			bChanged = true;
		}
		if (m_pos.y < origin.y - range)
		{
			m_pos.y = origin.y + range;
			bChanged = true;
		}
		if (m_pos.x > origin.x + range)
		{
			m_pos.x = origin.x - range;
			bChanged = true;
		}
		if (m_pos.y > origin.y + range)
		{
			m_pos.y = origin.y - range;
			bChanged = true;
		}
		if (bChanged)
			m_pos.z = bc.terrainZ = bc.engine->GetTerrainElevation(m_pos.x,m_pos.y) + bc.fBoidRadius*0.5f;
	}
	else
	{
	}

	if (!m_onGround)
	{
		m_accel.Set( 0,0,-10 );
	}

	if (m_pos.z < bc.terrainZ+0.001f)
	{
		// Land.
		m_pos.z = bc.terrainZ+0.001f;
		if (!m_onGround)
		{
			m_heading.z = 0;
			m_onGround = true;
			m_speed = 0;
			PlayAnimationId( FROG_IDLE_ANIM,true );
		}
	}

	// Do random idle sounds.
	if ((cry_rand()&0xFF) == 0)
		PlaySound(FROG_SOUND_IDLE);
}
Beispiel #11
0
void CChickenBoid::Think( float dt,SBoidContext &bc )
{
	Vec3 flockHeading(0,0,0);

	m_accel(0,0,0);
//	float height = m_pos.z - bc.terrainZ;

	if (m_bThrown)
	{
		m_accel.Set(0,0,-10.0f);
		//float z = bc.engine->GetTerrainElevation(m_pos.x,m_pos.y) + bc.fBoidRadius*0.5f;
		m_pos.z = bc.engine->GetTerrainElevation(m_pos.x,m_pos.y) + bc.fBoidRadius*0.5f;
		//pe_status_pos ppos;
		//m_pPhysics->GetStatus(&ppos);
		//if (m_pos.z < z)
		{
			m_physicsControlled = false;
			m_bThrown = false;
			m_heading.z = 0;
			if (m_heading.IsZero())
				m_heading = Vec3(1,0,0);
			m_heading.Normalize();
			m_accel.Set(0,0,0);
			m_speed = bc.MinSpeed;
			m_heading.z = 0;
		}
		return;
	}

	// Free will.
	// Continue accelerating in same dir untill target speed reached.
	// Try to maintain average speed of (maxspeed+minspeed)/2
	float targetSpeed = bc.MinSpeed;
	m_accel -= m_heading*(m_speed-targetSpeed)*0.4f;

	// Gaussian weight.
	m_accel.z = 0;

	m_bScared = false;

	if (bc.factorAlignment != 0)
	{
		//CalcCohesion();
		Vec3 alignmentAccel;
		Vec3 cohesionAccel;
		Vec3 separationAccel;
		CalcFlockBehavior(bc,alignmentAccel,cohesionAccel,separationAccel);

		//! Adjust for allignment,
		//m_accel += alignmentAccel.Normalized()*ALIGNMENT_FACTOR;
		m_accel += alignmentAccel*bc.factorAlignment;
		m_accel += cohesionAccel*bc.factorCohesion;
		m_accel += separationAccel;
	}

	/*
	// Avoid land.
	if (height < bc.MinHeight && !m_landing)
	{
		float v = (1.0f - height/bc.MinHeight);
		m_accel += Vec3(0,0,v*v)*bc.factorAvoidLand;
	}
	else if (height > bc.MaxHeight) // Avoid max height.
	{
		float v = (height - bc.MaxHeight)*0.1f;
		m_accel += Vec3(0,0,-v);
	}
	else
	{
		// Always try to accelerate in direction oposite to current in Z axis.
		m_accel.z = -(m_heading.z*m_heading.z*m_heading.z * 100.0f);
	}
	*/

	// Attract to origin point.
	if (bc.followPlayer)
	{
		m_accel += (bc.playerPos - m_pos) * bc.factorAttractToOrigin;
	}
	else
	{
		//m_accel += (m_birdOriginPos - m_pos) * bc.factorAttractToOrigin;
		if ((cry_rand()&31) == 1)
		{
			m_birdOriginPos = Vec3(	bc.flockPos.x+frand()*bc.fSpawnRadius,bc.flockPos.y+frand()*bc.fSpawnRadius,bc.flockPos.z+frand()*bc.fSpawnRadius );
			if (m_birdOriginPos.z - bc.terrainZ < bc.MinHeight)
			{
				m_birdOriginPos.z = bc.terrainZ + bc.MinHeight;
			}
		}

		/*
		if (m_pos.x < bc.flockPos.x-bc.fSpawnRadius || m_pos.x > bc.flockPos.x+bc.fSpawnRadius ||
		m_pos.y < bc.flockPos.y-bc.fSpawnRadius || m_pos.y > bc.flockPos.y+bc.fSpawnRadius ||
		m_pos.z < bc.flockPos.z-bc.fSpawnRadius || m_pos.z > bc.flockPos.z+bc.fSpawnRadius)
		*/
		{
			m_accel += (m_birdOriginPos - m_pos) * bc.factorAttractToOrigin;
		}
	}


	// Avoid collision with Terrain and Static objects.
	float fCollisionAvoidanceWeight = 10.0f;

	// Do walk sounds.
	if ((cry_rand()&0xFF) == 0)
		PlaySound(CHICKEN_SOUND_CLUCK);

	//////////////////////////////////////////////////////////////////////////
	// Player must scare chickens off.
	//////////////////////////////////////////////////////////////////////////
	float fScareDist = 5.0f;
	float sqrPlayerDist = m_pos.GetSquaredDistance(bc.playerPos);
	if (sqrPlayerDist < fScareDist*fScareDist)
	{
		Vec3 retreatDir = (m_pos - bc.playerPos) + Vec3(frand()*2.0f,frand()*2.0f,0);
		retreatDir.NormalizeFast();
		float scareFactor = (1.0f - sqrPlayerDist/(fScareDist*fScareDist));
		m_accel.x += retreatDir.x*scareFactor*bc.factorAvoidLand;
		m_accel.y += retreatDir.y*scareFactor*bc.factorAvoidLand;

		m_bScared = true;
		if (m_landing) m_flightTime = m_maxIdleTime+1.0f; // Stop idle.
		// Do walk sounds.
		if ((cry_rand()&0xFF) == 0)
			PlaySound(CHICKEN_SOUND_SCARED);
	}

	//////////////////////////////////////////////////////////////////////////
	// Scare points also scare chicken off.
	//////////////////////////////////////////////////////////////////////////
	if (bc.scareRatio > 0)
	{
		float sqrScareDist = m_pos.GetSquaredDistance(bc.scarePoint);
		if (sqrScareDist < bc.scareRadius*bc.scareRadius)
		{
			float fScareMultiplier = 10.0f;
			Vec3 retreatDir = m_pos - bc.scarePoint;
			retreatDir.NormalizeFast();
			float scareFactor = (1.0f - sqrScareDist/(bc.scareRadius*bc.scareRadius));
			m_accel.x += retreatDir.x*scareFactor*fScareMultiplier;
			m_accel.y += retreatDir.y*scareFactor*fScareMultiplier;

			if (m_landing) m_flightTime = m_maxIdleTime+1.0f; // Stop idle.

			m_bScared = true;

			// Do walk sounds.
			if ((cry_rand()&0xF) == 0)
				PlaySound(CHICKEN_SOUND_CLUCK);
		}
	}
	//////////////////////////////////////////////////////////////////////////


	if (bc.avoidObstacles)
	{
		// Avoid obstacles & terrain.
		IPhysicalWorld *physWorld = bc.physics;

		Vec3 vDir0 = m_heading*bc.fBoidRadius*0.5f;
		Vec3 vPos = m_pos + Vec3(0,0,bc.fBoidRadius*0.5f) + vDir0;
		Vec3 vDir = m_heading*(bc.fBoidRadius*2) + Vec3(0,0,bc.fBoidRadius*0.5f);
		// Add some random variation in probe ray.
		vDir.x += frand()*0.5f;
		vDir.y += frand()*0.5f;

		int objTypes = ent_all|ent_no_ondemand_activation;
		int flags = rwi_stop_at_pierceable|rwi_ignore_terrain_holes;
		ray_hit hit;
		int col = physWorld->RayWorldIntersection( vPos,vDir,objTypes,flags,&hit,1 );
		if (col != 0 && hit.dist > 0)
		{
			// Turn from collided surface.
			Vec3 normal = hit.n;
			float rayLen = vDir.GetLength();
			float w = (1.0f - hit.dist/rayLen);
			Vec3 R = m_heading - (2.0f*m_heading.Dot(normal))*normal;
			R.NormalizeFast();
			R += normal;
			//m_accel += R*(w*w)*bc.factorAvoidLand * fCollisionAvoidanceWeight;
			Vec3 accel = R*w*bc.factorAvoidLand * fCollisionAvoidanceWeight;
			m_avoidanceAccel = m_avoidanceAccel*bc.fSmoothFactor + accel*(1.0f-bc.fSmoothFactor);
		}
	}

	m_accel += m_avoidanceAccel;
	m_avoidanceAccel = m_avoidanceAccel*bc.fSmoothFactor;

	if (!m_landing)
	{
		m_flightTime += dt;
		if (m_flightTime > m_maxNonIdleTime && (m_pos.z > bc.waterLevel && bc.bAvoidWater))
		{
			// Play idle.
			PlayAnimationId( CHICKEN_IDLE_ANIM + (cry_rand()%CHICKEN_IDLE_ANIM_NUM),true );
			m_maxIdleTime = 2.0f + cry_frand()*MAX_REST_TIME;
			m_landing = true;
			m_flightTime = 0;
			
			m_accel.Set(0,0,0);
			m_speed = 0;
		}
	}
	else
	{
		m_accel = m_heading;
		m_speed = 0.1f;

		m_flightTime += dt;
		if (m_flightTime > m_maxIdleTime)
		{
			m_maxNonIdleTime = cry_frand()*MAX_WALK_TIME;
			PlayAnimationId( CHICKEN_WALK_ANIM,true );
			m_landing = false;
			m_flightTime = 0;
		}
	}

	// Limits birds to above water and land.
	m_pos.z = bc.engine->GetTerrainElevation(m_pos.x,m_pos.y) + bc.fBoidRadius*0.5f;
	m_accel.z = 0;

	//////////////////////////////////////////////////////////////////////////
	// Avoid water ocean..
	if (m_pos.z < bc.waterLevel && bc.bAvoidWater)
	{
		if (m_landing)
			m_flightTime = m_maxIdleTime;
		Vec3 nextpos = m_pos + m_heading;
		float farz = bc.engine->GetTerrainElevation(nextpos.x,nextpos.y) + bc.fBoidRadius*0.5f;
		if (farz > m_pos.z)
			m_accel += m_heading*bc.factorAvoidLand;
		else
			m_accel += -m_heading*bc.factorAvoidLand;
		m_accel.z = 0;
	}
	//////////////////////////////////////////////////////////////////////////
}
//------------------------------------------------------------------------
bool CTracer::Update(float frameTime, const Vec3 &camera, const float fovScale)
{
	frameTime							= (float)__fsel(-m_age, 0.002f, frameTime);
	const float tracerAge	= (float)__fsel(-m_age, 0.002f, m_age+frameTime);

	m_age = tracerAge;

	if (tracerAge >= m_lifeTime)
		return false;

	Vec3 currentLimitDestination;
	if (gEnv->bMultiplayer)
	{
		if(m_tracerFlags & kTracerFlag_updateDestFromBullet)
		{
			IEntity* pBulletEntity = gEnv->pEntitySystem->GetEntity(m_boundToBulletId);
			if(pBulletEntity)
			{
				m_dest = pBulletEntity->GetPos();
			}
		}
		currentLimitDestination = m_dest;
	}
	else
	{
		IEntity* pBulletEntity = gEnv->pEntitySystem->GetEntity(m_boundToBulletId);
		currentLimitDestination = pBulletEntity ? pBulletEntity->GetPos() : m_dest;
	}

	const Vec3 maxTravelledDistance = m_dest - m_startingPos;
	const float maxTravelledDistanceSqr = maxTravelledDistance.len2();
	
	float dist = sqrt_tpl(maxTravelledDistanceSqr);
	if (dist <= 0.001f)
		return false;
		
	const Vec3 dir = maxTravelledDistance * (float)__fres(dist);
	Vec3 pos = m_pos;
	float lengthScale = 1.f;
	Vec3 newPos = m_pos;
	
	if (!(m_tracerFlags & kTracerFlag_dontTranslate))
  {
    const float sqrRadius = GetGameConstCVar(g_tracers_slowDownAtCameraDistance) * GetGameConstCVar(g_tracers_slowDownAtCameraDistance);
		const float cameraDistance = (m_pos-camera).len2();
    const float speed = m_speed * (float)__fsel(sqrRadius - cameraDistance, 0.35f + (cameraDistance/(sqrRadius*2)), 1.0f); //Slow down tracer when near the player
    newPos += dir * min(speed*frameTime, dist);
	  pos = newPos;

		if(m_slideFrac > 0.f)
		{
			pos += (((2.f * cry_frand()) - 0.5f) * m_slideFrac * speed * frameTime * dir);
		}
  }

	// Now update visuals...
	if (IEntity *pEntity = gEnv->pEntitySystem->GetEntity(m_entityId))
	{
		AABB tracerBbox;
		pEntity->GetWorldBounds(tracerBbox);

		float tracerHalfLength = !tracerBbox.IsEmpty() ? tracerBbox.GetRadius() : 0.0f;
		const Vec3 frontOfTracerPos = pos + (dir * tracerHalfLength);

		if((frontOfTracerPos-m_startingPos).len2() > maxTravelledDistanceSqr)
		{
			return false;
		}
	
		if (!(m_tracerFlags & kTracerFlag_dontTranslate) && tracerHalfLength > 0.f)
		{
			//Ensure that never goes in front of the bullet
			const Vec3 dirFromFrontOfTracerToDestination = currentLimitDestination - frontOfTracerPos;
			if (dir.dot(dirFromFrontOfTracerToDestination) < 0)
			{
				pos += dirFromFrontOfTracerToDestination;
			}

			// ... and check if back of tracer is behind starting point, so adjust length.
			const Vec3 backOfTracerPos = pos - (dir * tracerHalfLength);
			const Vec3 dirFromBackOfTracerToStart = m_startingPos - backOfTracerPos;

			if (dir.dot(dirFromBackOfTracerToStart) > 0)
			{
				if(dir.dot((m_startingPos - pos)) > 0)
				{
					pos = m_startingPos + (dir * cry_frand() * tracerHalfLength);
				}

				lengthScale = ((pos - m_startingPos).GetLength() / tracerHalfLength);
			}
		}
		
		m_pos = newPos;
		
		Matrix34 tm(Matrix33::CreateRotationVDir(dir));
		tm.AddTranslation(pos);

		pEntity->SetWorldTM(tm);

		//Do not scale effects
		if((m_tracerFlags & kTracerFlag_useGeometry))
		{
			float finalFovScale = fovScale;
			if((m_tracerFlags & kTracerFlag_scaleToDistance) != 0)
			{
				lengthScale = dist * 0.5f;
			}
			else
			{
				const float cameraDistanceSqr = (m_pos-camera).len2();
				const float minScale = GetGameConstCVar(g_tracers_minScale);
				const float maxScale = GetGameConstCVar(g_tracers_maxScale);
				const float minDistanceRange = GetGameConstCVar(g_tracers_minScaleAtDistance) * GetGameConstCVar(g_tracers_minScaleAtDistance);
				const float maxDistanceRange = max(GetGameConstCVar(g_tracers_maxScaleAtDistance) * GetGameConstCVar(g_tracers_maxScaleAtDistance), minDistanceRange + 1.0f);
				const float currentRefDistance = clamp(cameraDistanceSqr, minDistanceRange, maxDistanceRange);

				const float distanceToCameraFactor = ((currentRefDistance - minDistanceRange) / (maxDistanceRange - minDistanceRange));
				const float distanceToCameraScale = LERP(minScale, maxScale, distanceToCameraFactor);
				
				lengthScale = m_scale * distanceToCameraScale;
				finalFovScale *= distanceToCameraScale;
			}
			
			const float widthScale = fovScale;

			tm.SetIdentity();
			tm.SetScale(Vec3(m_scale * finalFovScale, lengthScale, m_scale * finalFovScale));
			pEntity->SetSlotLocalTM(m_geometrySlot,tm);
		}
	}

	return true;
}
//--------------------------------------------------------------------------------------------------
// Name: SpawnParticlesOnSkeleton
// Desc: Spawn particles on Skeleton
//--------------------------------------------------------------------------------------------------
void CGameEffect::SpawnParticlesOnSkeleton(IEntity* pEntity, IParticleEmitter* pParticleEmitter, uint32 numParticles,float maxHeightScale) const
{
	if((pEntity) && (numParticles>0) && (pParticleEmitter) && (maxHeightScale>0.0f))
	{
		ICharacterInstance* pCharacter = pEntity->GetCharacter(0);
		if(pCharacter)
		{
			ICharacterModelSkeleton* pICharacterModelSkeleton = pCharacter->GetICharacterModel()->GetICharacterModelSkeleton();
			ISkeletonPose* pPose = pCharacter->GetISkeletonPose();
			if(pPose && pICharacterModelSkeleton)
			{
				Vec3 animPos;
				Quat animRot;

				IActor* pActor = gEnv->pGame->GetIGameFramework()->GetIActorSystem()->GetActor(pEntity->GetId());
				if(pActor) // First try to get animation data
				{
					QuatT animLoc = pActor->GetAnimatedCharacter()->GetAnimLocation();
					animPos = animLoc.t;
					animRot = animLoc.q;
				}
				else // If no actor, then use entity data
				{
					animPos = pEntity->GetWorldPos();
					animRot = pEntity->GetWorldRotation();
				}

				animRot.Invert();

				AABB bbox;
				pEntity->GetLocalBounds(bbox);
				float bbHeight = bbox.max.z - bbox.min.z;
				// Avoid division by 0
				if(bbHeight == 0)
				{
					bbHeight = 0.0001f;
				}

				const uint32 numJoints = pICharacterModelSkeleton->GetJointCount();

				while(numParticles > 0)
				{
					int id = Random(numJoints);
					int parentId = pICharacterModelSkeleton->GetJointParentIDByID(id);

					if(parentId>0)
					{
						QuatT boneQuat = pPose->GetAbsJointByID(id);
						QuatT parentBoneQuat= pPose->GetAbsJointByID(parentId);
						float lerpScale = cry_frand();

						QuatTS loc(IDENTITY);
						loc.t = LERP(boneQuat.t,parentBoneQuat.t,lerpScale);

						float heightScale = ((loc.t.z - bbox.min.z) / bbHeight);
						if(heightScale < maxHeightScale)
						{
							loc.t = loc.t * animRot;
							loc.t = loc.t + animPos;

							pParticleEmitter->EmitParticle(NULL, NULL, &loc);
						}
					}
				}
			}
		}
	}
}//-------------------------------------------------------------------------------------------------