//------------------------------------------------------------------------
void CDebugGun::Shoot(bool bPrimary)
{   
  CWeapon::StartFire();
  
  // console cmd      
  string cmd;  

  cmd = (bPrimary) ? g_pGameCVars->i_debuggun_1->GetString() : g_pGameCVars->i_debuggun_2->GetString();  
  cmd += " ";        
        
  unsigned int flags = rwi_stop_at_pierceable|rwi_colltype_any;
  
  if (m_fireModes[m_fireMode].first == "pierceability")
  { 
    flags = (unsigned int)m_fireModes[m_fireMode].second & rwi_pierceability_mask;
  }
  
  IPhysicalWorld* pWorld = gEnv->pPhysicalWorld;
  IPhysicalEntity *pSkip = GetOwnerActor()->GetEntity()->GetPhysics();
  ray_hit rayhit;

  CCamera& cam = GetISystem()->GetViewCamera();
  Vec3 pos = cam.GetPosition()+cam.GetViewdir();
  Vec3 dir = cam.GetViewdir() * HIT_RANGE;

  IEntity* pEntity = 0;

  if (pWorld->RayWorldIntersection(pos, dir, ent_all, flags, &rayhit, 1, &pSkip, 1))
  {
    pEntity = (IEntity*)rayhit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);        
  }
  
  cmd.append(pEntity ? pEntity->GetName() : "0");   
  
  // if we execute an AI command take care of ai_debugdraw
  if (cmd.substr(0, 3) == "ai_")
  {
    if (pEntity && m_pAIDebugDraw->GetIVal() == 0)
      m_pAIDebugDraw->Set(1);
    else if(!pEntity && m_aiDebugDrawPrev == 0 && m_pAIDebugDraw->GetIVal() == 1)
      m_pAIDebugDraw->Set(0);
  }

  gEnv->pConsole->ExecuteString(cmd.c_str());

  // if 2nd button hits a vehicle, enable movement profiling  
  if (!bPrimary)
  {
    static IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem();
     
    string vehicleCmd = "v_debugVehicle ";
    vehicleCmd.append((pEntity && pVehicleSystem->GetVehicle(pEntity->GetId())) ? pEntity->GetName() : "0");
    
    gEnv->pConsole->ExecuteString(vehicleCmd.c_str());
  }

  OnShoot(GetOwnerId(), 0, 0, pos, dir, Vec3(ZERO));
}
	void OnUpdate( SActivationInfo* pActInfo )
	{
		const Vec3 positionOffsetLocal = GetPortVec3( pActInfo, PORT_IN_POSITION_OFFSET_LOCAL );
		const float maxDistance = max( 0.f, GetPortFloat( pActInfo, PORT_IN_MAX_LENGTH ) );

		const CCamera& camera = GetISystem()->GetViewCamera();
		
		const Vec3 cameraDirection = camera.GetViewdir();
		const Vec3 cameraPositionWorld = camera.GetPosition();
		const Matrix33 cameraOrientation = Matrix33::CreateRotationVDir( cameraDirection );
		const Vec3 positionOffsetWorld = cameraOrientation * positionOffsetLocal;

		const Vec3 rayOriginWorld = cameraPositionWorld + positionOffsetWorld;
		const Vec3 raySegment = cameraDirection * maxDistance;


		IPhysicalWorld* pWorld = gEnv->pPhysicalWorld;

		const int objectTypes = ent_all;
		const unsigned int raycastFlags = rwi_stop_at_pierceable | rwi_colltype_any;

		ray_hit hit;
		const int hitCount = pWorld->RayWorldIntersection( rayOriginWorld, raySegment, objectTypes, raycastFlags, &hit, 1 );
		
		float hitDistance = maxDistance;
		if ( 0 < hitCount )
		{
			hitDistance = hit.dist;
		}

		const float timeDelta = 0.1f;
		const float smoothTime = max( 0.f, GetPortFloat( pActInfo, PORT_IN_SMOOTH_TIME ) );
		SmoothCD( m_smoothedHitDistance, m_hitDistanceChangeRate, timeDelta, hitDistance, smoothTime );
		
		ActivateOutput( pActInfo, PORT_OUT_FOCUS_DISTANCE, m_smoothedHitDistance );

		const float focusRangeFactor = max( 0.f, GetPortFloat( pActInfo, PORT_IN_FOCUS_RANGE_FACTOR ) );
		const float focusRange = focusRangeFactor * m_smoothedHitDistance;

		ActivateOutput( pActInfo, PORT_OUT_FOCUS_RANGE, focusRange );


		const bool drawDebugInfo = GetPortBool( pActInfo, PORT_IN_DEBUG_ENABLED );
		if ( ! drawDebugInfo )
		{
			return;
		}

		IRenderer* pRenderer = gEnv->pRenderer;
		IRenderAuxGeom* pRenderAuxGeom = pRenderer->GetIRenderAuxGeom();

		ColorB rayColor = ( 0 < hitCount ) ? ColorB( 255, 255, 0 ) : ColorB( 255, 0, 0 );
		pRenderAuxGeom->DrawSphere( hit.pt, 0.1f, rayColor );
		pRenderAuxGeom->DrawLine( rayOriginWorld, rayColor, hit.pt, rayColor );

	}
