identified_danger assess_danger( const const_entity_handle& victim, const const_entity_handle& danger ) { identified_danger result; const auto* const sentience = victim.find<components::sentience>(); if (!sentience) { return result; } result.danger = danger; const auto* const missile = danger.find<invariants::missile>(); const auto* const attitude = danger.find<components::attitude>(); if ((!missile && !attitude) || (missile && danger.get<components::sender>().is_sender_subject(victim))) { return result; } const auto victim_pos = victim.get_logic_transform().pos; const auto danger_pos = danger.get_logic_transform().pos; const auto danger_vel = danger.get_owner_of_colliders().get_effective_velocity(); const auto danger_dir = (danger_pos - victim_pos); const auto danger_distance = danger_dir.length(); result.recommended_evasion = augs::danger_avoidance(victim_pos, danger_pos, danger_vel); result.recommended_evasion.normalize(); const auto& sentience_def = victim.get<invariants::sentience>(); const auto comfort_zone = sentience_def.comfort_zone; const auto comfort_zone_disturbance_ratio = augs::disturbance(danger_distance, comfort_zone); if (missile) { result.amount += comfort_zone_disturbance_ratio * missile->damage.base*4; } if (attitude) { const auto att = calc_attitude(danger, victim); if (is_hostile(att)) { result.amount += comfort_zone_disturbance_ratio * sentience_def.danger_amount_from_hostile_attitude; } } return result; }
entity_id get_closest_hostile( const const_entity_handle subject, const const_entity_handle subject_attitude, const real32 radius, const b2Filter filter ) { const auto& cosm = subject.get_cosmos(); const auto si = cosm.get_si(); const auto& physics = cosm.get_solvable_inferred().physics; const auto transform = subject.get_logic_transform(); entity_id closest_hostile; auto min_distance = std::numeric_limits<real32>::max(); if (subject_attitude.alive()) { const auto subject_attitude_transform = subject_attitude.get_logic_transform(); physics.for_each_in_aabb( si, transform.pos - vec2(radius, radius), transform.pos + vec2(radius, radius), filter, [&](const b2Fixture& fix) { const const_entity_handle s = cosm[get_body_entity_that_owns(fix)]; if (s != subject && s.has<components::attitude>() && !sentient_and_unconscious(s)) { const auto calculated_attitude = calc_attitude(s, subject_attitude); if (is_hostile(calculated_attitude)) { const auto dist = (s.get_logic_transform().pos - subject_attitude_transform.pos).length_sq(); if (dist < min_distance) { closest_hostile = s; min_distance = dist; } } } return callback_result::CONTINUE; } ); } return closest_hostile; }
std::vector<entity_id> get_closest_hostiles( const const_entity_handle subject, const const_entity_handle subject_attitude, const real32 radius, const b2Filter filter ) { const auto& cosm = subject.get_cosmos(); const auto si = cosm.get_si(); const auto& physics = cosm.get_solvable_inferred().physics; const auto transform = subject.get_logic_transform(); struct hostile_entry { entity_id s; real32 dist = 0.f; bool operator<(const hostile_entry& b) const { return dist < b.dist; } bool operator==(const hostile_entry& b) const { return s == b.s; } operator entity_id() const { return s; } }; std::vector<hostile_entry> hostiles; if (subject_attitude.alive()) { const auto subject_attitude_transform = subject_attitude.get_logic_transform(); physics.for_each_in_aabb( si, transform.pos - vec2(radius, radius), transform.pos + vec2(radius, radius), filter, [&](const b2Fixture& fix) { const const_entity_handle s = cosm[get_body_entity_that_owns(fix)]; if (s != subject && s.has<components::attitude>()) { const auto calculated_attitude = calc_attitude(s, subject_attitude); if (is_hostile(calculated_attitude)) { const auto dist = (s.get_logic_transform().pos - subject_attitude_transform.pos).length_sq(); hostile_entry new_entry; new_entry.s = s; new_entry.dist = dist; hostiles.push_back(new_entry); } } return callback_result::CONTINUE; } ); } sort_range(hostiles); remove_duplicates_from_sorted(hostiles); return { hostiles.begin(), hostiles.end() }; }