bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const	
	{
		
		if( H.initiator() !=  Level().CurrentControlEntity())
			return false;

		if(H.type() == ALife::eHitTypeExplosion)
		{
			edirection dr = dir( ea, H, angle );
			m = motion( dr );
			type_motion_diagnostic( "type_motion6: 7. √ранта", dr, ea, H, m );
			return true;
		}

		CObject* O = Level().Objects.net_Find( H.weaponID );
		if(!O)
		{
			m = MotionID();
			return false;
		}

		if( smart_cast<CExplosive*>( O ) != 0 )
		{	
			edirection dr = dir( ea, H, angle );
			m = motion(  dr );
			type_motion_diagnostic( "type_motion6: 7. √ранта - осколок", dr, ea, H, m );
			return true;
		}

		return false;
	}
	bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle )	const
	{
		m = MotionID();
		if( H.initiator() !=  Level().CurrentControlEntity())
			return false;
		
		VERIFY( ea.Visual( ) );
		IKinematics *K = ea.Visual()->dcast_PKinematics();
		VERIFY( K );
		if( !is_bone_head( *K, H.bone() ))
			return false;

		//CAI_Stalker* s = ea.cast_stalker	();
		CCharacterPhysicsSupport* chs = ea.character_physics_support();
		if( !chs || chs->Type( ) == CCharacterPhysicsSupport::etBitting )
			return false;

		VERIFY( chs->movement() );
		
		const Fvector stalker_velocity = chs->movement()->GetVelocity();
		const float stalker_speed = stalker_velocity.magnitude();
		const float min_stalker_speed = 3.65f;
		if(stalker_speed < min_stalker_speed )
			return false;

		const Fvector stalker_velocity_dir = Fvector().mul( stalker_velocity, 1.f/stalker_speed );

		const Fvector dir_to_actor = Fvector().sub( H.initiator()->Position(), ea.Position() ).normalize_safe();

		const float front_angle_cos = _cos( deg2rad ( 20.f ) );
		
		if( stalker_velocity_dir.dotproduct(dir_to_actor) < front_angle_cos )
			return false;

		if( type_motion::front != type_motion::dir( ea, H, angle )  )
			return false;
		Fvector p;
		if( Fvector().sub( H.initiator()->Position(), global_hit_position( p, ea, H ) ).magnitude() > 30.f )
			return false;

		m = motion( front );
		type_motion_diagnostic( " type_motion0: 1. = »нерционное движение вперед от попадани¤ в голову ", front, ea, H, m );
		return true;
	}
	bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const	
	{
		m = MotionID();
		if( H.initiator() !=  Level().CurrentControlEntity())
		return false;
		
		CObject* O = Level().Objects.net_Find( H.weaponID );
		if(!O)
			return false;
		//static_cast<CGameObject*>(O)->cast_weapon()
		CWeaponShotgun* s = smart_cast< CWeaponShotgun* >( static_cast<CGameObject*>(O) );
		if(!s)
			return false;
		Fvector p;
		const	float max_distance = 20.f;
		if(Fvector().sub(H.initiator()->Position(),global_hit_position( p, ea, H )).magnitude() > max_distance)
			return false;
		edirection dr = dir( ea, H, angle );
		m = motion( dr );
		type_motion_diagnostic( " type_motion2: 3.	Ўотган ", dr, ea, H, m );
		return true;
	}
	bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const
	{
		m = MotionID();
		if( H.initiator() !=  Level().CurrentControlEntity())
			return false;
		VERIFY( ea.Visual( ) );
		IKinematics *K = ea.Visual()->dcast_PKinematics();
		VERIFY( K );
		if( is_bone_head( *K, H.bone() ) )
		{
			edirection dr = dir( ea, H, angle );
			m = motion( dr );
			type_motion_diagnostic( " type_motion3: 4.	’едшот (по веро¤тности), кроме 5 (4)", dr, ea, H, m );
			return true;
		}
		return false;
	}
	bool predicate( CEntityAlive& ea, const SHit& H, MotionID &m, float &angle ) const	
	{
		if( H.initiator() !=  Level().CurrentControlEntity())
			return false;
		m = MotionID();
		VERIFY( ea.Visual( ) );
		IKinematics *K = ea.Visual()->dcast_PKinematics();
		VERIFY( K );

		if(is_snipper( H.weaponID ) && !is_bone_head( *K, H.bone() ))
		{
			edirection dr = dir( ea, H, angle );
			m = motion( dr );
			type_motion_diagnostic( "type_motion5: 6.	—найперка в тело", dr, ea, H, m );
			return true;
		}
		return false;
	}
