void target_closest_enemy::execute_leaf_goal_callback(tree::execution_occurence occ, tree::state_of_traversal& t) const { if (occ == tree::execution_occurence::LAST) return; auto& cosmos = t.step.cosm; auto subject = t.subject; auto pos = position(subject); auto& los = t.step.transient.calculated_line_of_sight.at(subject); auto& attitude = subject.get<components::attitude>(); entity_id closest_hostile_raw; float min_distance = std::numeric_limits<float>::max(); for (auto s_raw : los.visible_sentiences) { auto s = cosmos[s_raw]; auto att = calculate_attitude(s, subject); if (att == attitude_type::WANTS_TO_KILL || att == attitude_type::WANTS_TO_KNOCK_UNCONSCIOUS) { auto dist = distance_sq(s, subject); if (dist < min_distance) { closest_hostile_raw = s; min_distance = dist; } } } auto closest_hostile = cosmos[closest_hostile_raw]; attitude.currently_attacked_visible_entity = closest_hostile; if (closest_hostile.alive()) { attitude.is_alert = true; attitude.last_seen_target_position_inspected = false; attitude.last_seen_target_position = position(closest_hostile); attitude.last_seen_target_velocity = velocity(closest_hostile); } auto crosshair = subject[sub_entity_name::CHARACTER_CROSSHAIR]; if (crosshair.alive()) { auto& crosshair_offset = crosshair.get<components::crosshair>().base_offset; float vel1 = assess_projectile_velocity_of_weapon(subject[slot_function::PRIMARY_HAND].get_item_if_any()); float vel2 = assess_projectile_velocity_of_weapon(subject[slot_function::SECONDARY_HAND].get_item_if_any()); float vel = std::max(vel1, vel2); if (vel > 1.0 && closest_hostile.alive()) { vec2 leaded; if (velocity(closest_hostile).length_sq() > 1) leaded = position(closest_hostile) + velocity(closest_hostile) * distance(closest_hostile, subject) / vel;// direct_solution(position(closest_hostile), velocity(closest_hostile), vel); else leaded = position(closest_hostile); crosshair_offset = leaded - position(subject); } else if (is_entity_physical(subject)) { crosshair_offset = velocity(subject).length() > 3.0 ? velocity(subject) : vec2(10, 0); } else crosshair_offset = vec2(10, 0); } }
void draw_crosshair_lines( std::function<void(vec2, vec2, rgba)> callback, std::function<void(vec2, vec2)> dashed_line_callback, const interpolation_system& interp, const const_entity_handle crosshair, const const_entity_handle character) { if (crosshair.alive()) { const auto& cosmos = crosshair.get_cosmos(); const auto& physics = cosmos.systems_temporary.get<physics_system>(); vec2 line_from[2]; vec2 line_to[2]; const auto crosshair_pos = crosshair.viewing_transform(interp).pos; const auto guns = character.guns_wielded(); auto calculate_color = [&](const const_entity_handle target) { const auto att = calculate_attitude(character, target); if (att == attitude_type::WANTS_TO_KILL || att == attitude_type::WANTS_TO_KNOCK_UNCONSCIOUS) { return red; } else if (att == attitude_type::WANTS_TO_HEAL) { return green; } else { return cyan; } }; if (guns.size() >= 1) { const auto subject_item = guns[0]; const auto& gun = subject_item.get<components::gun>(); const auto rifle_transform = subject_item.viewing_transform(interp); const auto barrel_center = gun.calculate_barrel_center(rifle_transform); const auto muzzle = gun.calculate_muzzle_position(rifle_transform); line_from[0] = muzzle; const auto proj = crosshair_pos.get_projection_multiplier(barrel_center, muzzle); if (proj > 1.f) { line_to[0] = barrel_center + (muzzle - barrel_center) * proj; const auto raycast = physics.ray_cast_px(line_from[0], line_to[0], filters::bullet(), subject_item); auto col = cyan; if (raycast.hit) { dashed_line_callback(raycast.intersection, line_to[0]); line_to[0] = raycast.intersection; col = calculate_color(cosmos[raycast.what_entity]); } callback(line_from[0], line_to[0], col); } } if (guns.size() >= 2) { const auto subject_item = guns[1]; const auto& gun = subject_item.get<components::gun>(); const auto rifle_transform = subject_item.viewing_transform(interp); const auto barrel_center = gun.calculate_barrel_center(rifle_transform); const auto muzzle = gun.calculate_muzzle_position(rifle_transform); line_from[1] = muzzle; const auto proj = crosshair_pos.get_projection_multiplier(barrel_center, muzzle); if (proj > 1.f) { line_to[1] = barrel_center + (muzzle - barrel_center) * proj; const auto raycast = physics.ray_cast_px(line_from[1], line_to[1], filters::bullet(), subject_item); auto col = cyan; if (raycast.hit) { dashed_line_callback(raycast.intersection, line_to[1]); line_to[1] = raycast.intersection; col = calculate_color(cosmos[raycast.what_entity]); } callback(line_from[1], line_to[1], col); } } } }