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; }
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)); }
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)); }
// ****************************** 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; } }
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 ¶ms = 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); }
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; }
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; }
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; }
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); } }
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 (); ////////////////////////////////////////////////////////////////////////// }
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; }
/** * \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; } }
/** * \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; } }
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); }
/** * \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; } }
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); }
/** * \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 ) ); }
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); }
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; }
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); }
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; }
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; }