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;
	}
}
CAlienEffector::CAlienEffector(ECamEffectorType type, CAI_Bloodsucker *obj) :
	inherited(type, flt_max)
{
	dangle_target.set		(angle_normalize(Random.randFs(DELTA_ANGLE_X)),angle_normalize(Random.randFs(DELTA_ANGLE_Y)),angle_normalize(Random.randFs(DELTA_ANGLE_Z)));
	dangle_current.set		(0.f, 0.f, 0.f);

	monster					= obj;
	
	m_prev_eye_matrix.c		= get_head_position(monster);
	m_prev_eye_matrix.k		= monster->Direction();
	Fvector::generate_orthonormal_basis(m_prev_eye_matrix.k,m_prev_eye_matrix.j,m_prev_eye_matrix.i);
	m_inertion				= 1.f;
	m_current_fov			= MIN_FOV;
}
示例#3
0
static void
Boat_update_angles(Boat *boat, const Uint8 *key_state)
{
    Uint32 cur_time = game_time(),
           last_rot_time = Boat_GET(last_rot_time, boat);
    float angle = Ent_GET(rotation, boat);
    vec2 move_direction = {0, 0};
 
    if(!key_state[SDLK_RIGHT] && !key_state[SDLK_LEFT]) {
        Boat_SET(last_rot_time, boat, 0);
        return;
    }

    if(last_rot_time != 0 && (cur_time - last_rot_time) < BOAT_ROTATION_DELAY)
        return;

    if(key_state[SDLK_LEFT])
        angle += BOAT_SPRITE_ANGLE_INTERVAL;
    else
        angle -= BOAT_SPRITE_ANGLE_INTERVAL;

    Boat_SET(last_rot_time, boat, cur_time);

    angle = angle_normalize(angle_round(angle, BOAT_SPRITE_ANGLE_INTERVAL));
    Ent_SET(rotation, boat, angle);

    vec2_from_angle(&move_direction, angle);
    Ent_SET(move_direction, boat, &move_direction);
}
float CControlDirection::angle_to_target(const Fvector &position)
{
	float		angle = Fvector().sub(position, m_object->Position()).getH();
	angle		*= -1;
	
	return		(angle_normalize(angle));
}
示例#5
0
void CControlJump::hit_test() 
{
	if (m_object_hitted)	return;
	if (!m_data.target_object)	return;

	// ѕроверить на нанесение хита во врем¤ прыжка
	Fvector trace_from;
	m_object->Center(trace_from);

	collide::rq_result	l_rq;

	if (Level().ObjectSpace.RayPick(trace_from, m_object->Direction(), m_hit_trace_range, collide::rqtObject, l_rq, m_object)) {
		if ((l_rq.O == m_data.target_object) && (l_rq.range < m_hit_trace_range)) {
			m_object_hitted = true;
		}
	}

	if (!m_object_hitted && m_data.target_object) {
		
		m_object_hitted = true;
		// определить дистанцию до врага
		Fvector d;
		d.sub(m_data.target_object->Position(),m_object->Position());
		if (d.magnitude() > m_hit_trace_range) m_object_hitted = false;

		// проверка на  Field-Of-Hit
		float my_h,my_p;
		float h,p;

		m_object->Direction().getHP(my_h,my_p);
		d.getHP(h,p);

		float from	= angle_normalize(my_h - PI_DIV_6);
		float to	= angle_normalize(my_h + PI_DIV_6);

		if (!is_angle_between(h, from, to)) m_object_hitted = false;

		from	= angle_normalize(my_p - PI_DIV_6);
		to		= angle_normalize(my_p + PI_DIV_6);

		if (!is_angle_between(p, from, to)) m_object_hitted = false;

	} 

	if (m_object_hitted) 
		m_object->HitEntityInJump(smart_cast<CEntity*>(m_data.target_object));
}
示例#6
0
// ****************************** Update actor orientation according to camera orientation
void CActor::g_cl_Orientate	(u32 mstate_rl, float dt)
{
	// capture camera into torso (only for FirstEye & LookAt cameras)
	if (eacFreeLook!=cam_active)
	{
		r_torso.yaw		=	cam_Active()->GetWorldYaw	();
		r_torso.pitch	=	cam_Active()->GetWorldPitch	();
	}
	else
	{
		r_torso.yaw		=	cam_FirstEye()->GetWorldYaw	();
		r_torso.pitch	=	cam_FirstEye()->GetWorldPitch	();
	}

	unaffected_r_torso.yaw		= r_torso.yaw;
	unaffected_r_torso.pitch	= r_torso.pitch;
	unaffected_r_torso.roll		= r_torso.roll;

	CWeaponMagazined *pWM = smart_cast<CWeaponMagazined*>(inventory().GetActiveSlot() != NO_ACTIVE_SLOT ? 
		inventory().ItemFromSlot(inventory().GetActiveSlot())/*inventory().m_slots[inventory().GetActiveSlot()].m_pIItem*/ : NULL);
	if (pWM && pWM->GetCurrentFireMode() == 1 && eacFirstEye != cam_active)
	{
		Fvector dangle = weapon_recoil_last_delta();
		r_torso.yaw		=	unaffected_r_torso.yaw + dangle.y;
		r_torso.pitch	=	unaffected_r_torso.pitch + dangle.x;
	}
	
	// если есть движение - выровнять модель по камере
	if (mstate_rl&mcAnyMove)	{
		r_model_yaw		= angle_normalize(r_torso.yaw);
		mstate_real		&=~mcTurn;
	} else {
		// if camera rotated more than 45 degrees - align model with it
		float ty = angle_normalize(r_torso.yaw);
		if (_abs(r_model_yaw-ty)>PI_DIV_4)	{
			r_model_yaw_dest = ty;
			// 
			mstate_real	|= mcTurn;
		}
		if (_abs(r_model_yaw-r_model_yaw_dest)<EPS_L){
			mstate_real	&=~mcTurn;
		}
		if (mstate_rl&mcTurn){
			angle_lerp	(r_model_yaw,r_model_yaw_dest,PI_MUL_2,dt);
		}
	}
}
void CControlRotationJump::build_line_first()
{
	// get animation time
	m_time						= m_man->animation().motion_time(m_right_side ? m_data.anim_stop_rs : m_data.anim_stop_ls, m_object->Visual());
	// set acceleration and velocity
	m_start_velocity			= m_man->movement().velocity_current();
	m_target_velocity			= 0.f;
	
	// acceleration
	m_accel = (m_target_velocity - m_start_velocity) / m_time;

	// path distance
	m_dist = (m_target_velocity*m_target_velocity - m_start_velocity*m_start_velocity) / (2*m_accel);
	
	
	// set angular speed in exclusive force mode
	SControlDirectionData					*ctrl_data_dir = (SControlDirectionData*)m_man->data(this, ControlCom::eControlDir); 
	VERIFY									(ctrl_data_dir);	

	float target_yaw						= angle_normalize(-m_object->Direction().getH() + (m_right_side ? m_data.turn_angle : -m_data.turn_angle));
	ctrl_data_dir->heading.target_angle		= target_yaw;
	
	float cur_yaw;
	m_man->direction().get_heading			(cur_yaw, target_yaw);
	ctrl_data_dir->heading.target_speed		= angle_difference(cur_yaw,target_yaw)/ m_time;
	ctrl_data_dir->linear_dependency		= false;

	VERIFY									(!fis_zero(ctrl_data_dir->heading.target_speed));
	
	u32 velocity_mask	= MonsterMovement::eVelocityParameterStand | MonsterMovement::eVelocityParameterRunNormal;
	m_stage				= eStop;
	
	Fvector target_position;
	target_position.mad(m_object->Position(), m_object->Direction(), m_dist);

	if (!m_man->build_path_line(this, target_position, u32(-1), velocity_mask)) {
		m_man->notify				(ControlCom::eventRotationJumpEnd, 0);
	} else { 
		// enable path
		SControlPathBuilderData		*ctrl_path = (SControlPathBuilderData*)m_man->data(this, ControlCom::eControlPath); 
		VERIFY						(ctrl_path);
		ctrl_path->enable			= true;
		
		m_man->lock					(this, ControlCom::eControlPath);

		SControlMovementData		*ctrl_move = (SControlMovementData*)m_man->data(this, ControlCom::eControlMovement); 
		VERIFY						(ctrl_move);
		ctrl_move->velocity_target	= m_target_velocity;
		ctrl_move->acc				= _abs(m_accel);

		// start new animation
		SControlAnimationData		*ctrl_data = (SControlAnimationData*)m_man->data(this, ControlCom::eControlAnimation); 
		VERIFY						(ctrl_data);

		ctrl_data->global.motion	= m_right_side ? m_data.anim_stop_rs : m_data.anim_stop_ls;
		ctrl_data->global.actual	= false;
	}
}
示例#8
0
void CControlDirectionBase::use_path_direction(bool reversed)
{
	float yaw,pitch;
	m_man->path_builder().detail().direction().getHP	(yaw,pitch);

	if (fsimilar(yaw,0.f,EPS_S)) return;

	m_heading.target = angle_normalize((reversed) ? (-yaw + PI) : (-yaw));
}
void CMonsterCoverManager::less_cover_direction(Fvector &dir)
{
	float angle				= ai().level_graph().vertex_cover_angle(m_object->ai_location().level_vertex_id(),deg(10), std::greater<float>());

	collide::rq_result		l_rq;

	float angle_from		= angle_normalize(angle - ANGLE_DISP);
	float angle_to			= angle_normalize(angle + ANGLE_DISP);

	Fvector					trace_from;
	m_object->Center		(trace_from);
	Fvector					direction;

	// trace discretely left
	for (float ang = angle; angle_difference(ang, angle) < ANGLE_DISP; ang = angle_normalize(ang - ANGLE_DISP_STEP)) {

		direction.setHP	(ang, 0.f);

		if (Level().ObjectSpace.RayPick(trace_from, direction, TRACE_STATIC_DIST, collide::rqtStatic, l_rq,m_object)) {
			if ((l_rq.range < TRACE_STATIC_DIST)) {
				angle_from = ang;
				break;
			}
		}
	}

	// trace discretely right
	for (float ang = angle; angle_difference(ang, angle) < ANGLE_DISP; ang = angle_normalize(ang + ANGLE_DISP_STEP)) {

		direction.setHP	(ang, 0.f);

		if (Level().ObjectSpace.RayPick(trace_from, direction, TRACE_STATIC_DIST, collide::rqtStatic, l_rq,m_object)) {
			if ((l_rq.range < TRACE_STATIC_DIST)) {
				angle_to = ang;
				break;
			}
		}
	}

	angle		= angle_normalize(angle_from + angle_difference(angle_from,angle_to) / 2);
	dir.setHP	(angle,0.f);
}
void CControlAnimationBase::check_hit(MotionID motion, float time_perc)
{
	if (!m_object->EnemyMan.get_enemy()) return;
	const CEntityAlive *enemy = m_object->EnemyMan.get_enemy();

	SAAParam &params		= AA_GetParams(motion,time_perc);
	
	m_object->sound().play	(MonsterSound::eMonsterSoundAttackHit);

	bool should_hit = true;
	// определить дистанцию до врага
	Fvector d;
	d.sub(enemy->Position(),m_object->Position());
	if (d.magnitude() > params.dist) 
		should_hit = false;
	
	// проверка на  Field-Of-Hit
	float my_h,my_p;
	float h,p;

	m_object->Direction().getHP(my_h,my_p);
	d.getHP(h,p);
	
	float from	= angle_normalize(my_h + params.foh.from_yaw);
	float to	= angle_normalize(my_h + params.foh.to_yaw);
	
	if (!is_angle_between(h, from, to)) 
		should_hit = false;

	from		= angle_normalize(my_p + params.foh.from_pitch);
	to			= angle_normalize(my_p + params.foh.to_pitch);

	if (!is_angle_between(p, from, to)) 
		should_hit = false;

	if (should_hit) 
		m_object->HitEntity(enemy, params.hit_power, params.impulse, params.impulse_dir);

	m_object->MeleeChecker.on_hit_attempt(should_hit);
}
示例#11
0
Fvector   CMonsterSquad::calc_monster_target_dir (CBaseMonster* monster, const CEntity* enemy)
{
	VERIFY(monster);
	VERIFY(enemy);

	const Fvector enemy_pos = enemy->Position();
	Fvector home2enemy = enemy_pos;
	home2enemy.sub(monster->Home->get_home_point());

	const float home2enemy_mag = home2enemy.magnitude();

	// enemy pos == home pos?
	const float near_zero = 0.00001f;
	if ( home2enemy_mag < near_zero )
	{
		Fvector enemy2monster = monster->Position();
		enemy2monster.sub(enemy_pos);
		const float enemy2monster_mag = enemy2monster.magnitude();
		// monster pos == enemy pos?
		if ( enemy2monster_mag < near_zero )
		{
			VERIFY2(false, "Enemy and Monster should not have same pos!");
			Fvector dir = { 1.f, 0.f, 0.f }; // happy with random dir then :)
			return dir;
		}

		enemy2monster.normalize();
		return enemy2monster;
	}

	const u8 squad_size  = squad_alife_count();
	VERIFY(squad_size);

	u8 squad_index = get_index(monster);
	if ( squad_index == -1 )
	{
		squad_index = 0;
	}

	float heading, pitch;
	home2enemy.getHP(heading, pitch);

	// 2pi * index/num - encircle
	heading += M_PI * 2.f * squad_index / squad_size;
	heading = angle_normalize(heading);

	Fvector dir;
	dir.setHP(heading, pitch);
	dir.normalize();

	return dir;
}
示例#12
0
void CControlRotationJump::stop_at_once()
{
	m_time = m_man->animation().motion_time(m_right_side ? m_data.anim_stop_rs : m_data.anim_stop_ls, m_object->Visual());	

	// set angular speed in exclusive force mode
	SControlDirectionData					*ctrl_data_dir = (SControlDirectionData*)m_man->data(this, ControlCom::eControlDir); 
	VERIFY									(ctrl_data_dir);	

	float target_yaw;
	if (m_data.flags.is(SControlRotationJumpData::eRotateOnce) && m_object->EnemyMan.get_enemy()) {
		// if rotate once so rotate to enemy
		Fvector					dir_to_enemy;
		dir_to_enemy.sub		(m_object->EnemyMan.get_enemy()->Position(), m_object->Position());
		dir_to_enemy.normalize	();
		target_yaw				= angle_normalize(-dir_to_enemy.getH());
	} else {
		target_yaw				= angle_normalize(-m_object->Direction().getH() + (m_right_side ? m_data.turn_angle : -m_data.turn_angle));
	}

	ctrl_data_dir->heading.target_angle		= target_yaw;

	float cur_yaw;
	m_man->direction().get_heading			(cur_yaw, target_yaw);
	ctrl_data_dir->heading.target_speed		= angle_difference(cur_yaw,target_yaw)/ m_time;
	ctrl_data_dir->linear_dependency		= false;
	VERIFY									(!fis_zero(ctrl_data_dir->heading.target_speed));

	m_stage									= eStop;	

	// start new animation
	SControlAnimationData		*ctrl_data = (SControlAnimationData*)m_man->data(this, ControlCom::eControlAnimation); 
	VERIFY						(ctrl_data);

	ctrl_data->global.motion	= m_right_side ? m_data.anim_stop_rs : m_data.anim_stop_ls;
	ctrl_data->global.actual	= false;
}
示例#13
0
void CActorMP::fill_state	(actor_mp_state &state)
{
	if (OnClient())
	{
		//R_ASSERT						(g_Alive());
		//R_ASSERT2						(PHGetSyncItemsNumber() == 1,make_string("PHGetSyncItemsNumber() returned %d, health = %.2f",PHGetSyncItemsNumber(),GetfHealth()));
	}

	SPHNetState						State;
	PHGetSyncItem(0)->get_State		(State);

//	static test = false;
//	if (test) {
#if 0
		Msg							("Frame [%d], object [%d]",Device.dwFrame,ID());
//		Msg							("quaternion   : [%f][%f][%f][%f]",State.quaternion.x,State.quaternion.y,State.quaternion.z,State.quaternion.w);
//		Msg							("angular      : [%f][%f][%f]",State.angular_vel.x,State.angular_vel.y,State.angular_vel.z);
		Msg							("linear       : [%f][%f][%f]",State.linear_vel.x,State.linear_vel.y,State.linear_vel.z);
//		Msg							("force        : [%f][%f][%f]",State.force.x,State.force.y,State.force.z);
//		Msg							("torque       : [%f][%f][%f]",State.torque.x,State.torque.y,State.torque.z);
//		Msg							("acceleration : [%f][%f][%f]",NET_SavedAccel.x,NET_SavedAccel.y,NET_SavedAccel.z);
		Msg							("model_yaw    : [%f]",angle_normalize(r_model_yaw));
		Msg							("camera_yaw   : [%f]",angle_normalize(unaffected_r_torso.yaw));
//		Msg							("camera_pitch : [%f]",angle_normalize(unaffected_r_torso.pitch));
//		Msg							("camera_roll  : [%f]",angle_normalize(unaffected_r_torso.roll));
//	}
#endif // 0

	state.physics_quaternion		= State.quaternion;
	state.physics_angular_velocity	= State.angular_vel;
	state.physics_linear_velocity	= State.linear_vel;
	state.physics_force				= State.force;
	state.physics_torque			= State.torque;
	state.physics_position			= State.position;

	state.position					= Position();

	state.logic_acceleration		= NET_SavedAccel;

	state.model_yaw					= angle_normalize(r_model_yaw);
	state.camera_yaw				= angle_normalize(unaffected_r_torso.yaw);
	state.camera_pitch				= angle_normalize(unaffected_r_torso.pitch);
	state.camera_roll				= angle_normalize(unaffected_r_torso.roll);

	state.time						= Level().timeServer();

	state.inventory_active_slot		= inventory().GetActiveSlot();
	state.body_state_flags			= mstate_real & 0x0000ffff;
	state.health					= GetfHealth();
	//because after packing to 1 byte, this value can be positive...
	if (state.health < EPS)
		state.health = 0;

	state.radiation					= g_Radiation()/100.0f;
	state.physics_state_enabled		= State.enabled ? 1 : 0;
}
示例#14
0
void CAI_Rat::set_dir()
{
	if ((Device.dwTimeGlobal - m_previous_query_time > TIME_TO_GO) || !m_previous_query_time) {
		CMonsterSquad *squad	= monster_squad().get_squad(this);
		Fvector m_enemy_position = memory().enemy().selected()->Position();
		if (squad && squad->SquadActive())
		{
			float m_delta_Angle = angle_normalize((PI * 2) / squad->squad_alife_count());
			float m_heading, m_pitch;
			Fvector m_temp, m_dest_direction;
			m_temp = squad->GetLeader()->Position();
			m_dest_direction.x = (m_temp.x - m_enemy_position.x) / m_temp.distance_to(m_enemy_position);
			m_dest_direction.y = (m_temp.y - m_enemy_position.y) / m_temp.distance_to(m_enemy_position);
			m_dest_direction.z = (m_temp.z - m_enemy_position.z) / m_temp.distance_to(m_enemy_position);
			m_dest_direction.getHP(m_heading, m_pitch);
			m_heading = angle_normalize(m_heading + m_delta_Angle * squad->get_index(this));
			m_dest_direction.setHP(m_heading, m_pitch);
			m_dest_direction.mul(0.5f);
			m_enemy_position.add(m_enemy_position,m_dest_direction);
		}

		m_tGoalDir.set(m_enemy_position);
	}
}
示例#15
0
void CControlRotationJump::activate()
{
	m_man->capture_pure	(this);
	m_man->subscribe	(this, ControlCom::eventAnimationEnd);

	// disable path builder and movement
	m_man->path_stop	(this);
	m_man->move_stop	(this);

	float yaw			= Fvector().sub(m_object->EnemyMan.get_enemy()->Position(), m_object->Position()).getH();
	m_right_side		=  m_man->direction().is_from_right(angle_normalize(-yaw));
	
	//////////////////////////////////////////////////////////////////////////
	if (m_data.flags.is(SControlRotationJumpData::eStopAtOnce)) 
		stop_at_once		();
	else 
		build_line_first	();
	//////////////////////////////////////////////////////////////////////////
}
示例#16
0
void CControlDirectionBase::face_target(const Fvector &position, u32 delay, float add_yaw)
{
	if (m_time_last_faced + delay > Device.dwTimeGlobal) return;

	m_delay = delay;

	float	yaw, pitch;
	Fvector dir;

	dir.sub		(position, m_object->Position());
	dir.getHP	(yaw,pitch);
	yaw			*= -1;

	yaw			+= (m_man->direction().is_from_right(position)) ? add_yaw : -add_yaw;
	yaw			= angle_normalize(yaw);

	m_heading.target	= yaw;

	m_time_last_faced	= Device.dwTimeGlobal;
}
示例#17
0
/**
 * \brief Get the cardinal direction of angle
 * \param[in] angle Angle in radians.
 * \return dir4type direction
 */