Пример #6
0
void CAI_Stalker::Hit(SHit* pHDS)
{
	//хит может меняться в зависимости от ранга (новички получают больше хита, чем ветераны)
	SHit HDS = *pHDS;
	HDS.add_wound = true;
	
	float hit_power = HDS.power * m_fRankImmunity;

	if(m_boneHitProtection && HDS.hit_type == ALife::eHitTypeFireWound)
	{
		float BoneArmor = m_boneHitProtection->getBoneArmor(HDS.bone());
		float ap = HDS.armor_piercing;
		if(!fis_zero(BoneArmor, EPS))
		{
			if(ap > BoneArmor)
			{
				float d_hit_power = (ap - BoneArmor) / ap;
				if(d_hit_power < m_boneHitProtection->m_fHitFracNpc)
					d_hit_power = m_boneHitProtection->m_fHitFracNpc;

				hit_power *= d_hit_power;
				VERIFY(hit_power>=0.0f);
			}
			else
			{
				hit_power *= m_boneHitProtection->m_fHitFracNpc;
				HDS.add_wound = false;
			}
		}

		if ( wounded() ) //уже лежит => добивание
		{
			hit_power = 1000.f;
		}
	}
	HDS.power = hit_power;

	if (g_Alive())
	{
		bool already_critically_wounded = critically_wounded();

		if (!already_critically_wounded)
		{
			const CCoverPoint		*cover = agent_manager().member().member(this).cover();
			if ( !invulnerable() && cover && HDS.initiator() &&
				( HDS.initiator()->ID() != ID() ) && !fis_zero( HDS.damage() ) && brain().affect_cover() )
			{
				agent_manager().location().add( xr_new<CDangerCoverLocation>(cover,Device.dwTimeGlobal,DANGER_INTERVAL,DANGER_DISTANCE) );
			}
		}

		const CEntityAlive	*entity_alive = smart_cast<const CEntityAlive*>(HDS.initiator());
		if (entity_alive && !wounded()) {
			if (is_relation_enemy(entity_alive))
				sound().play		(eStalkerSoundInjuring);
//			else
//				sound().play		(eStalkerSoundInjuringByFriend);
		}

		int							weapon_type = -1;
		if (best_weapon())
			weapon_type				= best_weapon()->object().ef_weapon_type();

		if	(
				!wounded() &&
				!already_critically_wounded)
		{
			bool					became_critically_wounded = update_critical_wounded(HDS.boneID,HDS.power);
			if	(
				!became_critically_wounded &&
				animation().script_animations().empty() &&
				(HDS.bone() != BI_NONE)
			)
			{
				Fvector					D;
				float					yaw, pitch;
				D.getHP					(yaw,pitch);

	#pragma todo("Dima to Dima : forward-back bone impulse direction has been determined incorrectly!")
				float					power_factor = m_power_fx_factor * HDS.damage() / 100.f;
				clamp					(power_factor,0.f,1.f);

				//IKinematicsAnimated		*tpKinematics = smart_cast<IKinematicsAnimated*>(Visual());
				IKinematics *tpKinematics = smart_cast<IKinematics*>(Visual());
	#ifdef DEBUG
				tpKinematics->LL_GetBoneInstance	(HDS.bone());
				if (HDS.bone() >= tpKinematics->LL_BoneCount()) {
					Msg					("tpKinematics has no bone_id %d",HDS.bone());
					HDS._dump			();
				}
	#endif
//				int						fx_index = iFloor(tpKinematics->LL_GetBoneInstance(HDS.bone()).get_param(1) + (angle_difference(movement().m_body.current.yaw,-yaw) <= PI_DIV_2 ? 0 : 1));
//				if (fx_index != -1)
//					animation().play_fx	(power_factor,fx_index);
			}
			else {
				if (!already_critically_wounded && became_critically_wounded) {
					if (HDS.who) {
						CAI_Stalker		*stalker = smart_cast<CAI_Stalker*>(HDS.who);
						if ( stalker && stalker->g_Alive() )
							stalker->on_critical_wound_initiator	(this);
					}
				}
			}
		}
	}

	if ( g_Alive() && ( !m_hit_callback || m_hit_callback( &HDS ) ) )
	{
		float const damage_factor	= invulnerable() ? 0.f : 100.f;
		memory().hit().add			( damage_factor*HDS.damage(), HDS.direction(), HDS.who, HDS.boneID );
	}

	//conditions().health()			= 1.f;

	inherited::Hit					( &HDS );
}