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