int CScriptBind_Boids::OnPickup(IFunctionHandler *pH, SmartScriptTable flockEntity, SmartScriptTable boidEntity, bool bPickup, float fThrowSpeed) { CFlock* flock = GetFlock(flockEntity); IEntity* pBoidEntity = GetEntity(boidEntity); if (flock != NULL && pBoidEntity != NULL) { CBoidObject* pBoidObject = NULL; for (int i = 0; i < flock->GetBoidsCount(); ++i) { if (flock->GetBoid(i)->GetId() == pBoidEntity->GetId()) { pBoidObject = flock->GetBoid(i); break; } } if (pBoidObject != NULL) { pBoidObject->OnPickup(bPickup, fThrowSpeed); } } return pH->EndFunction(); }
int CScriptBind_Boids::CanPickup(IFunctionHandler *pH, SmartScriptTable flockEntity, SmartScriptTable boidEntity) { CFlock* flock = GetFlock(flockEntity); IEntity* pBoidEntity = GetEntity(boidEntity); if (flock != NULL && pBoidEntity != NULL) { CBoidObject* pBoidObject = NULL; for (int i = 0; i < flock->GetBoidsCount(); ++i) { if (flock->GetBoid(i)->GetId() == pBoidEntity->GetId()) { pBoidObject = flock->GetBoid(i); break; } } if (pBoidObject != NULL) { SBoidContext bc; flock->GetBoidSettings(bc); return pH->EndFunction((pBoidObject->IsDead() && bc.bPickableWhenDead) || (!pBoidObject->IsDead() && bc.bPickableWhenAlive)); } } return pH->EndFunction(0); }
void CFlock::UpdateBoidCollisions() { if(!m_bc.avoidObstacles) return; const int numberOfChecks = 5; CTimeValue now = gEnv->pTimer->GetFrameStartTime(); int checked = 0; // rough check if(m_BoidCollisionMap.size() != m_boids.size()) { m_BoidCollisionMap.clear(); for (Boids::iterator it = m_boids.begin(),itEnd = m_boids.end(); it != itEnd; ++it) m_BoidCollisionMap.insert(std::make_pair(now,*it)); } for (TTimeBoidMap::iterator it = m_BoidCollisionMap.begin(),itEnd = m_BoidCollisionMap.end(); it != itEnd && checked < numberOfChecks; ++it) { CBoidObject* pBoid = it->second; if(pBoid && pBoid->ShouldUpdateCollisionInfo(now)) { pBoid->UpdateCollisionInfo(); m_BoidCollisionMap.erase(it); m_BoidCollisionMap.insert(std::make_pair(now,pBoid)); it = m_BoidCollisionMap.begin(); ++checked; } } }
void CFlock::OnBoidHit( EntityId nBoidId,SmartScriptTable &hit ) { int num = (int)m_boids.size(); for (int i = 0; i < num; i++) { CBoidObject *boid = m_boids[i]; if (boid->m_entity == nBoidId) { Vec3 pos = boid->m_pos; Vec3 force = Vec3(1,1,1); float damage = 1.0f; hit->GetValue("pos", pos); hit->GetValue("dir", force); hit->GetValue("damage", damage); boid->Kill( pos,force*damage ); break; } } }
void CFlock::SetPos( const Vec3& pos ) { Vec3 ofs = pos - m_origin; m_origin = pos; m_bc.flockPos = m_origin; for (Boids::iterator it = m_boids.begin(); it != m_boids.end(); ++it) { CBoidObject *boid = *it; boid->m_pos += ofs; boid->OnFlockMove( m_bc ); } // Update bounding box of flock entity. if (m_pEntity) { //float s = m_bc.MaxAttractDistance; // float s = 1; //m_pEntity->SetBBox( pos-Vec3(s,s,s),pos+Vec3(s,s,s) ); //m_pEntity->ForceRegisterInSectors(); } RegisterAIEventListener(true); }
void CFlock::UpdateBoidCollisions() { if(!m_bc.avoidObstacles) return; const int numberOfChecks = 5; CTimeValue now = gEnv->pTimer->GetFrameStartTime(); int checked = 0; // rough check if(m_BoidCollisionMap.size() != m_boids.size()) { m_BoidCollisionMap.clear(); m_BoidCollisionMap.reserve( m_boids.size() ); for (Boids::iterator it = m_boids.begin(),itEnd = m_boids.end(); it != itEnd; ++it) { m_BoidCollisionMap.push_back( SBoidCollisionTime( now, *it ) ); } std::sort( m_BoidCollisionMap.begin(), m_BoidCollisionMap.end(), FSortBoidByTime() ); } for (TTimeBoidMap::iterator it = m_BoidCollisionMap.begin(),itEnd = m_BoidCollisionMap.end(); it != itEnd && checked < numberOfChecks; ++it) { CBoidObject* pBoid = it->m_pBoid; if(pBoid && pBoid->ShouldUpdateCollisionInfo(now)) { pBoid->UpdateCollisionInfo(); it->m_time = now; ++checked; } } std::sort( m_BoidCollisionMap.begin(), m_BoidCollisionMap.end(), FSortBoidByTime() ); }
void CFlock::UpdateAvgBoidPos(float dt) { m_lastUpdatePosTimePassed += dt; if(m_lastUpdatePosTimePassed < 0.5f + Boid::Frand()/4.f) return; m_lastUpdatePosTimePassed = 0; m_avgBoidPos.zero(); int n=0; for (Boids::iterator it = m_boids.begin(),itEnd = m_boids.end(); it != itEnd; ++it) { CBoidObject* pBoid = (*it); if(pBoid && !pBoid->IsDead()) { m_avgBoidPos += pBoid->GetPos(); ++n; } } if(n) m_avgBoidPos /= float(n); }
bool CFlock::CreateEntities() { if (!m_e_flocks) return false; SEntitySpawnParams spawnParams; spawnParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("Boid"); if (!spawnParams.pClass) return false; spawnParams.nFlags = ENTITY_FLAG_CLIENT_ONLY | ENTITY_FLAG_NO_SAVE | ENTITY_FLAG_NO_PROXIMITY | m_nBoidEntityFlagsAdd; spawnParams.sName = m_boidEntityName; m_modelCgf = PathUtil::ReplaceExtension(m_model,"cgf"); bool bHasCgfFile = gEnv->pCryPak->IsFileExist(m_modelCgf) && m_bc.animationMaxDistanceSq > 0; if(!bHasCgfFile) m_bc.animationMaxDistanceSq = 0; bool bAnyCreated = false; for (Boids::iterator it = m_boids.begin(); it != m_boids.end(); ++it) { CBoidObject *boid = *it;/*m_boids[i]*/; if (boid->m_dead || boid->m_dying) continue; spawnParams.vPosition = boid->m_pos; spawnParams.vScale = Vec3(boid->m_scale,boid->m_scale,boid->m_scale); spawnParams.id = 0; IEntity *pBoidEntity = gEnv->pEntitySystem->SpawnEntity( spawnParams ); if (!pBoidEntity) { //delete boid; //it = m_boids.erase(it); continue; } boid->m_noentity = false; boid->m_entity = pBoidEntity->GetId(); CBoidObjectProxyPtr pBoidObjectProxy = ComponentCreateAndRegister_DeleteWithRelease<CBoidObjectProxy>( IComponent::SComponentInitializer(pBoidEntity), true ); pBoidEntity->SetProxy(ENTITY_PROXY_BOID_OBJECT,pBoidObjectProxy); pBoidObjectProxy->SetBoid(boid); // check if character. if (IsCharacterFile(m_model)) { if(bHasCgfFile) pBoidEntity->LoadGeometry(CBoidObject::eSlot_Cgf, m_modelCgf); pBoidEntity->LoadCharacter( CBoidObject::eSlot_Chr,m_model ); boid->m_object = pBoidEntity->GetCharacter(0); if (!boid->m_object) { gEnv->pEntitySystem->RemoveEntity(boid->m_entity,true); boid->m_entity = 0; //delete boid; //it = m_boids.erase(it); continue; } } else { pBoidEntity->LoadGeometry( 0,m_model ); } bAnyCreated = true; // boid->m_object->GetModel()->AddRef(); AABB aabb; if (boid->m_object) { boid->m_object->SetFlags( CS_FLAG_DRAW_MODEL|CS_FLAG_UPDATE ); boid->PlayAnimation( m_boidDefaultAnimName,true ); aabb = boid->m_object->GetAABB(); } else { pBoidEntity->GetLocalBounds(aabb); } float fBBoxRadius = ((aabb.max-aabb.min).GetLength()/2.0f); m_bc.fBoidRadius = max( fBBoxRadius, 0.001f ); m_bc.fBoidThickness = m_bc.fBoidRadius; if (!m_bc.vEntitySlotOffset.IsZero()) { pBoidEntity->SetSlotLocalTM(0,Matrix34::CreateTranslationMat(m_bc.vEntitySlotOffset*fBBoxRadius)); } boid->Physicalize(m_bc); IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pBoidEntity->GetProxy(ENTITY_PROXY_RENDER); if (pRenderProxy != NULL && m_bc.fBoidRadius > 0) { float r = m_bc.fBoidRadius; AABB box; box.min = Vec3(-r,-r,-r); box.max = Vec3(r,r,r); pRenderProxy->SetLocalBounds( box,true ); } IScriptTable *pScriptTable = pBoidEntity->GetScriptTable(); if (pScriptTable) { pScriptTable->SetValue( "flock_entity",m_pEntity->GetScriptTable() ); } } m_bEntityCreated = true; return bAnyCreated; }
void CFlock::Update( CCamera *pCamera ) { FUNCTION_PROFILER( GetISystem(),PROFILE_ENTITY ); if (!IsFlockActive()) return; if (!m_e_flocks) { if (m_bEntityCreated) DeleteEntities( true ); return; } if(GetISystem()->IsSerializingFile() == 1) //quickloading return; if (!m_bEntityCreated) { if (!CreateEntities()) return; } float dt = gEnv->pTimer->GetFrameTime(); // Make sure delta time is limited. if (dt > 1.0f) dt = 0.01f; if (dt > 0.1f) dt = 0.1f; m_bc.fSmoothFactor = 1.f - gEnv->pTimer->GetProfileFrameBlending(); /* for (Boids::iterator it = m_boids.begin(); it != m_boids.end(); ++it) { CBoidObject *boid = *it; boid->Think(); } */ //m_bc.playerPos = m_flockMgr->GetPlayerPos(); m_bc.playerPos = GetISystem()->GetViewCamera().GetMatrix().GetTranslation(); // Player position is position of camera. m_bc.flockPos = m_origin; m_bc.waterLevel = m_bc.engine->GetWaterLevel( &m_origin ); m_bounds.min = Vec3(FLT_MAX,FLT_MAX,FLT_MAX); m_bounds.max = Vec3(-FLT_MAX,-FLT_MAX,-FLT_MAX); int numBoids = m_boids.size(); if (m_percentEnabled < 100) { numBoids = (m_percentEnabled*numBoids)/100; } if (!m_pEntity->GetRotation().IsIdentity()) { // Entity matrix must not have rotation. //Quat q; //q.SetIdentity(); //m_pEntity->SetRotation(q); } ////////////////////////////////////////////////////////////////////////// // Update flock random center. ////////////////////////////////////////////////////////////////////////// m_fCenterFloatingTime += gEnv->pTimer->GetFrameTime(); float tc = m_fCenterFloatingTime*0.2f; m_bc.randomFlockCenter = m_bc.flockPos + //m_bc.fSpawnRadius*Vec3(sinf(0.9f*m_fCenterFloatingTime),cosf(1.1f*sin(0.9f*m_fCenterFloatingTime)),0.3f*sinf(1.2f*m_fCenterFloatingTime) ); m_bc.fSpawnRadius*Vec3(sinf(tc*0.913f)*cosf(tc*1.12f),sinf(tc*0.931f)*cosf(tc*0.971f),0.4f*sinf(tc*1.045f)*cosf(tc*0.962f) ); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere( m_bc.randomFlockCenter,0.1f,ColorB(255,0,0,255) ); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)m_pEntity->GetProxy(ENTITY_PROXY_RENDER); if (pRenderProxy) { if (pRenderProxy->GetRenderNode()->GetViewDistRatio() != m_nViewDistRatio) UpdateBoidsViewDistRatio(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// // Update scare factors. if (m_bc.scareThreatLevel > 0) { m_bc.scareThreatLevel *= 0.95f; m_bc.scareRatio *= 0.95f; if (m_bc.scareRatio < 0.01f) { m_bc.scareRatio = 0; m_bc.scareThreatLevel = 0; } if (m_e_flocks == 2) { int c = (int)(255*m_bc.scareRatio); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere( m_bc.scarePoint,m_bc.scareRadius,ColorB(c,0,0,c),false ); } } ////////////////////////////////////////////////////////////////////////// UpdateBoidCollisions(); Vec3 entityPos = m_pEntity->GetWorldPos(); Matrix34 boidTM; int num = 0; for (Boids::iterator it = m_boids.begin(); it != m_boids.end(); ++it,num++) { if (num > numBoids) break; CBoidObject* boid = *it; m_bc.terrainZ = m_bc.engine->GetTerrainElevation(boid->m_pos.x,boid->m_pos.y); boid->Update(dt,m_bc); if (!boid->m_physicsControlled && !boid->m_dead) { IEntity *pBoidEntity = gEnv->pEntitySystem->GetEntity(boid->m_entity); if (pBoidEntity) { Quat q(IDENTITY); boid->CalcOrientation(q); const Vec3 scaleVector(boid->m_scale,boid->m_scale,boid->m_scale); pBoidEntity->SetPosRotScale( boid->m_pos, q, scaleVector, ENTITY_XFORM_NO_SEND_TO_ENTITY_SYSTEM ); } } } m_updateFrameID = gEnv->pRenderer->GetFrameID(false); //gEnv->pLog->Log( "Birds Update" ); }