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