PUBLIC dir4type Get4dir( float angle )
{
	angle = angle_normalize( angle + M_PI / 4 );

	if( angle < M_PI / 2 )
	{
		return dir4_east;
	}
	else if( angle < M_PI )
	{
		return dir4_north;
	}
	else if( angle < 3 * M_PI / 2 )
	{
		return dir4_west;
	}
	else
	{
		return dir4_south;
	}
}
示例#18
0
/**
 * \brief Get the quadrant the angle resides in
 * \param[in] angle Angle in radians.
 * \return quadrant the angle resides in
 */
PUBLIC quadrant GetQuadrant( float angle )
{
	angle = angle_normalize( angle );

	if( angle < M_PI / 2 )
	{
		return q_first;
	}
	else if( angle < M_PI )
	{
		return q_second;
	}
	else if( angle < 3 * M_PI / 2 )
	{
		return q_third;
	}
	else
	{
		return q_fourth;
	}
}
示例#19
0
void CBaseMonster::HitSignal(float amount, Fvector& vLocalDir, CObject* who, s16 element)
{
	if (!g_Alive()) return;
	
	feel_sound_new(who,SOUND_TYPE_WEAPON_SHOOTING,0,who->Position(),1.f);
	if (g_Alive()) sound().play(MonsterSound::eMonsterSoundTakeDamage);

	if (element < 0) return;

	// Определить направление хита (перед || зад || лево || право)
	float yaw,pitch;
	vLocalDir.getHP(yaw,pitch);
	
	yaw = angle_normalize(yaw);
	
	EHitSide hit_side = eSideFront;
	if ((yaw >= PI_DIV_4) && (yaw <= 3*PI_DIV_4)) hit_side = eSideLeft;
	else if ((yaw >= 3 * PI_DIV_4) && (yaw <= 5*PI_DIV_4)) hit_side = eSideBack;
	else if ((yaw >= 5 * PI_DIV_4) && (yaw <= 7*PI_DIV_4)) hit_side = eSideRight;

	anim().FX_Play	(hit_side, 1.0f);

	HitMemory.add_hit	(who,hit_side);

	Morale.on_hit		();

	callback(GameObject::eHit)(
		lua_game_object(), 
		amount,
		vLocalDir,
		smart_cast<const CGameObject*>(who)->lua_game_object(),
		element
	);

	// если нейтрал - добавить как врага
	CEntityAlive	*obj = smart_cast<CEntityAlive*>(who);
	if (obj && (tfGetRelationType(obj) == ALife::eRelationTypeNeutral)) EnemyMan.add_enemy(obj);
}
示例#20
0
/**
 * \brief Get ordinal direction of angle
 * \param[in] angle Angle in radians.
 * \return dir8type direction
 */
