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); }
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); } }
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; }
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); }
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; }
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 ] ); }
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); } }
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); } }
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); }