예제 #1
0
unsigned calculate_space_occupied_with_children(const const_entity_handle item) {
	auto space_occupied = item.get<components::item>().get_space_occupied();

	if (item.find<components::container>()) {
		ensure(item.get<components::item>().charges == 1);

		for (auto& slot : item.get<components::container>().slots) {
			for (auto& entity_in_slot : slot.second.items_inside) {
				space_occupied += calculate_space_occupied_with_children(item.get_cosmos()[entity_in_slot]);
			}
		}
	}

	return space_occupied;
}
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;
}
ammunition_information calc_reloadable_ammo_info(const const_entity_handle item) {
	ammunition_information out;

	const auto maybe_magazine_slot = item[slot_function::GUN_DETACHABLE_MAGAZINE];

	if (maybe_magazine_slot.alive() && maybe_magazine_slot.has_items()) {
		const auto mag = item.get_cosmos()[maybe_magazine_slot.get_items_inside()[0]];
		const auto ammo_depo = mag[slot_function::ITEM_DEPOSIT];

		ensure(ammo_depo->has_limited_space());

		out.total_charges += count_charges_in_deposit(mag);
		out.total_ammo_space += ammo_depo->space_available;
		out.available_ammo_space += ammo_depo.calc_local_space_available();
	}

	return out;
}
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() };
}
예제 #5
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);
				}
			}
		}
	}