void CControlManagerCustom::check_jump_over_physics()
{
	if (!m_man->path_builder().is_moving_on_path()) return;
	if (!m_man->check_start_conditions(ControlCom::eControlJump)) return;
	if (!m_object->check_start_conditions(ControlCom::eControlJump)) return;
	if (m_object->GetScriptControl()) return;

	Fvector prev_pos	= m_object->Position();
	float	dist_sum	= 0.f;

	for(u32 i = m_man->path_builder().detail().curr_travel_point_index(); i<m_man->path_builder().detail().path().size();i++) {
		const DetailPathManager::STravelPathPoint &travel_point = m_man->path_builder().detail().path()[i];

		// получить список объектов вокруг врага
		m_nearest.clear_not_free		();
		Level().ObjectSpace.GetNearest	(m_nearest,travel_point.position, m_object->Radius(), NULL);

		for (u32 k=0;k<m_nearest.size();k++) {
			CPhysicsShellHolder *obj = smart_cast<CPhysicsShellHolder *>(m_nearest[k]);
			if (!obj || !obj->PPhysicsShell() || !obj->PPhysicsShell()->isActive() || (obj->Radius() < 0.5f)) continue;
			if (m_object->Position().distance_to(obj->Position()) < MAX_DIST_SUM / 2) continue;

			Fvector dir = Fvector().sub(travel_point.position, m_object->Position());

			// проверка на  Field-Of-View
			float	my_h	= m_object->Direction().getH();
			float	h		= dir.getH();

			float from	= angle_normalize(my_h - deg(8));
			float to	= angle_normalize(my_h + deg(8));

			if (!is_angle_between(h, from, to)) continue;

			dir = Fvector().sub(obj->Position(), m_object->Position());

			// вычислить целевую позицию для прыжка
			Fvector target;
			obj->Center(target);
			target.y += obj->Radius();
			// --------------------------------------------------------

			m_jump->setup_data().flags.set			(SControlJumpData::ePrepareSkip, true);
			m_jump->setup_data().target_object		= 0;
			m_jump->setup_data().target_position	= target;

			jump(m_jump->setup_data());

			return;
		}

		dist_sum += prev_pos.distance_to(travel_point.position);
		if (dist_sum > MAX_DIST_SUM) break;

		prev_pos = travel_point.position;
	}
}
Beispiel #2
0
void CBaseGraviZone ::Affect(SZoneObjectInfo* O) 
{
	CPhysicsShellHolder* GO = smart_cast<CPhysicsShellHolder*>(O->object);
	if(!GO) return;


	//////////////////////////////////////////////////////////////////////////
	//	зат¤гиваем объет по направлению к центру зоны

	Fvector					throw_in_dir;
	Fvector					zone_center;
	ThrowInCenter			(zone_center);
	Fvector					go_center;
	GO->Center				(go_center);
	throw_in_dir.sub		(zone_center, go_center);

	float dist				= throw_in_dir.magnitude();
	float dist_to_radius	= dist/Radius();

	if(!fis_zero(dist))
		throw_in_dir.mul(1.f/dist);
	else 
		throw_in_dir.set(0.f,1.f,0.f);

	bool CanApplyPhisImpulse = GO->Local() == TRUE;

	if( CheckAffectField(GO,dist_to_radius)&& CanApplyPhisImpulse)
	{
		AffectPull(GO,throw_in_dir,dist);
	}
	else
	{
		//////////////////////////////////////////////////////////////////////////
		// выброс аномалии
		
		//если врем¤ выброса еще не пришло
		if(m_dwBlowoutExplosionTime<(u32)m_iPreviousStateTime ||
			m_dwBlowoutExplosionTime>=(u32)m_iStateTime)
		{

			AffectPull(GO,throw_in_dir,BlowoutRadiusPercent(GO)*Radius());	
			return;
		}
		AffectThrow(O,GO,throw_in_dir,dist);
			
	}
}
void CBlackGraviArtefact::GraviStrike()
{
	xr_list<s16>		elements_list;
	xr_list<Fvector>	bone_position_list;

	Fvector object_pos					; 
	Fvector strike_dir					;

	rq_storage.r_clear	();

	for(GAME_OBJECT_LIST_it it = m_GameObjectList.begin(); 
						    m_GameObjectList.end() != it;
							++it)
	{
		CPhysicsShellHolder* pGameObject = *it;

		if(pGameObject->Visual()) 
			pGameObject->Center(object_pos); 
		else 
			object_pos.set(pGameObject->Position());

		strike_dir.sub(object_pos, Position()); 
		float distance = strike_dir.magnitude(); 

		float impulse = 100.f*m_fStrikeImpulse * (1.f - (distance/m_fRadius)*
										   (distance/m_fRadius));
						
		if(impulse > .001f) 
		{
//?			BOOL		enabled = getEnabled();
//?			setEnabled	(FALSE);
			impulse		*= CExplosive::ExplosionEffect	(rq_storage,NULL,pGameObject, Position(),m_fRadius);
//?			setEnabled	(enabled);
		}

		float hit_power		;
		CEntityAlive* pEntityAlive = smart_cast<CEntityAlive*>(pGameObject);
		if(pGameObject->m_pPhysicsShell)	hit_power = 0;
		else if(pEntityAlive && pEntityAlive->g_Alive() && 
				pEntityAlive->character_physics_support()->movement()->CharacterExist())
			hit_power = 0;
		else
			hit_power = impulse;

		
		if(impulse > .001f) 
		{
			while(!elements_list.empty()) 
			{
				s16 element = elements_list.front();
				Fvector bone_pos = bone_position_list.front();
				
				NET_Packet		P;
				SHit	HS;
				HS.GenHeader(GE_HIT, pGameObject->ID());	//				u_EventGen		(P,GE_HIT, pGameObject->ID());				
				HS.whoID  =ID();							//				P.w_u16			(ID());
				HS.weaponID = ID();							//				P.w_u16			(ID());
				HS.dir = strike_dir;						//				P.w_dir			(strike_dir);
				HS.power = hit_power;						//				P.w_float		(hit_power);
				HS.boneID = element;						//				P.w_s16			(element);
				HS.p_in_bone_space = bone_pos;				//				P.w_vec3		(bone_pos);
				HS.impulse = impulse;						//				P.w_float		(impulse);
				HS.hit_type = (ALife::eHitTypeWound);		//				P.w_u16			(u16(ALife::eHitTypeWound));
				HS.Write_Packet(P);

				u_EventSend		(P);
				elements_list.pop_front();
				bone_position_list.pop_front();
			}
		}
	}
}