//------------------------------------------------------------------------ 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 ); }
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); } } }
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 ); } } }
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); }
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; } }
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; } ////////////////////////////////////////////////////////////////////////// }
//----------------------------------------------------------------------------- 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); } } }