void CTeamBaseZone::OnRender() { if(!bDebug) return; if (!(dbg_net_Draw_Flags.is_any((1<<3)))) return; // RCache.OnFrameEnd(); Fvector l_half; l_half.set(.5f, .5f, .5f); Fmatrix l_ball, l_box; xr_vector<CCF_Shape::shape_def> &l_shapes = ((CCF_Shape*)CFORM())->Shapes(); xr_vector<CCF_Shape::shape_def>::iterator l_pShape; for(l_pShape = l_shapes.begin(); l_shapes.end() != l_pShape; ++l_pShape) { switch(l_pShape->type) { case 0: { Fsphere &l_sphere = l_pShape->data.sphere; l_ball.scale(l_sphere.R, l_sphere.R, l_sphere.R); Fvector l_p; XFORM().transform(l_p, l_sphere.P); l_ball.translate_add(l_p); Level().debug_renderer().draw_ellipse(l_ball, D3DCOLOR_XRGB(0,255,255)); } break; case 1: { l_box.mul(XFORM(), l_pShape->data.box); Level().debug_renderer().draw_obb(l_box, l_half, D3DCOLOR_XRGB(0,255,255)); } break; } } }
void CMosquitoBald::Affect(SZoneObjectInfo* O) { CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>(O->object); if(!pGameObject) return; if(O->zone_ignore) return; Fvector P; XFORM().transform_tiny(P,CFORM()->getSphere().P); Fvector hit_dir; hit_dir.set( ::Random.randF(-.5f,.5f), ::Random.randF(.0f,1.f), ::Random.randF(-.5f,.5f)); hit_dir.normalize(); Fvector position_in_bone_space; VERIFY(!pGameObject->getDestroy()); float dist = pGameObject->Position().distance_to(P) - pGameObject->Radius(); float power = Power(dist>0.f?dist:0.f, Radius()); float impulse = m_fHitImpulseScale*power*pGameObject->GetMass(); if(power > 0.01f) { position_in_bone_space.set(0.f,0.f,0.f); CreateHit(pGameObject->ID(),ID(),hit_dir,power,0,position_in_bone_space,impulse,m_eHitTypeBlowout); PlayHitParticles(pGameObject); } }
void CRadioactiveZone::Affect(SZoneObjectInfo* O) { // вермя срабатывания не чаще, чем заданный период if(m_dwDeltaTime < m_dwPeriod) return; //. m_dwDeltaTime = 0; CGameObject *GO = O->object; if(GO) { Fvector pos; XFORM().transform_tiny(pos,CFORM()->getSphere().P); #ifdef DEBUG char pow[255]; sprintf(pow, "zone hit. %.3f", Power(GO->Position().distance_to(pos))); if(bDebug) Msg("%s %s", *GO->cName(), pow); #endif Fvector dir; dir.set(0,0,0); Fvector position_in_bone_space; float power = (GameID() == GAME_SINGLE) ? Power(GO->Position().distance_to(pos)) : 0.0f; float impulse = 0.f; if(power > EPS) { //. m_dwDeltaTime = 0; position_in_bone_space.set(0.f,0.f,0.f); CreateHit(GO->ID(),ID(),dir,power,BI_NONE,position_in_bone_space,impulse,ALife::eHitTypeRadiation); } } }
float CAmebaZone::distance_to_center(CObject* O) { Fvector P; XFORM().transform_tiny(P,CFORM()->getSphere().P); Fvector OP;OP.set(O->Position()); return _sqrt((P.x-OP.x)*(P.x-OP.x)+(P.x-OP.x)*(P.x-OP.x)); }
void CCustomZone::PlayBoltEntranceParticles() { CCF_Shape* Sh = (CCF_Shape*)CFORM(); const Fmatrix& XF = XFORM(); Fmatrix PXF; xr_vector<CCF_Shape::shape_def>& Shapes = Sh->Shapes(); Fvector sP0, sP1, vel; CParticlesObject* pParticles = NULL; xr_vector<CCF_Shape::shape_def>::iterator it = Shapes.begin(); xr_vector<CCF_Shape::shape_def>::iterator it_e = Shapes.end(); for(;it!=it_e;++it) { CCF_Shape::shape_def& s = *it; switch (s.type) { case 0: // sphere { sP0 = s.data.sphere.P; XF.transform_tiny (sP0); float ki = 10.0f * s.data.sphere.R; float c = 2.0f * s.data.sphere.R; float quant_h = (PI_MUL_2/float(ki))*c; float quant_p = (PI_DIV_2/float(ki)); for(float i=0; i<ki; ++i) { vel.setHP ( ::Random.randF(quant_h/2.0f, quant_h)*i, ::Random.randF(quant_p/2.0f, quant_p)*i ); vel.mul (s.data.sphere.R); sP1.add (sP0, vel); PXF.identity (); PXF.k.normalize (vel); Fvector::generate_orthonormal_basis(PXF.k, PXF.j, PXF.i); PXF.c = sP1; pParticles = CParticlesObject::Create(m_sBoltEntranceParticles.c_str(), TRUE); pParticles->UpdateParent(PXF,vel); pParticles->Play (false); } }break; case 1: // box break; } } }
void CTeamBaseZone::shedule_Update(u32 dt) { inherited::shedule_Update (dt); const Fsphere &s = CFORM()->getSphere(); Fvector P; XFORM().transform_tiny (P,s.P); feel_touch_update (P,s.R); }
BOOL CRadioactiveZone::feel_touch_contact(CObject* O) { CActor* A = smart_cast<CActor*>(O); if ( A ) { if (!((CCF_Shape*)CFORM())->Contact(O)) return FALSE; return A->feel_touch_on_contact(this); }else return FALSE; }
void CLevelChanger::shedule_Update(u32 dt) { inherited::shedule_Update (dt); const Fsphere &s = CFORM()->getSphere(); Fvector P; XFORM().transform_tiny (P,s.P); feel_touch_update (P,s.R); update_actor_invitation (); }
float CRadioactiveZone::nearest_shape_radius(SZoneObjectInfo* O) { CCF_Shape* Sh = (CCF_Shape*)CFORM(); if(Sh->Shapes().size()==1) { return Radius(); }else { xr_vector<CCF_Shape::shape_def>& Shapes = Sh->Shapes(); CCF_Shape::shape_def& s = Shapes[0]; return s.data.sphere.R; } }
BOOL CLevelChanger::net_Spawn (CSE_Abstract* DC) { m_entrance_time = 0; CCF_Shape *l_pShape = xr_new<CCF_Shape>(this); collidable.model = l_pShape; CSE_Abstract *l_tpAbstract = (CSE_Abstract*)(DC); CSE_ALifeLevelChanger *l_tpALifeLevelChanger = smart_cast<CSE_ALifeLevelChanger*>(l_tpAbstract); R_ASSERT (l_tpALifeLevelChanger); m_game_vertex_id = l_tpALifeLevelChanger->m_tNextGraphID; m_level_vertex_id = l_tpALifeLevelChanger->m_dwNextNodeID; m_position = l_tpALifeLevelChanger->m_tNextPosition; m_angles = l_tpALifeLevelChanger->m_tAngles; m_bSilentMode = !!l_tpALifeLevelChanger->m_bSilentMode; if (ai().get_level_graph()) { //. this information should be computed in xrAI ai_location().level_vertex (ai().level_graph().vertex(u32(-1),Position())); ai_location().game_vertex (ai().cross_table().vertex(ai_location().level_vertex_id()).game_vertex_id()); } feel_touch.clear (); for (u32 i=0; i < l_tpALifeLevelChanger->shapes.size(); ++i) { CSE_Shape::shape_def &S = l_tpALifeLevelChanger->shapes[i]; switch (S.type) { case 0 : { l_pShape->add_sphere(S.data.sphere); break; } case 1 : { l_pShape->add_box(S.data.box); break; } } } BOOL bOk = inherited::net_Spawn(DC); if (bOk) { l_pShape->ComputeBounds (); Fvector P; XFORM().transform_tiny (P,CFORM()->getSphere().P); setEnabled (TRUE); } g_lchangers.push_back (this); return (bOk); }
void CRadioactiveZone::Affect(SZoneObjectInfo* O) { float one = 0.1f; float tg = Device.fTimeGlobal; if(!O->object || O->f_time_affected+one > Device.fTimeGlobal) return; clamp (O->f_time_affected, tg-(one*3), tg); Fvector pos; XFORM().transform_tiny (pos,CFORM()->getSphere().P); Fvector dir ={0,0,0}; float power = Power(O->object->Position().distance_to(pos),nearest_shape_radius(O)); float impulse = 0.0f; if(power < EPS) { O->f_time_affected = tg; return; } float send_power = power*one; while(O->f_time_affected+one < tg) { CreateHit ( O->object->ID(), ID(), dir, send_power, BI_NONE, Fvector().set(0.0f,0.0f,0.0f), impulse, m_eHitTypeBlowout); #ifdef DEBUG // if(bDebug) /* Msg ( "Zone[%s]-hit->[%s] Power=%3.3f Frame=%d Time=%3.3f", cName().c_str(), O->object->cName().c_str(), send_power, Device.dwFrame, tg);*/ /// Msg( "Zone hit ___ damage = %.4f Frame=%d ", send_power, Device.dwFrame ); #endif O->f_time_affected += one; }//while }
void CMosquitoBald::Affect(SZoneObjectInfo* O) { CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>(O->object); if(!pGameObject) return; if(O->zone_ignore) return; Fvector P; XFORM().transform_tiny(P,CFORM()->getSphere().P); #ifdef DEBUG char l_pow[255]; sprintf_s(l_pow, "zone hit. %.1f", Power(pGameObject->Position().distance_to(P))); if(bDebug) Msg("%s %s",*pGameObject->cName(), l_pow); #endif Fvector hit_dir; hit_dir.set(::Random.randF(-.5f,.5f), ::Random.randF(.0f,1.f), ::Random.randF(-.5f,.5f)); hit_dir.normalize(); Fvector position_in_bone_space; VERIFY(!pGameObject->getDestroy()); float dist = pGameObject->Position().distance_to(P) - pGameObject->Radius(); float power = Power(dist>0.f?dist:0.f); float impulse = m_fHitImpulseScale*power*pGameObject->GetMass(); //статистика по объекту O->total_damage += power; O->hit_num++; if(power > 0.01f) { m_dwDeltaTime = 0; position_in_bone_space.set(0.f,0.f,0.f); CreateHit(pGameObject->ID(),ID(),hit_dir,power,0,position_in_bone_space,impulse,m_eHitTypeBlowout); PlayHitParticles(pGameObject); } }
BOOL CTeamBaseZone::net_Spawn (CSE_Abstract* DC) { CCF_Shape *l_pShape = xr_new<CCF_Shape>(this); collidable.model = l_pShape; CSE_Abstract *l_tpAbstract = (CSE_Abstract*)(DC); CSE_ALifeTeamBaseZone *l_tpALifeScriptZone = smart_cast<CSE_ALifeTeamBaseZone*>(l_tpAbstract); R_ASSERT (l_tpALifeScriptZone); feel_touch.clear (); for (u32 i=0; i < l_tpALifeScriptZone->shapes.size(); ++i) { CSE_Shape::shape_def &S = l_tpALifeScriptZone->shapes[i]; switch (S.type) { case 0 : { l_pShape->add_sphere(S.data.sphere); break; } case 1 : { l_pShape->add_box(S.data.box); break; } } } m_Team = l_tpALifeScriptZone->m_team; BOOL bOk = inherited::net_Spawn(DC); if (bOk) { l_pShape->ComputeBounds (); Fvector P; XFORM().transform_tiny (P,CFORM()->getSphere().P); setEnabled (TRUE); } if (GameID() != GAME_SINGLE && !g_dedicated_server) { char BaseMapLocation[1024]; sprintf_s (BaseMapLocation, "mp_team_base_%d_location", m_Team); (Level().MapManager().AddMapLocation(BaseMapLocation,ID()))->EnablePointer(); }; return (bOk); }
BOOL CCustomZone::feel_touch_contact(CObject* O) { if (smart_cast<CCustomZone*>(O)) return FALSE; if (smart_cast<CBreakableObject*>(O)) return FALSE; if (0==smart_cast<IKinematics*>(O->Visual())) return FALSE; if (O->ID() == ID()) return (FALSE); CGameObject *object = smart_cast<CGameObject*>(O); if (!object || !object->IsVisibleForZones()) return (FALSE); if (!((CCF_Shape*)CFORM())->Contact(O)) return (FALSE); return (object->feel_touch_on_contact(this)); }
void CMosquitoBald::UpdateSecondaryHit() { if(m_dwAffectFrameNum == Device.dwFrame) return; m_dwAffectFrameNum = Device.dwFrame; if(Device.dwPrecacheFrame) return; OBJECT_INFO_VEC_IT it; for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) { if(!(*it).object->getDestroy()) { CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>((&(*it))->object); if(!pGameObject) return; if((&(*it))->zone_ignore) return; Fvector P; XFORM().transform_tiny(P,CFORM()->getSphere().P); Fvector hit_dir; hit_dir.set( ::Random.randF(-.5f,.5f), ::Random.randF(.0f,1.f), ::Random.randF(-.5f,.5f)); hit_dir.normalize(); Fvector position_in_bone_space; VERIFY(!pGameObject->getDestroy()); float dist = pGameObject->Position().distance_to(P) - pGameObject->Radius(); float power = m_fSecondaryHitPower * RelativePower(dist>0.f?dist:0.f, Radius()); if(power<0.0f) return; float impulse = m_fHitImpulseScale*power*pGameObject->GetMass(); position_in_bone_space.set(0.f,0.f,0.f); CreateHit(pGameObject->ID(),ID(),hit_dir,power,0,position_in_bone_space,impulse,m_eHitTypeBlowout); } } }
void CRadioactiveZone::UpdateWorkload (u32 dt) { if (IsEnabled() && GameID() != GAME_SINGLE) { OBJECT_INFO_VEC_IT it; Fvector pos; XFORM().transform_tiny(pos,CFORM()->getSphere().P); for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) { if( !(*it).object->getDestroy() && (*it).object->CLS_ID == CLSID_OBJECT_ACTOR) { //===================================== NET_Packet l_P; l_P.write_start(); l_P.read_start(); float dist = (*it).object->Position().distance_to(pos); float power = Power(dist)*dt/1000; /// Msg("Zone Dist %f, Radiation Power %f, ", dist, power); SHit HS; HS.GenHeader(GE_HIT, (*it).object->ID()); HS.whoID =ID(); HS.weaponID = ID(); HS.dir = Fvector().set(0,0,0); HS.power = power; HS.boneID = BI_NONE; HS.p_in_bone_space = Fvector().set(0, 0, 0); HS.impulse = 0.0f; HS.hit_type = ALife::eHitTypeRadiation; HS.Write_Packet_Cont(l_P); (*it).object->OnEvent(l_P, HS.PACKET_TYPE); //===================================== }; } } inherited::UpdateWorkload(dt); }
void CRadioactiveZone::UpdateWorkload (u32 dt) { if (IsEnabled() && GameID() != eGameIDSingle) { OBJECT_INFO_VEC_IT it; Fvector pos; XFORM().transform_tiny(pos,CFORM()->getSphere().P); for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) { if( !(*it).object->getDestroy() && smart_cast<CActor*>((*it).object)) { //===================================== NET_Packet l_P; l_P.write_start(); l_P.read_start(); float dist = (*it).object->Position().distance_to(pos); float power = Power(dist,nearest_shape_radius(it))*dt/1000; SHit HS; HS.GenHeader (GE_HIT, (*it).object->ID()); HS.whoID = ID(); HS.weaponID = ID(); HS.dir = Fvector().set(0,0,0); HS.power = power; HS.boneID = BI_NONE; HS.p_in_bone_space = Fvector().set(0, 0, 0); HS.impulse = 0.0f; HS.hit_type = m_eHitTypeBlowout; HS.Write_Packet_Cont(l_P); (*it).object->OnEvent(l_P, HS.PACKET_TYPE); //===================================== }; } } inherited::UpdateWorkload(dt); }
float CLevelChanger::Radius () const { return CFORM()->getRadius (); }
// called as usual void CCustomZone::shedule_Update(u32 dt) { m_zone_flags.set(eZoneIsActive, FALSE); if (IsEnabled()) { const Fsphere& s = CFORM()->getSphere(); Fvector P; XFORM().transform_tiny (P,s.P); // update feel_touch_update (P,s.R); //пройтись по всем объектам в зоне //и проверить их состояние for(OBJECT_INFO_VEC_IT it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) { CGameObject* pObject = (*it).object; if (!pObject) continue; CEntityAlive* pEntityAlive = smart_cast<CEntityAlive*>(pObject); SZoneObjectInfo& info = (*it); info.dw_time_in_zone += dt; if((!info.small_object && m_iDisableHitTime != -1 && (int)info.dw_time_in_zone > m_iDisableHitTime) || (info.small_object && m_iDisableHitTimeSmall != -1 && (int)info.dw_time_in_zone > m_iDisableHitTimeSmall)) { if(!pEntityAlive || !pEntityAlive->g_Alive()) info.zone_ignore = true; } if(m_iDisableIdleTime != -1 && (int)info.dw_time_in_zone > m_iDisableIdleTime) { if(!pEntityAlive || !pEntityAlive->g_Alive()) StopObjectIdleParticles( pObject ); } //если есть хотя бы один не дисабленый объект, то //зона считается активной if(info.zone_ignore == false) m_zone_flags.set(eZoneIsActive,TRUE); } if(eZoneStateIdle == m_eZoneState) CheckForAwaking(); inherited::shedule_Update(dt); // check "fast-mode" border float cam_distance = Device.vCameraPosition.distance_to(P)-s.R; if (cam_distance>FASTMODE_DISTANCE && !m_zone_flags.test(eAlwaysFastmode) ) o_switch_2_slow (); else o_switch_2_fast (); if (!m_zone_flags.test(eFastMode)) UpdateWorkload (dt); }; UpdateOnOffState (); if( !IsGameTypeSingle() && Local() ) { if(Device.dwTimeGlobal > m_ttl) DestroyObject (); } }
BOOL CTeamBaseZone::feel_touch_contact (CObject* O) { CActor* pActor = smart_cast<CActor*>(O); if (!pActor) return (FALSE); return ((CCF_Shape*)CFORM())->Contact(O); }
void CLevelChanger::Center (Fvector& C) const { XFORM().transform_tiny (C,CFORM()->getSphere().P); }
void CCustomZone::CalcDistanceTo(const Fvector& P, float& dist, float& radius) { R_ASSERT (CFORM()->Type()==cftShape); CCF_Shape* Sh = (CCF_Shape*)CFORM(); dist = P.distance_to(Position()); float sr = CFORM()->getSphere().R; //quick test if(Sh->Shapes().size()==1) { radius = sr; return; } /* //2nd quick test Fvector SC; float dist2; XF.transform_tiny (SC,CFORM()->getSphere().P); dist2 = P.distance_to(SC); if(dist2>sr) { radius = sr; return; } */ //full test const Fmatrix& XF = XFORM(); xr_vector<CCF_Shape::shape_def>& Shapes = Sh->Shapes(); CCF_Shape::shape_def* nearest_s = NULL; float nearest = flt_max; Fvector sP; xr_vector<CCF_Shape::shape_def>::iterator it = Shapes.begin(); xr_vector<CCF_Shape::shape_def>::iterator it_e = Shapes.end(); for(;it!=it_e;++it) { CCF_Shape::shape_def& s = *it; float d = 0.0f; switch (s.type) { case 0: // sphere sP = s.data.sphere.P; break; case 1: // box sP = s.data.box.c; break; } XF.transform_tiny(sP); d = P.distance_to(sP); if(d<nearest) { nearest = d; nearest_s = &s; } } R_ASSERT(nearest_s); dist = nearest; if(nearest_s->type==0) radius = nearest_s->data.sphere.R; else { float r1 = nearest_s->data.box.i.magnitude(); float r2 = nearest_s->data.box.j.magnitude(); float r3 = nearest_s->data.box.k.magnitude(); radius = _max(r1,r2); radius = _max(radius,r3); } }
float CTeamBaseZone::Radius () const { return (CFORM()->getRadius()); }
void CTeamBaseZone::Center (Fvector &C) const { XFORM().transform_tiny (C,CFORM()->getSphere().P); }
BOOL CLevelChanger::feel_touch_contact (CObject *object) { return (((CCF_Shape*)CFORM())->Contact(object)) && smart_cast<CActor*>(object); }
BOOL CScriptZone::feel_touch_contact (CObject* O) { return (((CCF_Shape*)CFORM())->Contact(O)); }