PUBLIC dir8type Get8dir( float angle )
{
	angle = angle_normalize( angle + M_PI / 12 );

	if( angle <= (M_PI / 4) )
	{
		return dir8_east;
	}
	else if( angle < (M_PI / 2) )
	{
		return dir8_northeast;
	}
	else if( angle <= (3 * M_PI / 4) )
	{
		return dir8_north;
	}
	else if( angle < M_PI )
	{
		return dir8_northwest;
	}
	else if( angle <= (5 * M_PI / 4) )
	{
		return dir8_west;
	}
	else if( angle < (3 * M_PI / 2) )
	{
		return dir8_southwest;
	}
	else if( angle <= (7 * M_PI / 4) )
	{
		return dir8_south;
	}
	else
	{
		return dir8_southeast;
	}
}
示例#21
0
static void
Boat_update_image(Boat *boat)
{
    SDL_Rect rect = {0, 0, BOAT_SPRITE_SIZE, BOAT_SPRITE_SIZE};
    int row, col, new_image_index;

    float angle = angle_normalize(Ent_GET(rotation, boat));
    if(angle < 0)
        angle = 360 + angle;

    new_image_index = (int)round_float(angle / BOAT_SPRITE_ANGLE_INTERVAL);
    if(new_image_index == Boat_GET(image_index, boat))
        return;
    
    row = new_image_index / BOAT_SPRITE_COLS;
    col = new_image_index % BOAT_SPRITE_COLS;
    rect.x = col * BOAT_SPRITE_SIZE;
    rect.y = row * BOAT_SPRITE_SIZE;

    VisibleEnt_SET(image_rect, boat, &rect);
    Boat_SET(image_index, boat, new_image_index);
    Ent_SET(bounds_width, boat, rect.w);
    Ent_SET(bounds_height, boat, rect.h);
}
示例#22
0
/**
 * \brief Transform point
 * \param[in] Point1X X-Coordinate.
 * \param[in] Point1Y Y-Coordinate.
 * \param[in] Point2X X-Coordinate.
 * \param[in] Point2Y Y-Coordinate.
 * \return Returns angle in radians
 * \note
 *      point2 = {x,y}
 *			  / |
 *		    /   |
 *		  /     |
 *		/a______|----------> x
 *	point1 = {x, y}
 */