Exemplo n.º 3
0
	virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo )
	{
		if (event == eFE_Activate && IsPortActive(pActInfo, GO))
		{
			IEntity * pEntity = pActInfo->pEntity;
			if (pEntity)
			{
				ray_hit hit;
				IPhysicalEntity *pSkip = pEntity->GetPhysics();
				Vec3 direction = GetPortVec3(pActInfo, DIR).GetNormalized();
				if(GetPortBool(pActInfo, TRANSFORM_DIRECTION))
					direction = pEntity->GetWorldTM().TransformVector( GetPortVec3(pActInfo, DIR).GetNormalized() );
				IPhysicalWorld * pWorld = gEnv->pPhysicalWorld;
				int numHits = pWorld->RayWorldIntersection( 
					pEntity->GetPos() + GetPortVec3(pActInfo, POS),
					direction * GetPortFloat(pActInfo, MAXLENGTH),
					ent_all,
					rwi_stop_at_pierceable|rwi_colltype_any,
					&hit, 1, 
					&pSkip, 1 );
					
				if (numHits)
				{
					pEntity = (IEntity*)hit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);    
					ActivateOutput( pActInfo, HIT,(bool)true );
					ActivateOutput( pActInfo, DIROUT, direction );
					ActivateOutput( pActInfo, DISTANCE, hit.dist );
					ActivateOutput( pActInfo, HITPOINT, hit.pt );
					ActivateOutput( pActInfo, NORMAL, hit.n );
					ActivateOutput( pActInfo, SURFTYPE, (int)hit.surface_idx );
					ActivateOutput( pActInfo, HIT_ENTITY, pEntity ? pEntity->GetId() : 0);
				}
				else
					ActivateOutput( pActInfo, NOHIT, false);
			}
		}
	}
Exemplo n.º 4
0
	virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo )
	{
		if (event == eFE_Activate && IsPortActive(pActInfo, GO))
		{
			IEntity * pEntity = pActInfo->pEntity;
			// if (pEntity)
			{
				ray_hit hit;
				CCamera& cam = GetISystem()->GetViewCamera();
				Vec3 pos = cam.GetPosition()+cam.GetViewdir();
				Vec3 direction = cam.GetViewdir();
				IPhysicalWorld * pWorld = gEnv->pPhysicalWorld;
//				IPhysicalEntity *pSkip = 0; // pEntity->GetPhysics();
				int numHits = pWorld->RayWorldIntersection( 
				pos + GetPortVec3(pActInfo, POS),
				direction * GetPortFloat(pActInfo, MAXLENGTH),
				ent_all,
				rwi_stop_at_pierceable|rwi_colltype_any,
				&hit, 1
				/* ,&pSkip, 1 */  );
				if (numHits)
				{
					pEntity = (IEntity*)hit.pCollider->GetForeignData(PHYS_FOREIGN_ID_ENTITY);    
					ActivateOutput( pActInfo, HIT,(bool)true );
					ActivateOutput( pActInfo, DIROUT, direction );
					ActivateOutput( pActInfo, DISTANCE, hit.dist );
					ActivateOutput( pActInfo, HITPOINT, hit.pt );
					ActivateOutput( pActInfo, NORMAL, hit.n );
					ActivateOutput( pActInfo, SURFTYPE, (int)hit.surface_idx );
					ActivateOutput( pActInfo, HIT_ENTITY, pEntity ? pEntity->GetId() : 0);
				}
				else
					ActivateOutput( pActInfo, NOHIT, false );
			}
		}
	}
