void Vision::feel_vision_query (Fmatrix& mFull, Fvector& P) { CFrustum Frustum ; Frustum.CreateFromMatrix (mFull,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); // Traverse object database r_spatial.clear_not_free (); g_SpatialSpace->q_frustum ( r_spatial, 0, STYPE_VISIBLEFORAI, Frustum ); // Determine visibility for dynamic part of scene seen.clear_and_reserve () ; for (u32 o_it=0; o_it<r_spatial.size(); o_it++) { ISpatial* spatial = r_spatial [o_it]; CObject* object = spatial->dcast_CObject (); if (object && feel_vision_isRelevant(object)) seen.push_back (object); } if (seen.size()>1) { std::sort (seen.begin(),seen.end()); xr_vector<CObject*>::iterator end = std::unique (seen.begin(),seen.end()); if (end!=seen.end()) seen.erase (end,seen.end()); } }
void CActor::Check_for_AutoPickUp() { // mp only if (!psActorFlags.test(AF_AUTOPICKUP)) return; if (IsGameTypeSingle()) return; if (Level().CurrentControlEntity() != this) return; if (!g_Alive()) return; Fvector bc; bc.add (Position(), m_AutoPickUp_AABB_Offset); Fbox APU_Box; APU_Box.set (Fvector().sub(bc, m_AutoPickUp_AABB), Fvector().add(bc, m_AutoPickUp_AABB)); xr_vector<ISpatial*> ISpatialResult; g_SpatialSpace->q_box (ISpatialResult, 0, STYPE_COLLIDEABLE, bc, m_AutoPickUp_AABB); // Determine visibility for dynamic part of scene for (u32 o_it=0; o_it<ISpatialResult.size(); o_it++) { ISpatial* spatial = ISpatialResult[o_it]; CInventoryItem* pIItem = smart_cast<CInventoryItem*> (spatial->dcast_CObject()); if (0 == pIItem) continue; if (!pIItem->CanTake()) continue; if (Level().m_feel_deny.is_object_denied(spatial->dcast_CObject()) ) continue; CGrenade* pGrenade = smart_cast<CGrenade*> (pIItem); if (pGrenade) continue; if (APU_Box.Pick(pIItem->object().Position(), pIItem->object().Position())) { if (GameID() == eGameIDDeathmatch || GameID() == eGameIDTeamDeathmatch) { if (pIItem->BaseSlot() == INV_SLOT_2 || pIItem->BaseSlot() == INV_SLOT_3 ) { if (inventory().ItemFromSlot(pIItem->BaseSlot())) continue; } } Game().SendPickUpEvent(ID(), pIItem->object().ID()); } } }
BOOL CObjectSpace::_RayPick ( const Fvector &start, const Fvector &dir, float range, rq_target tgt, rq_result& R, CObject* ignore_object) { r_temp.r_clear (); R.O = 0; R.range = range; R.element = -1; // static test if (tgt&rqtStatic){ xrc.ray_options (CDB::OPT_ONLYNEAREST | CDB::OPT_CULL); xrc.ray_query (&Static,start,dir,range); if (xrc.r_count()) R.set_if_less(xrc.r_begin()); } // dynamic test if (tgt&rqtDyn){ collide::ray_defs Q (start,dir,R.range,CDB::OPT_ONLYNEAREST|CDB::OPT_CULL,tgt); // traverse object database u32 d_flags = STYPE_COLLIDEABLE|((tgt&rqtObstacle)?STYPE_OBSTACLE:0)|((tgt&rqtShape)?STYPE_SHAPE:0); g_SpatialSpace->q_ray (r_spatial,0,d_flags,start,dir,range); // Determine visibility for dynamic part of scene for (u32 o_it=0; o_it<r_spatial.size(); o_it++){ ISpatial* spatial = r_spatial[o_it]; CObject* collidable = spatial->dcast_CObject(); if (0==collidable) continue; if (collidable==ignore_object) continue; ECollisionFormType tp = collidable->collidable.model->Type(); if (((tgt&(rqtObject|rqtObstacle))&&(tp==cftObject))||((tgt&rqtShape)&&(tp==cftShape))){ u32 C = D3DCOLOR_XRGB (64,64,64); Q.range = R.range; if (collidable->collidable.model->_RayQuery(Q,r_temp)){ C = D3DCOLOR_XRGB(128,128,196); R.set_if_less (r_temp.r_begin()); } #ifdef DEBUG if (bDebug){ Fsphere S; S.P = spatial->spatial.sphere.P; S.R = spatial->spatial.sphere.R; m_pRender->dbgAddSphere(S,C); //dbg_S.push_back (mk_pair(S,C)); } #endif } } } return (R.element>=0); }
void CActor::PickupModeUpdate_COD () { if (Level().CurrentViewEntity() != this || !g_b_COD_PickUpMode) return; if (!g_Alive() || eacFirstEye != cam_active) { CurrentGameUI()->UIMainIngameWnd->SetPickUpItem(NULL); return; }; CFrustum frustum; frustum.CreateFromMatrix (Device.mFullTransform, FRUSTUM_P_LRTB|FRUSTUM_P_FAR); ISpatialResult.clear_not_free (); g_SpatialSpace->q_frustum (ISpatialResult, 0, STYPE_COLLIDEABLE, frustum); float maxlen = 1000.0f; CInventoryItem* pNearestItem = NULL; for (u32 o_it=0; o_it<ISpatialResult.size(); o_it++) { ISpatial* spatial = ISpatialResult[o_it]; CInventoryItem* pIItem = smart_cast<CInventoryItem*> (spatial->dcast_CObject ()); if (0 == pIItem) continue; if (pIItem->object().H_Parent() != NULL) continue; if (!pIItem->CanTake()) continue; if ( smart_cast<CExplosiveRocket*>( &pIItem->object() ) ) continue; CGrenade* pGrenade = smart_cast<CGrenade*> (spatial->dcast_CObject ()); if (pGrenade && !pGrenade->Useful()) continue; CMissile* pMissile = smart_cast<CMissile*> (spatial->dcast_CObject ()); if (pMissile && !pMissile->Useful()) continue; Fvector A, B, tmp; pIItem->object().Center (A); if (A.distance_to_sqr(Position())>4) continue; tmp.sub(A, cam_Active()->vPosition); B.mad(cam_Active()->vPosition, cam_Active()->vDirection, tmp.dotproduct(cam_Active()->vDirection)); float len = B.distance_to_sqr(A); if (len > 1) continue; if (maxlen>len && !pIItem->object().getDestroy()) { maxlen = len; pNearestItem = pIItem; }; } if(pNearestItem) { CFrustum frustum; frustum.CreateFromMatrix (Device.mFullTransform,FRUSTUM_P_LRTB|FRUSTUM_P_FAR); if (!CanPickItem(frustum, Device.vCameraPosition, &pNearestItem->object())) pNearestItem = NULL; } if (pNearestItem && pNearestItem->cast_game_object()) { if (Level().m_feel_deny.is_object_denied(pNearestItem->cast_game_object())) pNearestItem = NULL; } if (pNearestItem && pNearestItem->cast_game_object()) { if(!pNearestItem->cast_game_object()->getVisible()) pNearestItem = NULL; } CurrentGameUI()->UIMainIngameWnd->SetPickUpItem(pNearestItem); if (pNearestItem && m_bPickupMode) { CUsableScriptObject* pUsableObject = smart_cast<CUsableScriptObject*>(pNearestItem); if(pUsableObject && (!m_pUsableObject)) pUsableObject->use(this); //подбирание объекта Game().SendPickUpEvent(ID(), pNearestItem->object().ID()); } };
BOOL CObjectSpace::_RayTest ( const Fvector &start, const Fvector &dir, float range, collide::rq_target tgt, collide::ray_cache* cache, CObject* ignore_object) { VERIFY (_abs(dir.magnitude()-1)<EPS); r_temp.r_clear (); xrc.ray_options (CDB::OPT_ONLYFIRST); collide::ray_defs Q (start,dir,range,CDB::OPT_ONLYFIRST,tgt); // dynamic test if (tgt&rqtDyn){ u32 d_flags = STYPE_COLLIDEABLE|((tgt&rqtObstacle)?STYPE_OBSTACLE:0)|((tgt&rqtShape)?STYPE_SHAPE:0); // traverse object database g_SpatialSpace->q_ray (r_spatial,0,d_flags,start,dir,range); // Determine visibility for dynamic part of scene for (u32 o_it=0; o_it<r_spatial.size(); o_it++) { ISpatial* spatial = r_spatial[o_it]; CObject* collidable = spatial->dcast_CObject (); if (collidable && (collidable!=ignore_object)) { ECollisionFormType tp = collidable->collidable.model->Type(); if ((tgt&(rqtObject|rqtObstacle))&&(tp==cftObject)&&collidable->collidable.model->_RayQuery(Q,r_temp)) return TRUE; if ((tgt&rqtShape)&&(tp==cftShape)&&collidable->collidable.model->_RayQuery(Q,r_temp)) return TRUE; } } } // static test if (tgt&rqtStatic){ // If we get here - test static model if (cache) { // 0. similar query??? if (cache->similar(start,dir,range)) { return cache->result; } // 1. Check cached polygon float _u,_v,_range; if (CDB::TestRayTri(start,dir,cache->verts,_u,_v,_range,false)) { if (_range>0 && _range<range) return TRUE; } // 2. Polygon doesn't pick - real database query xrc.ray_query (&Static,start,dir,range); if (0==xrc.r_count()) { cache->set (start,dir,range,FALSE); return FALSE; } else { // cache polygon cache->set (start,dir,range,TRUE); CDB::RESULT* R = xrc.r_begin(); CDB::TRI& T = Static.get_tris() [ R->id ]; Fvector* V = Static.get_verts(); cache->verts[0].set (V[T.verts[0]]); cache->verts[1].set (V[T.verts[1]]); cache->verts[2].set (V[T.verts[2]]); return TRUE; } } else { xrc.ray_query (&Static,start,dir,range); return xrc.r_count (); } } return FALSE; }
void CExplosive::Explode() { VERIFY(0xffff != Initiator()); VERIFY(m_explosion_flags.test(flReadyToExplode));//m_bReadyToExplode VERIFY(!ph_world->Processing()); //m_bExploding = true; m_explosion_flags.set(flExploding,TRUE); cast_game_object()->processing_activate(); Fvector& pos = m_vExplodePos; Fvector& dir = m_vExplodeDir; #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { DBG_OpenCashedDraw(); DBG_DrawPoint(pos,0.3f,D3DCOLOR_XRGB(255,0,0)); } #endif // Msg("---------CExplosive Explode [%d] frame[%d]",cast_game_object()->ID(), Device.dwFrame); OnBeforeExplosion(); //играем звук взрыва Sound->play_at_pos(sndExplode, 0, pos, false); //показываем эффекты m_wallmark_manager.PlaceWallmarks (pos); Fvector vel; smart_cast<CPhysicsShellHolder*>(cast_game_object())->PHGetLinearVell(vel); Fmatrix explode_matrix; explode_matrix.identity(); explode_matrix.j.set(dir); Fvector::generate_orthonormal_basis(explode_matrix.j, explode_matrix.i, explode_matrix.k); explode_matrix.c.set(pos); CParticlesObject* pStaticPG; pStaticPG = CParticlesObject::Create(*m_sExplodeParticles,!m_bDynamicParticles); if (m_bDynamicParticles) m_pExpParticle = pStaticPG; pStaticPG->UpdateParent(explode_matrix,vel); pStaticPG->Play(); //включаем подсветку от взрыва StartLight(); //trace frags Fvector frag_dir; ////////////////////////////// //осколки ////////////////////////////// //------------------------------------- bool SendHits = false; if (OnServer()) SendHits = true; else SendHits = false; for(int i = 0; i < m_iFragsNum; ++i){ frag_dir.random_dir (); frag_dir.normalize (); CCartridge cartridge; cartridge.m_kDist = 1.f; cartridge.m_kHit = 1.f; cartridge.m_kImpulse = 1.f; cartridge.m_kPierce = 1.f; cartridge.fWallmarkSize = fWallmarkSize; cartridge.bullet_material_idx = GMLib.GetMaterialIdx(WEAPON_MATERIAL_NAME); cartridge.m_flags.set (CCartridge::cfTracer,FALSE); Level().BulletManager().AddBullet( pos, frag_dir, m_fFragmentSpeed, m_fFragHit, m_fFragHitImpulse, Initiator(), cast_game_object()->ID(), m_eHitTypeFrag, m_fFragsRadius, cartridge, SendHits ); } if (cast_game_object()->Remote()) return; ///////////////////////////////// //взрывная волна //////////////////////////////// //--------------------------------------------------------------------- xr_vector<ISpatial*> ISpatialResult; g_SpatialSpace->q_sphere(ISpatialResult,0,STYPE_COLLIDEABLE,pos,m_fBlastRadius); m_blasted_objects.clear (); for (u32 o_it=0; o_it<ISpatialResult.size(); o_it++) { ISpatial* spatial = ISpatialResult[o_it]; // feel_touch_new(spatial->dcast_CObject()); CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>(spatial->dcast_CObject()); if(pGameObject && cast_game_object()->ID() != pGameObject->ID()) m_blasted_objects.push_back(pGameObject); } GetExplosionBox(m_vExplodeSize); START_PROFILE("explosive/activate explosion box") ActivateExplosionBox(m_vExplodeSize,m_vExplodePos); STOP_PROFILE //--------------------------------------------------------------------- #ifdef DEBUG if(ph_dbg_draw_mask.test(phDbgDrawExplosions)) { DBG_ClosedCashedDraw(100000); } #endif ////////////////////////////////////////////////////////////////////////// // Explode Effector ////////////// CGameObject* GO = smart_cast<CGameObject*>(Level().CurrentEntity()); CActor* pActor = smart_cast<CActor*>(GO); if(pActor) { float dist_to_actor = pActor->Position().distance_to(pos); float max_dist = EFFECTOR_RADIUS; if (dist_to_actor < max_dist) AddEffector (pActor, effExplodeHit, effector.effect_sect_name, (max_dist - dist_to_actor) / max_dist ); } }