Пример #1
0
void CSE_ALifeGroupAbstract::switch_online	()
{
	CSE_ALifeDynamicObject		*object = smart_cast<CSE_ALifeDynamicObject*>(this);
	VERIFY						(object);

	R_ASSERT					(!object->m_bOnline);
	object->m_bOnline			= true;

	ALife::OBJECT_IT			I = m_tpMembers.begin(), B = I;
	ALife::OBJECT_IT			E = m_tpMembers.end();
	u32							N = (u32)(E - I);
	for ( ; I != E; ++I) {
		CSE_ALifeDynamicObject	*J = ai().alife().objects().object(*I);
		if (m_bCreateSpawnPositions) {
			J->o_Position		= object->o_Position;
			J->m_tNodeID		= object->m_tNodeID;
			CSE_ALifeMonsterAbstract	*l_tpALifeMonsterAbstract = smart_cast<CSE_ALifeMonsterAbstract*>(J);
			if (l_tpALifeMonsterAbstract)
				l_tpALifeMonsterAbstract->o_torso.yaw = angle_normalize_signed((I - B)/N*PI_MUL_2);
		}
		object->alife().add_online	(J, false);
	}
	m_bCreateSpawnPositions		= false;
	object->alife().scheduled().remove	(object);
	object->alife().graph().remove		(object,object->m_tGraphID,false);
}
Пример #2
0
void player_hud::update_inertion(Fmatrix& trans)
{
	if ( inertion_allowed() )
	{
		Fmatrix								xform;
		Fvector& origin						= trans.c; 
		xform								= trans;

		static Fvector						st_last_dir={0,0,0};

		// calc difference
		Fvector								diff_dir;
		diff_dir.sub						(xform.k, st_last_dir);

		// clamp by PI_DIV_2
		Fvector last;						last.normalize_safe(st_last_dir);
		float dot							= last.dotproduct(xform.k);
		if (dot<EPS){
			Fvector v0;
			v0.crossproduct					(st_last_dir,xform.k);
			st_last_dir.crossproduct		(xform.k,v0);
			diff_dir.sub					(xform.k, st_last_dir);
		}

		// tend to forward
		st_last_dir.mad						(diff_dir,TENDTO_SPEED*Device.fTimeDelta);
		origin.mad							(diff_dir,ORIGIN_OFFSET);

		// pitch compensation
		float pitch							= angle_normalize_signed(xform.k.getP());
		origin.mad							(xform.k,	-pitch * PITCH_OFFSET_D);
		origin.mad							(xform.i,	-pitch * PITCH_OFFSET_R);
		origin.mad							(xform.j,	-pitch * PITCH_OFFSET_N);
	}
}
Пример #3
0
void CHelicopter::UpdateMGunDir()
{
	IKinematics* K		= smart_cast<IKinematics*>(Visual());
	m_fire_bone_xform	= K->LL_GetTransform(m_fire_bone);

	m_fire_bone_xform.mulA_43	(XFORM());
	m_fire_pos.set				(0,0,0); 
	m_fire_bone_xform.transform_tiny(m_fire_pos);
	m_fire_dir.set				(0,0,1);
	m_fire_bone_xform.transform_dir(m_fire_dir);
	
	m_fire_dir.sub				(m_enemy.destEnemyPos,m_fire_pos).normalize_safe();

	m_left_rocket_bone_xform	= K->LL_GetTransform(m_left_rocket_bone);
	m_left_rocket_bone_xform.mulA_43	(XFORM());
	m_left_rocket_bone_xform.c.y += 1.0f;
	//.fake
	m_right_rocket_bone_xform	= K->LL_GetTransform(m_right_rocket_bone);
	m_right_rocket_bone_xform.mulA_43	(XFORM());
	m_right_rocket_bone_xform.c.y += 1.0f;
	//.fake

	m_allow_fire		= TRUE;
	Fmatrix XFi;
	XFi.invert			(XFORM());
	Fvector dep;
	XFi.transform_tiny	(dep,m_enemy.destEnemyPos);
	{// x angle
		Fvector A_;		A_.sub(dep,m_bind_x);	m_i_bind_x_xform.transform_dir(A_); A_.normalize();
		m_tgt_rot.x		= angle_normalize_signed(m_bind_rot.x-A_.getP());
		float sv_x		= m_tgt_rot.x;
		clamp			(m_tgt_rot.x,-m_lim_x_rot.y,-m_lim_x_rot.x);
		if (!fsimilar(sv_x,m_tgt_rot.x,EPS_L)) m_allow_fire=FALSE;
	}
	{// y angle
		Fvector A_;		A_.sub(dep,m_bind_y);	m_i_bind_y_xform.transform_dir(A_); A_.normalize();
		m_tgt_rot.y		= angle_normalize_signed(m_bind_rot.y-A_.getH());
		float sv_y		= m_tgt_rot.y;
		clamp			(m_tgt_rot.y,-m_lim_y_rot.y,-m_lim_y_rot.x);
		if (!fsimilar(sv_y,m_tgt_rot.y,EPS_L)) m_allow_fire=FALSE;
	}
	
	if ((angle_difference(m_cur_rot.x,m_tgt_rot.x)>deg2rad(m_barrel_dir_tolerance))||
		(angle_difference(m_cur_rot.y,m_tgt_rot.y)>deg2rad(m_barrel_dir_tolerance)))
		m_allow_fire=FALSE;

}
Пример #4
0
bool CMonsterEnemyManager::is_faced(const CEntityAlive *object0, const CEntityAlive *object1)
{
	if (object0->Position().distance_to(object1->Position()) > object0->ffGetRange())
	{
		return false;
	}

	float			yaw1, pitch1, yaw2, pitch2, fYawFov, fPitchFov, fRange;
	Fvector			tPosition = object0->Position();

	yaw1			= object0->Orientation().yaw;
	pitch1			= object0->Orientation().pitch;
	fYawFov			= angle_normalize_signed(object0->ffGetFov()*PI/180.f);
	fRange			= object0->ffGetRange();

	fYawFov			= angle_normalize_signed((_abs(fYawFov) + _abs(atanf(1.f/tPosition.distance_to(object1->Position()))))/2.f);
	fPitchFov		= angle_normalize_signed(fYawFov*1.f);
	tPosition.sub	(object1->Position());
	tPosition.mul	(-1);
	tPosition.getHP	(yaw2,pitch2);
	yaw1			= angle_normalize_signed(yaw1);
	pitch1			= angle_normalize_signed(pitch1);
	yaw2			= angle_normalize_signed(yaw2);
	pitch2			= angle_normalize_signed(pitch2);
	if ((angle_difference(yaw1,yaw2) <= fYawFov) && (angle_difference(pitch1,pitch2) <= fPitchFov))
		return		(true);
	return			(false);
}
Пример #5
0
void CCustomMonster::Exec_Look						( float dt )
{
	if (animation_movement_controlled())
		return;

	movement().m_body.current.yaw		= angle_normalize_signed	(movement().m_body.current.yaw);
	movement().m_body.current.pitch		= angle_normalize_signed	(movement().m_body.current.pitch);
	movement().m_body.target.yaw		= angle_normalize_signed	(movement().m_body.target.yaw);
	movement().m_body.target.pitch		= angle_normalize_signed	(movement().m_body.target.pitch);
	
	float pitch_speed					= get_custom_pitch_speed(movement().m_body.speed);
	angle_lerp_bounds					(movement().m_body.current.yaw,movement().m_body.target.yaw,movement().m_body.speed,dt);
	angle_lerp_bounds					(movement().m_body.current.pitch,movement().m_body.target.pitch,pitch_speed,dt);

	Fvector P							= Position();
	XFORM().setHPB						(-NET_Last.o_model,-NET_Last.o_torso.pitch,0);
	Position()							= P;
}
Пример #6
0
void CCarWeapon::UpdateBarrelDir()
{
	CKinematics* K		= smart_cast<CKinematics*>(m_object->Visual());
	m_fire_bone_xform	= K->LL_GetTransform(m_fire_bone);

	m_fire_bone_xform.mulA_43(m_object->XFORM());
	m_fire_pos.set(0,0,0); 
	m_fire_bone_xform.transform_tiny(m_fire_pos);
	m_fire_dir.set(0,0,1);
	m_fire_bone_xform.transform_dir(m_fire_dir);
	m_fire_norm.set(0,1,0);
	m_fire_bone_xform.transform_dir(m_fire_norm);


	m_allow_fire		= true;
	Fmatrix XFi;
	XFi.invert			(m_object->XFORM());
	Fvector dep;
	XFi.transform_dir	(dep,m_destEnemyDir);
	{// x angle
		m_i_bind_x_xform.transform_dir(dep); dep.normalize();
		m_tgt_x_rot		= angle_normalize_signed(m_bind_x_rot-dep.getP());
		clamp			(m_tgt_x_rot,-m_lim_x_rot.y,-m_lim_x_rot.x);
	}
	{// y angle
		m_i_bind_y_xform.transform_dir(dep); dep.normalize();
		m_tgt_y_rot		= angle_normalize_signed(m_bind_y_rot-dep.getH());
		clamp			(m_tgt_y_rot,-m_lim_y_rot.y,-m_lim_y_rot.x);
	}

	m_cur_x_rot		= angle_inertion_var(m_cur_x_rot,m_tgt_x_rot,m_min_gun_speed,m_max_gun_speed,PI,Device.fTimeDelta);
	m_cur_y_rot		= angle_inertion_var(m_cur_y_rot,m_tgt_y_rot,m_min_gun_speed,m_max_gun_speed,PI,Device.fTimeDelta);
	static float dir_eps = deg2rad(5.0f);
	if( !fsimilar(m_cur_x_rot,m_tgt_x_rot,dir_eps)|| !fsimilar(m_cur_y_rot,m_tgt_y_rot,dir_eps))
		m_allow_fire=FALSE;

#if (0)
	if(Device.dwFrame%200==0){
		Msg("m_cur_x_rot=[%f]",m_cur_x_rot);
		Msg("m_cur_y_rot=[%f]",m_cur_y_rot);
	}
#endif
}
TEMPLATE_SPECIALIZATION
void _detail::callback		(CBoneInstance *B)
{
	CAI_Stalker*			A = static_cast<CAI_Stalker*>(B->Callback_Param);
	VERIFY					(_valid(B->mTransform));
	Fvector c				= B->mTransform.c;
	Fmatrix					spin;
	float					yaw_factor = 0, pitch_factor = 0;
	if (A->sight().use_torso_look()) {
		yaw_factor			= yaw_factor_fire/100.f;
		pitch_factor		= pitch_factor_fire/100.f;
	}
	else {
		yaw_factor			= yaw_factor_non_fire/100.f;
		pitch_factor		= pitch_factor_non_fire/100.f;
	}

	float					effector_yaw = 0.f, effector_pitch = 0.f;
	if (A->weapon_shot_effector().IsActive()) {
		Fvector				temp;
		A->weapon_shot_effector().GetDeltaAngle(temp);
		effector_yaw		= temp.y;
		VERIFY				(_valid(effector_yaw));
		effector_pitch		= temp.x;
		VERIFY				(_valid(effector_pitch));
	}

	VERIFY					(_valid(A->movement().head_orientation().current.yaw));
	VERIFY					(_valid(A->movement().body_orientation().current.yaw));
	VERIFY					(_valid(A->NET_Last.o_torso.pitch));

	float					yaw		= angle_normalize_signed(-yaw_factor * angle_normalize_signed(A->movement().head_orientation().current.yaw + effector_yaw - (A->movement().body_orientation().current.yaw)));
	float					pitch	= angle_normalize_signed(-pitch_factor * angle_normalize_signed(A->NET_Last.o_torso.pitch + effector_pitch));
	VERIFY					(_valid(yaw));
	VERIFY					(_valid(pitch));

	spin.setXYZ				(pitch, yaw, 0);
	VERIFY					(_valid(spin));
	B->mTransform.mulA_43	(spin);
	B->mTransform.c			= c;
}
MotionID CStalkerAnimationManager::legs_move_animation		()
{
	m_no_move_actual			= false;

	stalker_movement_manager_smart_cover		&movement = object().movement();

	VERIFY						(
		(movement.body_state() == eBodyStateStand) ||
		(movement.mental_state() != eMentalStateFree)
	);

	if (eMentalStateDanger != movement.mental_state()) {
		m_target_speed			= movement.speed(eMovementDirectionForward);
		m_last_non_zero_speed	= m_target_speed;

		return					(
			m_data_storage->m_part_animations.A[
				body_state()
			].m_movement.A[
				movement.movement_type()
			].A[
				eMovementDirectionForward
			].A[
				1
			]
		);
	}

	float						yaw,pitch;
	object().sight().GetDirectionAngles(yaw,pitch);

	yaw							= angle_normalize_signed(-yaw);;
	legs_process_direction		(yaw);

	float						body_current = movement.body_orientation().current.yaw;
	bool						left = left_angle(yaw,body_current);
	float						test_angle_forward = right_forward_angle;
	float						test_angle_backward = left_forward_angle;
	if (left) {
		test_angle_forward		= left_forward_angle;
		test_angle_backward		= right_forward_angle;
	}
	test_angle_backward			= PI - test_angle_backward;

	EMovementDirection			speed_direction;
	float						difference = angle_difference(yaw,body_current);

	if (difference <= test_angle_forward)
		speed_direction			= eMovementDirectionForward;
	else {
		if (difference > test_angle_backward)
			speed_direction		= eMovementDirectionBackward;
		else {
			if (left)
				speed_direction	= eMovementDirectionLeft;
			else
				speed_direction	= eMovementDirectionRight;
		}
	}

	if (m_previous_speed_direction != speed_direction) {
		if (m_change_direction_time < Device.dwTimeGlobal)
			m_change_direction_time	= Device.dwTimeGlobal;

		if (!legs_switch_factor()) {
			m_previous_speed		= 0.f;
			m_target_speed			= 0.f;
		}

		m_previous_speed_direction	= speed_direction;
	}

	m_target_speed				= movement.speed(speed_direction);
	m_last_non_zero_speed		= m_target_speed;

	return						(
		m_data_storage->m_part_animations.A[
			body_state()
		].m_movement.A[
			movement.movement_type()
		].A[
			speed_direction
		].A[
			0
		]
	);
}
Пример #9
0
void CActor::g_Orientate	(u32 mstate_rl, float dt)
{
	static float fwd_l_strafe_yaw	= deg2rad(pSettings->r_float(ACTOR_ANIM_SECT,	"fwd_l_strafe_yaw"));
	static float back_l_strafe_yaw	= deg2rad(pSettings->r_float(ACTOR_ANIM_SECT,	"back_l_strafe_yaw"));
	static float fwd_r_strafe_yaw	= deg2rad(pSettings->r_float(ACTOR_ANIM_SECT,	"fwd_r_strafe_yaw"));
	static float back_r_strafe_yaw	= deg2rad(pSettings->r_float(ACTOR_ANIM_SECT,	"back_r_strafe_yaw"));
	static float l_strafe_yaw		= deg2rad(pSettings->r_float(ACTOR_ANIM_SECT,	"l_strafe_yaw"));
	static float r_strafe_yaw		= deg2rad(pSettings->r_float(ACTOR_ANIM_SECT,	"r_strafe_yaw"));

	if(!g_Alive())return;
	// visual effect of "fwd+strafe" like motion
	float calc_yaw = 0;
	if(mstate_real&mcClimb)
	{
		if(g_LadderOrient()) return;
	}
	switch(mstate_rl&mcAnyMove)
	{
	case mcFwd+mcLStrafe:
		calc_yaw = +fwd_l_strafe_yaw;//+PI_DIV_4; 
		break;
	case mcBack+mcRStrafe:
		calc_yaw = +back_r_strafe_yaw;//+PI_DIV_4; 
		break;
	case mcFwd+mcRStrafe:
		calc_yaw = -fwd_r_strafe_yaw;//-PI_DIV_4; 
		break;
	case mcBack+mcLStrafe: 
		calc_yaw = -back_l_strafe_yaw;//-PI_DIV_4; 
		break;
	case mcLStrafe:
		calc_yaw = +l_strafe_yaw;//+PI_DIV_3-EPS_L; 
		break;
	case mcRStrafe:
		calc_yaw = -r_strafe_yaw;//-PI_DIV_4+EPS_L; 
		break;
	}

	// lerp angle for "effect" and capture torso data from camera
	angle_lerp		(r_model_yaw_delta,calc_yaw,PI_MUL_4,dt);

	// build matrix
	Fmatrix mXFORM;
	mXFORM.rotateY	(-(r_model_yaw + r_model_yaw_delta));
	mXFORM.c.set	(Position());
	XFORM().set		(mXFORM);

	//-------------------------------------------------

	float tgt_roll		=	0.f;
	if (mstate_rl&mcLookout)
	{
		tgt_roll		=	(mstate_rl&mcLLookout)?-ACTOR_LOOKOUT_ANGLE:ACTOR_LOOKOUT_ANGLE;
		
		if( (mstate_rl&mcLLookout) && (mstate_rl&mcRLookout) )
			tgt_roll	= 0.0f;
	}
	if (!fsimilar(tgt_roll,r_torso_tgt_roll,EPS)){
		angle_lerp		(r_torso_tgt_roll,tgt_roll,PI_MUL_2,dt);
		r_torso_tgt_roll= angle_normalize_signed(r_torso_tgt_roll);
	}
}
Пример #10
0
void CMonsterSquad::Attack_AssignTargetDir(ENTITY_VEC &members, const CEntity *enemy)
{
	_elem	first;
	_elem	last;

	lines.clear();

	// сортировать по убыванию расстояния от npc до врага 
	std::sort(members.begin(), members.end(), sort_predicate(enemy));
	if (members.empty()) return;

	float delta_yaw = PI_MUL_2 / members.size();

	// обработать ближний элемент
	first.pE		= members.back();
	first.p_from	= first.pE->Position();
	first.yaw		= 0;
	members.pop_back();

	lines.push_back(first);

	// обработать дальний элемент
	if (!members.empty()) {
		last.pE			= members[0];
		last.p_from		= last.pE->Position();
		last.yaw		= PI;
		members.erase	(members.begin());

		lines.push_back(last);
	}

	Fvector target_pos = enemy->Position();
	float	next_right_yaw	= delta_yaw;
	float	next_left_yaw	= delta_yaw;

	// проходим с конца members в начало (начиная с наименьшего расстояния)
	while (!members.empty()) {
		CEntity *pCur;

		pCur = members.back();
		members.pop_back();

		_elem cur_line;
		cur_line.p_from		= pCur->Position();
		cur_line.pE			= pCur;

		// определить cur_line.yaw

		float h1,p1,h2,p2;
		Fvector dir;
		dir.sub(target_pos, first.p_from);
		dir.getHP(h1,p1);	
		dir.sub(target_pos, cur_line.p_from);
		dir.getHP(h2,p2);

		bool b_add_left = false;

		if (angle_normalize_signed(h2 - h1) > 0)  {		// right
			if ((next_right_yaw < PI) && !fsimilar(next_right_yaw, PI, PI/60.f)) b_add_left = false;
			else b_add_left = true;
		} else {										// left
			if ((next_left_yaw < PI) && !fsimilar(next_left_yaw, PI, PI/60.f)) b_add_left = true;
			else b_add_left = false;
		}

		if (b_add_left) {
			cur_line.yaw = -next_left_yaw;
			next_left_yaw += delta_yaw;
		} else {
			cur_line.yaw = next_right_yaw;
			next_right_yaw += delta_yaw;
		}

		lines.push_back(cur_line);
	}

	// Пройти по всем линиям и заполнить таргеты у npc
	float first_h, first_p;
	Fvector d; d.sub(target_pos,first.p_from);
	d.getHP(first_h, first_p);

	for (u32 i = 0; i < lines.size(); i++){
		SSquadCommand command;
		command.type			= SC_ATTACK;
		command.entity			= enemy;
		command.direction.setHP	(first_h + lines[i].yaw, first_p);
		UpdateCommand(lines[i].pE, command);
	}
}
Пример #11
0
void CControlDirection::update_frame()
{
	pitch_correction			();	

	SRotationEventData			event_data;
	event_data.angle			= 0;

	bool heading_similar		= false;
	bool pitch_similar			= false;

	// difference
	float diff = angle_difference(m_pitch.current_angle, m_data.pitch.target_angle) * 4.0f;
	clamp(diff, PI_DIV_6, 5 * PI_DIV_6);

	m_data.pitch.target_speed = m_pitch.current_speed = diff;

	// поправка угловой скорости в соответствии с текущей и таргетовой линейной скоростями
	// heading speed correction
	if (!fis_zero(m_man->movement().velocity_current()) && !fis_zero(m_man->movement().velocity_target()) && m_data.linear_dependency)
		m_heading.current_speed	= m_data.heading.target_speed * m_man->movement().velocity_current() / (m_man->movement().velocity_target() + EPS_L);
	else 
		velocity_lerp			(m_heading.current_speed, m_data.heading.target_speed, m_heading.current_acc, m_object->client_update_fdelta());

	m_heading.current_angle		= angle_normalize(m_heading.current_angle);
	m_data.heading.target_angle	= angle_normalize(m_data.heading.target_angle);
	
	if (fsimilar(m_heading.current_angle, m_data.heading.target_angle)) heading_similar = true;
	angle_lerp(m_heading.current_angle, m_data.heading.target_angle, m_heading.current_speed, m_object->client_update_fdelta());
	if (!heading_similar && fsimilar(m_heading.current_angle, m_data.heading.target_angle)) {
		event_data.angle |= SRotationEventData::eHeading;
	}

	// update pitch
	velocity_lerp				(m_pitch.current_speed, m_data.pitch.target_speed, m_pitch.current_acc, m_object->client_update_fdelta());

	m_pitch.current_angle		= angle_normalize_signed	(m_pitch.current_angle);
	m_data.pitch.target_angle	= angle_normalize_signed	(m_data.pitch.target_angle);

	if (fsimilar(m_pitch.current_angle, m_data.pitch.target_angle)) pitch_similar = true;
	angle_lerp					(m_pitch.current_angle, m_data.pitch.target_angle, m_pitch.current_speed, m_object->client_update_fdelta());
	if (!pitch_similar && fsimilar(m_pitch.current_angle, m_data.pitch.target_angle)) {
		event_data.angle |= SRotationEventData::ePitch;
	}

	// set
	m_man->path_builder().m_body.speed			= m_heading.current_speed;
	m_man->path_builder().m_body.current.yaw	= m_heading.current_angle;
	m_man->path_builder().m_body.target.yaw		= m_heading.current_angle;
	m_man->path_builder().m_body.current.pitch	= m_pitch.current_angle;
	m_man->path_builder().m_body.target.pitch	= m_pitch.current_angle;

	// save object position
	Fvector P					= m_object->Position();
	// set angles
	if(!m_object->animation_movement_controlled())
		m_object->XFORM().setHPB	(-m_man->path_builder().m_body.current.yaw,-m_man->path_builder().m_body.current.pitch,0);
	// restore object position
	m_object->Position()		= P;

	
	// if there is an event
	if (event_data.angle)		m_man->notify(ControlCom::eventRotationEnd, &event_data);
}