Exemplo n.º 5
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);
}
Exemplo n.º 6
0
void CBoidFish::Update( float dt,SBoidContext &bc )
{
	if (m_dead)
		return;

	if (m_physicsControlled)
	{
		if (m_pPhysics)
		{
			// If fish is dead, get it position from physics.
			pe_status_pos ppos;
			m_pPhysics->GetStatus(&ppos);
			m_pos = ppos.pos;

			{
				m_dyingTime += Boid::Frand()*0.2f;
				// Apply force on this body.
				pe_action_impulse theAction;
				theAction.impulse = Vec3(sinf(m_dyingTime*0.1f),cosf(m_dyingTime*0.13f),cosf(m_dyingTime*0.171f)*2.8f) * 0.01f;
				theAction.point = m_pos + Vec3(Boid::Frand(),Boid::Frand(),Boid::Frand())*0.1f;
				theAction.iApplyTime = 0;
				theAction.ipart = 0;
				m_pPhysics->Action(&theAction);

				pe_simulation_params sym;
				sym.density = 950.0f + 200.0f*sinf(m_dyingTime);
				if (sym.density < FISH_PHYSICS_DENSITY)
					sym.density = FISH_PHYSICS_DENSITY;
				m_pPhysics->SetParams( &sym );
			}
		}
	}
	if (m_dying)
	{
		// If fish is dying it floats up to the water surface, and die there.
		//UpdateDying(dt,bc);
		m_dyingTime += dt;
		if (m_dyingTime > 60)
		{
			m_dead = true;
			m_dying = false;
			if (m_object)
				m_object->GetISkeletonAnim()->StopAnimationsAllLayers();
		}
		return;
	}


	//////////////////////////////////////////////////////////////////////////
	if (bc.followPlayer)
	{
		if (m_pos.GetSquaredDistance(bc.playerPos) > MAX_FISH_DISTANCE*MAX_FISH_DISTANCE)
		{
			float z = bc.MinHeight + (Boid::Frand()+1)/2.0f*(bc.MaxHeight - bc.MinHeight);
			m_pos = bc.playerPos + Vec3(Boid::Frand()*MAX_FISH_DISTANCE,Boid::Frand()*MAX_FISH_DISTANCE,z );
			m_speed = bc.MinSpeed + ((Boid::Frand()+1)/2.0f) / (bc.MaxSpeed - bc.MinSpeed);
			m_heading = Vec3(Boid::Frand(),Boid::Frand(),0).GetNormalized();
		}
	}

	float height = m_pos.z - bc.terrainZ;

	m_accel.Set(0,0,0);
	m_accel = bc.factorRandomAccel*Vec3(Boid::Frand(),Boid::Frand(),Boid::Frand());
	// Continue accelerating in same dir until target speed reached.
	// Try to maintain average speed of (maxspeed+minspeed)/2
	float targetSpeed = (bc.MaxSpeed + bc.MinSpeed)/2;
	m_accel -= m_heading*(m_speed-targetSpeed)*0.2f;


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

		m_accel += alignmentAccel*bc.factorAlignment;
		m_accel += cohesionAccel*bc.factorCohesion;
		m_accel += separationAccel;
	}

	// Avoid water.
	if (m_pos.z > bc.waterLevel-1)
	{
		float h = bc.waterLevel - m_pos.z;
		float v = (1.0f - h);
		float vv = v*v;
		m_accel.z += (-vv)*bc.factorAvoidLand;

		//gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( m_pos,ColorB(0,0,255,255),m_pos+m_accel,ColorB(0,0,255,255) );
	}
	// Avoid land.
	if (height < bc.MinHeight)
	{
		float v = (1.0f - height/(bc.MinHeight+0.01f));
		float vv = v*v;
		m_accel.z += vv*bc.factorAvoidLand;
		
		// Slow down fast.
		m_accel -= m_heading*(m_speed-0.1f)*vv*bc.factorAvoidLand;
		// Go to origin.
		m_accel += (bc.flockPos - m_pos) * vv * bc.factorAvoidLand;

		//gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( m_pos,ColorB(255,0,0,255),Vec3(m_pos.x,m_pos.y,bc.terrainZ),ColorB(255,0,0,255) );
	}

	if (fabs(m_heading.z) > 0.5f)
	{
		// Always try to accelerate in direction opposite to the current in Z axis.
		m_accel.z += -m_heading.z * 0.8f;
	}

	// Attract to the origin point.
	if (bc.followPlayer)
	{
		m_accel += (bc.playerPos - m_pos) * bc.factorAttractToOrigin;
	}
	else
	{
		m_accel += (bc.randomFlockCenter - m_pos) * bc.factorAttractToOrigin;
	}

	bool bAvoidObstacles = bc.avoidObstacles;
	//////////////////////////////////////////////////////////////////////////
	// High Terrain avoidance.
	//////////////////////////////////////////////////////////////////////////
	Vec3 fwd_pos = m_pos + m_heading*1.0f; // Look ahead 1 meter.
	float fwd_z = bc.engine->GetTerrainElevation(fwd_pos.x,fwd_pos.y);
	if (fwd_z >= m_pos.z-bc.fBoidRadius)
	{
		// If terrain in front of the fish is high, enable obstacle avoidance.
		bAvoidObstacles = true;
	}

	//////////////////////////////////////////////////////////////////////////

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

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

		Vec3 vPos = m_pos;
		Vec3 vDir = m_heading*fCollisionDistance;
		// Add some random variation in probe ray.
		vDir.x += Boid::Frand()*0.8f;
		vDir.y += Boid::Frand()*0.8f;

		int objTypes = ent_all|ent_no_ondemand_activation;
		int flags = rwi_stop_at_pierceable|rwi_ignore_terrain_holes;
		ray_hit hit;

		//gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( vPos,ColorB(0,0,255,255),vPos+vDir,ColorB(0,0,255,255) );

		int col = physWorld->RayWorldIntersection( vPos,vDir,objTypes,flags,&hit,1 );
		if (col != 0 && hit.dist > 0)
		{
				// Turn from collided surface.
			Vec3 normal = hit.n;
			//normal.z = 0; // Only turn left/right.
			float w = (1.0f - hit.dist/fCollisionDistance);
			Vec3 R = m_heading - (2.0f*m_heading.Dot(normal))*normal;
			Boid::Normalize_fast(R);
			R += normal;
			R.z = R.z*0.2f;
			m_accel += R*(w*w)*bc.factorAvoidLand * fCollisionAvoidanceWeight;

			//gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( m_pos,ColorB(0,0,255,255),hit.pt,ColorB(0,0,255,255) );

			//gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( hit.pt,ColorB(255,0,0,255),hit.pt+R*2,ColorB(255,0,0,255) );
			//gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine( m_pos,ColorB(255,0,0,255),m_pos+R*2,ColorB(255,0,0,255) );
		}
	}

	/*
	if (rand()%80 == 1)
	{
		if (m_pos.GetSquaredDistance(bc.playerPos) < 10.0f*10.0f)
		{
			// Spawn bubble.
			SpawnParticleEffect( m_pos,bc,SPAWN_BUBBLE );
		}
	}
	*/

	//////////////////////////////////////////////////////////////////////////
	// Player must scare fishes off.
	//////////////////////////////////////////////////////////////////////////
	float sqrPlayerDist = m_pos.GetSquaredDistance(bc.playerPos);
	if (sqrPlayerDist < SCARE_DISTANCE*SCARE_DISTANCE)
	{
		Vec3 retreatDir = m_pos - bc.playerPos;
		Boid::Normalize_fast(retreatDir);
		float scareFactor = (1.0f - sqrPlayerDist/(SCARE_DISTANCE*SCARE_DISTANCE));
		m_accel.x += retreatDir.x*scareFactor*bc.factorAvoidLand;
		m_accel.y += retreatDir.y*scareFactor*bc.factorAvoidLand;
	}

	//////////////////////////////////////////////////////////////////////////
	// Calc movement.
	CalcMovement( dt,bc,false );
	m_accel.Set(0,0,0);

	// Limits fishes to under water and above terrain.
	if (m_pos.z > bc.waterLevel-0.2f)
	{
		m_pos.z = bc.waterLevel-0.2f;
		if (rand()%40 == 1)
		{
			if (m_pos.GetSquaredDistance(bc.playerPos) < 10.0f*10.0f)
			{
				// Spawn splash.
				SpawnParticleEffect( m_pos,bc,SPAWN_SPLASH );
			}
		}
	}
	else if (m_pos.z < bc.terrainZ+0.2f && bc.terrainZ < bc.waterLevel)
	{
		m_pos.z = bc.terrainZ+0.2f;
	}
}
Exemplo n.º 7
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;
	}
	//////////////////////////////////////////////////////////////////////////
}
Exemplo n.º 8
0
//-----------------------------------------------------------------------------
void CHomingMissile::UpdateControlledMissile(float frameTime)
{
	bool isServer = gEnv->bServer;
	bool isClient = gEnv->bClient;

	CActor *pClientActor=0;
	if (gEnv->bClient)
		pClientActor=static_cast<CActor *>(g_pGame->GetIGameFramework()->GetClientActor());
	bool isOwner = ((!m_ownerId && isServer) || (isClient && pClientActor && (pClientActor->GetEntityId() == m_ownerId) && pClientActor->IsPlayer()));

	IRenderer* pRenderer = gEnv->pRenderer;
	IRenderAuxGeom* pGeom = pRenderer->GetIRenderAuxGeom();
	float color[4] = {1,1,1,1};
	const static float step = 15.f;  
	float y = 20.f;    

	bool bDebug = g_pGameCVars->i_debug_projectiles > 0;

	if (isOwner || isServer)
	{
		//If there's a target, follow the target
		if(isServer)
		{
			if (m_targetId)
			{
				if (m_lockedTimer>0.0f)
					m_lockedTimer=m_lockedTimer-frameTime;
				else
				{
					// If we are here, there's a target
					IEntity* pTarget = gEnv->pEntitySystem->GetEntity(m_targetId);
					if (pTarget)
					{
						AABB box;
						pTarget->GetWorldBounds(box);
						Vec3 finalDes = box.GetCenter();
						SetDestination(finalDes);
						//SetDestination( box.GetCenter() );

						if (bDebug)
							pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "Target Entity: %s", pTarget->GetName());
					}

					m_lockedTimer+=0.05f;
				}
			}
			else if(m_autoControlled)
				return;
		} 

		if (m_controlled && !m_autoControlled && isOwner && !m_targetId)
		{
			//Check if the weapon is still selected
			CWeapon *pWeapon = GetWeapon();

			if(!pWeapon || !pWeapon->IsSelected())
				return;

			if (m_controlledTimer>0.0f)
				m_controlledTimer=m_controlledTimer-frameTime;
			else if (pClientActor && pClientActor->IsPlayer()) 	//Follow the crosshair
			{
				if (IMovementController *pMC=pClientActor->GetMovementController())
				{
					Vec3 eyePos(ZERO);
					Vec3 eyeDir(ZERO);

					IVehicle* pVehicle = pClientActor->GetLinkedVehicle();
					if(!pVehicle)
					{
						SMovementState state;
						pMC->GetMovementState(state);

						eyePos = state.eyePosition;
						eyeDir = state.eyeDirection;
					}
					else
					{	
						SViewParams viewParams;
						pVehicle->UpdateView(viewParams, pClientActor->GetEntityId());

						eyePos = viewParams.position;
						eyeDir = viewParams.rotation * Vec3(0,1,0);
						//eyeDir = (viewParams.targetPos - viewParams.position).GetNormalizedSafe();
					}

					int pierceability=7;

					if (IPhysicalEntity *pPE=GetEntity()->GetPhysics())
					{
						if (pPE->GetType()==PE_PARTICLE)
						{
							pe_params_particle pp;

							if (pPE->GetParams(&pp))
								pierceability=pp.iPierceability;
						}
					}

					static const int objTypes = ent_all;
					static const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (pierceability & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit);

					IPhysicalWorld* pWorld = gEnv->pPhysicalWorld;
					static IPhysicalEntity* pSkipEnts[10];
					int numSkip = CSingle::GetSkipEntities(pWeapon, pSkipEnts, 10);

					ray_hit hit;
					int hits = 0;

					float range=m_maxTargetDistance;
					hits = pWorld->RayWorldIntersection(eyePos + 1.5f*eyeDir, eyeDir*range, objTypes, flags, &hit, 1, pSkipEnts, numSkip);
					
					while (hits)
					{
						if (gEnv->p3DEngine->RefineRayHit(&hit, eyeDir*range))
							break;

						eyePos = hit.pt+eyeDir*0.003f;
						range -= hit.dist+0.003f;

						hits = pWorld->RayWorldIntersection(eyePos, eyeDir*range, objTypes, flags, &hit, 1, pSkipEnts, numSkip);
					}

					DestinationParams params;

					if(hits)
						params.pt=hit.pt;
					else
						params.pt=(eyePos+m_maxTargetDistance*eyeDir);	//Some point in the sky...

					GetGameObject()->InvokeRMI(SvRequestDestination(), params, eRMI_ToServer);

					if (bDebug)
					{
						pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "PlayerView eye direction: %.3f %.3f %.3f", eyeDir.x, eyeDir.y, eyeDir.z);
						pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "PlayerView Target: %.3f %.3f %.3f", hit.pt.x, hit.pt.y, hit.pt.z);
						pRenderer->GetIRenderAuxGeom()->DrawCone(m_destination, Vec3(0,0,-1), 2.5f, 7.f, ColorB(255,0,0,255));
					}
				}

				m_controlledTimer+=0.0f;
			}
		}
	}

	//This code is shared by both modes above (auto and controlled)
	if(!m_destination.IsZero())
	{
		pe_status_dynamics status;
		if (!GetEntity()->GetPhysics()->GetStatus(&status))
		{
			CryLogAlways("couldn't get physics status!");
			return;
		}

		pe_status_pos pos;
		if (!GetEntity()->GetPhysics()->GetStatus(&pos))
		{
			CryLogAlways("couldn't get physics pos!");
			return;
		}

		float currentSpeed = status.v.len();

		if (currentSpeed>0.001f)
		{
			Vec3 currentVel = status.v;
			Vec3 currentPos = pos.pos;
			Vec3 goalDir(ZERO);

			assert(!_isnan(currentSpeed));
			assert(!_isnan(currentVel.x) && !_isnan(currentVel.y) && !_isnan(currentVel.z));

			//Just a security check
			if((currentPos-m_destination).len2()<(m_detonationRadius*m_detonationRadius))
			{
				Explode(true, true, m_destination, -currentVel.normalized(), currentVel, m_targetId);

				return;
			}

			goalDir = m_destination - currentPos;
			goalDir.Normalize();

			//Turn more slowly...
			currentVel.Normalize();

			if(bDebug)
			{

				pRenderer->Draw2dLabel(50,55,2.0f,color,false, "  Destination: %.3f, %.3f, %.3f",m_destination.x,m_destination.y,m_destination.z);
				pRenderer->Draw2dLabel(50,80,2.0f,color,false, "  Current Dir: %.3f, %.3f, %.3f",currentVel.x,currentVel.y,currentVel.z);
				pRenderer->Draw2dLabel(50,105,2.0f,color,false,"  Goal    Dir: %.3f, %.3f, %.3f",goalDir.x,goalDir.y,goalDir.z);
			}

			float cosine = currentVel.Dot(goalDir);
			cosine = CLAMP(cosine,-1.0f,1.0f);
			float totalAngle = RAD2DEG(cry_acosf(cosine));

			assert(totalAngle>=0);

			if (cosine<0.99)
			{
				float maxAngle = m_turnSpeed*frameTime;
				if (maxAngle>totalAngle)
					maxAngle=totalAngle;
				float t=(maxAngle/totalAngle)*m_lazyness;

				assert(t>=0.0 && t<=1.0);

				goalDir = Vec3::CreateSlerp(currentVel, goalDir, t);
				goalDir.Normalize();
			}

			if(bDebug)
				pRenderer->Draw2dLabel(50,180,2.0f,color,false,"Corrected Dir: %.3f, %.3f, %.3f",goalDir.x,goalDir.y,goalDir.z);

			pe_action_set_velocity action;
			action.v = goalDir * currentSpeed;
			GetEntity()->GetPhysics()->Action(&action);
		}
	}
}