PUBLIC float TransformPoint( const double Point1X, const double Point1Y, const double Point2X, const double Point2Y )
{

	return (float)angle_normalize( (float)atan2( Point1Y - Point2Y, Point1X - Point2X ) );
}
示例#23
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);
}
示例#24
0
u32 CMonsterHome::get_place_in_mid_home()
{
	u32		result = u32(-1);
	u32		input_node;
	const CPatrolPath::CVertex *vertex;

	int m_move_dist = min_move_dist + Random.randI(max_move_dist - min_move_dist); 
	float m_res_dist = 0.f + m_move_dist;
	if (!at_mid_home(m_object->Position()) || at_min_home(m_object->Position()))
	{
		if (!m_path)
		{
			input_node = m_object->ai_location().level_vertex_id();
		} else {
			vertex = m_path->vertex(Random.randI(m_path->vertex_count()));
			input_node = vertex->data().level_vertex_id();
		}
		m_object->control().path_builder().get_node_in_radius(input_node, m_radius_min, m_radius_middle , 5, result);
	} else {
		int i = 0;
		Fvector m_dest_direction;
		do 
		{
			i++;
			float m_heading, m_pitch;
			m_object->Direction().getHP(m_heading, m_pitch);
			float mAngle;
			if (i > 5)
			{
				if (Random.randI(2) == 1)
				{
					mAngle = Random.randF(-PI/3,-PI/4);
				} else {
					mAngle = Random.randF(PI/4,PI/3);
				}
			} else {
				mAngle = Random.randF(-PI/4,PI/4);
			}
			m_heading = angle_normalize(m_heading + mAngle);
			m_dest_direction.setHP(m_heading,m_pitch);
			m_dest_direction.mul(m_res_dist);
			m_dest_direction.add(m_object->Position(),m_dest_direction);
		} while(!ai().level_graph().valid_vertex_position(m_dest_direction) && i <= 10);
		if (ai().level_graph().valid_vertex_position(m_dest_direction))
		{
			result = ai().level_graph().vertex_id(m_dest_direction);
			input_node = result;
		} else {
			input_node = m_object->ai_location().level_vertex_id();
			m_object->control().path_builder().get_node_in_radius(input_node, m_res_dist - 1, m_res_dist, 5, result);
		}
	}

	if (result == u32(-1)) {
		// TODO: find more acceptable decision, than return its level_vertex_id, if !accessible
		if (ai().level_graph().valid_vertex_id(input_node) && m_object->control().path_builder().accessible(input_node))		
			result = input_node;
		else
			result = m_object->ai_location().level_vertex_id();
	}

	if (!ai().level_graph().valid_vertex_id(result) || !at_mid_home( ai().level_graph().vertex_position(result)))
		return get_place_in_min_home();

	return result;
}
示例#25
0
u32 CMonsterHome::get_place_in_max_home_to_direction(Fvector to_direction)
{
	Fvector m_home_point = get_home_point();
	u32 input_node = u32(-1);
	u32 result = u32(-1);
	int i = 0;
	float mAngle;
	Fvector m_dest_direction;
	float m_res_dist = m_radius_middle + (m_radius_max - m_radius_middle)/2 - (m_radius_max - m_radius_middle)/10;
	float m_heading, m_pitch;
	do 
	{
		i++;
		to_direction.getHP(m_heading, m_pitch);
		if (i > 5)
		{
			if (Random.randI(2) == 1)
			{
				mAngle = Random.randF(-PI/4,-PI/5);
			} else {
				mAngle = Random.randF(PI/5,PI/4);
			}
		} else {
			mAngle = Random.randF(-PI/5,PI/5);
		}
		m_heading = angle_normalize(m_heading + mAngle);
		m_dest_direction.setHP(m_heading,m_pitch);
		m_dest_direction.x = m_home_point.x + m_res_dist * m_dest_direction.x;
		m_dest_direction.y = m_home_point.y + m_res_dist * m_dest_direction.y;
		m_dest_direction.z = m_home_point.z + m_res_dist * m_dest_direction.z;

	} while(!ai().level_graph().valid_vertex_position(m_dest_direction) && i <= 10);

	if (ai().level_graph().valid_vertex_position(m_dest_direction))
		input_node = ai().level_graph().vertex_id(m_dest_direction);

	if (input_node != u32(-1))
		m_object->control().path_builder().get_node_in_radius(input_node, 1, (m_radius_max - m_radius_middle)/2, 5, result);

	if (result == u32(-1))
	{
		if (ai().level_graph().valid_vertex_id(input_node) && m_object->control().path_builder().accessible(input_node))
		{
			result = input_node;
		}
		else {
			m_res_dist = m_radius_min + (m_radius_middle - m_radius_min)/2 - (m_radius_middle - m_radius_min)/10;
			i = 0;
			input_node = u32(-1);
			do 
			{
				i++;
				to_direction.getHP(m_heading, m_pitch);
				if (i > 5)
				{
					if (Random.randI(2) == 1)
					{
						mAngle = Random.randF(-PI/3,-PI/5);
					} else {
						mAngle = Random.randF(PI/5,PI/3);
					}
				} else {
					mAngle = Random.randF(-PI/3,PI/3);
				}
				m_heading = angle_normalize(m_heading + mAngle);
				m_dest_direction.setHP(m_heading,m_pitch);
				m_dest_direction.x = m_home_point.x + m_res_dist * m_dest_direction.x;
				m_dest_direction.y = m_home_point.y + m_res_dist * m_dest_direction.y;
				m_dest_direction.z = m_home_point.z + m_res_dist * m_dest_direction.z;
			} while(!ai().level_graph().valid_vertex_position(m_dest_direction) && i <= 10);

			if (ai().level_graph().valid_vertex_position(m_dest_direction))
				input_node = ai().level_graph().vertex_id(m_dest_direction);

			if (input_node != u32(-1))
				m_object->control().path_builder().get_node_in_radius(input_node, 1, (m_radius_max - m_radius_middle)/2, 5, result);

			if (result == u32(-1))
			{
				if (ai().level_graph().valid_vertex_id(input_node) && m_object->control().path_builder().accessible(input_node))
				{
					result = input_node;
				} else {
					result = get_place_in_min_home();
				}
			}
		}
	}

	if (result == u32(-1)) result = get_place_in_max_home();

	return (result);
}
示例#26
0
BOOL CAlienEffector::ProcessCam(SCamEffectorInfo& info)
{
	// »нициализаци¤
	Fmatrix	Mdef;
	Mdef.identity		();
	Mdef.j.set			(info.n);
	Mdef.k.set			(info.d);
	Mdef.i.crossproduct	(info.n, info.d);
	Mdef.c.set			(info.p);


	// set angle 
	if (angle_lerp(dangle_current.x, dangle_target.x, ANGLE_SPEED, Device.fTimeDelta)) {
		dangle_target.x = angle_normalize(Random.randFs(DELTA_ANGLE_X));
	}

	if (angle_lerp(dangle_current.y, dangle_target.y, ANGLE_SPEED, Device.fTimeDelta)) {
		dangle_target.y = angle_normalize(Random.randFs(DELTA_ANGLE_Y));
	}

	if (angle_lerp(dangle_current.z, dangle_target.z, ANGLE_SPEED, Device.fTimeDelta)) {
		dangle_target.z = angle_normalize(Random.randFs(DELTA_ANGLE_Z));
	}

	// update inertion
	Fmatrix cur_matrix;
	cur_matrix.k = monster->Direction();
	cur_matrix.c = get_head_position(monster);

	float	rel_dist = m_prev_eye_matrix.c.distance_to(cur_matrix.c) / MAX_CAMERA_DIST;
	clamp	(rel_dist, 0.f, 1.f);

	def_lerp(m_inertion, 1 - rel_dist, rel_dist, Device.fTimeDelta);

	// set pos and dir with inertion
	m_prev_eye_matrix.c.inertion(cur_matrix.c, m_inertion);
	m_prev_eye_matrix.k.inertion(cur_matrix.k, m_inertion);
	Fvector::generate_orthonormal_basis_normalized(m_prev_eye_matrix.k,m_prev_eye_matrix.j,m_prev_eye_matrix.i);	

	// apply position and direction
	Mdef = m_prev_eye_matrix;

	//set fov
	float	rel_speed = monster->m_fCurSpeed / 15.f;
	clamp	(rel_speed,0.f,1.f);

	float	m_target_fov = MIN_FOV + (MAX_FOV-MIN_FOV) * rel_speed;
	def_lerp(m_current_fov, m_target_fov, FOV_SPEED, Device.fTimeDelta);
	
	info.fFov = m_current_fov;
	//////////////////////////////////////////////////////////////////////////

	// ”становить углы смещени¤
	Fmatrix		R;
	R.setHPB	(dangle_current.x,dangle_current.y,dangle_current.z);

	Fmatrix		mR;
	mR.mul		(Mdef,R);

	info.d.set		(mR.k);
	info.n.set		(mR.j);
	info.p.set		(mR.c);

	return TRUE;
}
示例#27
0
bool CControlJump::can_jump(CObject *target)
{
	const bool aggressive_jump = m_object->can_use_agressive_jump(target);

	if ( m_time_next_allowed != 0 )
	{
		// in aggressive mode we can jump after 1/3 of m_delay_after_jump
		if ( m_time_next_allowed - (int)aggressive_jump*(2*m_delay_after_jump/3) > Device.dwTimeGlobal) 
		{
			return false;
		}
	}

	Fvector source_position		= m_object->Position	();
	Fvector target_position;
	target->Center				(target_position);

	// проверка на dist
	float dist = source_position.distance_to(target_position);

	// in aggressive mode we can jump from distance >= 1
	const float test_min_distance = aggressive_jump ? _min(1.f, m_min_distance) : m_min_distance;
	if ( (dist < test_min_distance) || (dist > m_max_distance) ) return false;

	// получить вектор направлени¤ и его мир угол
	float		dir_yaw = Fvector().sub(target_position, source_position).getH();
	dir_yaw		= angle_normalize(-dir_yaw);

	// проверка на angle
	float yaw_current, yaw_target;
	m_object->control().direction().get_heading(yaw_current, yaw_target);

	if (angle_difference(yaw_current, dir_yaw) > m_max_angle) return false;
	
	// check if target on the same floor etc
	if (_abs(target_position.y-source_position.y) > m_max_height) return false;

	// проверка prepare
	if (!is_flag(SControlJumpData::ePrepareSkip) && !is_flag(SControlJumpData::eGlideOnPrepareFailed)) {
		if (!is_flag(SControlJumpData::ePrepareInMove)) {
			VERIFY(m_data.state_prepare.motion.valid());
		} else {
			VERIFY(m_data.state_prepare_in_move.motion.valid());
			VERIFY(m_data.state_prepare_in_move.velocity_mask != u32(-1));

			// try to trace distance according to prepare animation
			bool good_trace_res = false;

			// get animation time
			float time			= m_man->animation().motion_time(m_data.state_prepare_in_move.motion, m_object->Visual());
			// set acceleration and velocity
			SVelocityParam &vel	= m_object->move().get_velocity(m_data.state_prepare_in_move.velocity_mask);
			float dist = time * vel.velocity.linear;

			// check nodes in direction
			Fvector target_point;
			target_point.mad(m_object->Position(), m_object->Direction(), dist);

			if (m_man->path_builder().accessible(target_point)) {
				// нода в пр¤мой видимости?
				m_man->path_builder().restrictions().add_border(m_object->Position(), target_point);
				u32 node = ai().level_graph().check_position_in_direction(m_object->ai_location().level_vertex_id(),m_object->Position(),target_point);
				m_man->path_builder().restrictions().remove_border();
				
				if (ai().level_graph().valid_vertex_id(node) && m_man->path_builder().accessible(node)) 
					good_trace_res = true;
			}

			if (!good_trace_res) {
				// cannot prepare in move, so check if can prepare in stand state
				if (!m_data.state_prepare.motion.valid()) return false;
			}
		}
	}

	return true;
}