ed_journals/modules/exobiology/models/
spawn_source.rspub mod spawn_source_star;
pub mod target_planet;
pub mod target_system;
use strum::IntoEnumIterator;
use crate::exobiology::models::spawn_source::spawn_source_star::SpawnSourceStar;
use crate::exobiology::models::spawn_source::target_planet::TargetPlanet;
use crate::exobiology::models::spawn_source::target_system::TargetSystem;
use crate::exobiology::{SpawnCondition, Species};
use crate::galaxy::{AtmosphereDensity, AtmosphereType, Nebula, VolcanismType};
use crate::logs::scan_event::ScanEventParent;
#[derive(Debug)]
pub struct SpawnSource<'a> {
pub target_system: &'a TargetSystem,
pub target_planet: &'a TargetPlanet,
}
impl SpawnSource<'_> {
pub fn get_spawnable_species(&self) -> Vec<Species> {
Species::iter()
.filter(|species| self.can_spawn_species(species))
.collect()
}
pub fn can_spawn_species(&self, species: &Species) -> bool {
species
.spawn_conditions()
.iter()
.all(|condition| self.satisfies_spawn_condition(condition))
}
pub fn satisfies_spawn_condition(&self, condition: &SpawnCondition) -> bool {
match condition {
SpawnCondition::MinMeanTemperature(min_temp) => {
&self.target_planet.surface_temperature >= min_temp
}
SpawnCondition::MaxMeanTemperature(max_temp) => {
&self.target_planet.surface_temperature <= max_temp
}
SpawnCondition::NoAtmosphere => {
self.target_planet.atmosphere.kind == AtmosphereType::None
}
SpawnCondition::AnyThinAtmosphere => {
self.target_planet.atmosphere.density == AtmosphereDensity::Thin
}
SpawnCondition::ThinAtmosphere(atmosphere_type) => {
self.target_planet.atmosphere.density == AtmosphereDensity::Thin
&& &self.target_planet.atmosphere.kind == atmosphere_type
}
SpawnCondition::MinGravity(min_gravity) => {
&self.target_planet.gravity.as_g() >= min_gravity
}
SpawnCondition::MaxGravity(max_gravity) => {
&self.target_planet.gravity.as_g() <= max_gravity
}
SpawnCondition::PlanetClass(planet_class) => &self.target_planet.class == planet_class,
SpawnCondition::ParentStarClass(star_class) => {
self.parent_stars().any(|star| &star.class == star_class)
}
SpawnCondition::ParentStarLuminosity(star_luminosity) => self
.parent_stars()
.any(|star| &star.luminosity == star_luminosity),
SpawnCondition::MinOrEqualParentStarLuminosity(star_luminosity) => self
.parent_stars()
.any(|star| &star.luminosity >= star_luminosity),
SpawnCondition::SystemContainsPlanetClass(planet_class) => self
.target_system
.planet_classes_in_system
.contains(planet_class),
SpawnCondition::VolcanismType(volcanism_type) => {
&self.target_planet.volcanism.kind == volcanism_type
}
SpawnCondition::MinDistanceFromParentSun(min_distance) => {
&(self.target_planet.semi_major_axis / 149597870700.0) >= min_distance
}
SpawnCondition::AnyVolcanism => {
self.target_planet.volcanism.kind != VolcanismType::None
}
SpawnCondition::WithinNebulaRange(nebula_range) => {
&Nebula::closest_to(self.target_system.star_system_position)
.distance_to(self.target_system.star_system_position)
.as_ly()
<= nebula_range
}
SpawnCondition::GeologicalSignalsPresent => {
self.target_planet.geological_signals_present
}
SpawnCondition::MaterialPresence(material) => {
self.target_planet.materials.contains(material)
}
SpawnCondition::RockyComposition => {
let Some(composition) = &self.target_planet.composition else {
return false;
};
composition.rock > 0.0
}
SpawnCondition::IcyComposition => {
let Some(composition) = &self.target_planet.composition else {
return false;
};
composition.ice > 0.0
}
SpawnCondition::MetalComposition => {
let Some(composition) = &self.target_planet.composition else {
return false;
};
composition.metal > 0.0
}
SpawnCondition::Special => false,
SpawnCondition::Any(conditions) => conditions
.iter()
.any(|condition| self.satisfies_spawn_condition(condition)),
SpawnCondition::All(conditions) => conditions
.iter()
.all(|condition| self.satisfies_spawn_condition(condition)),
}
}
pub fn parent_stars(&self) -> impl Iterator<Item = &SpawnSourceStar> {
self.target_planet.parents.iter().filter_map(|parent| {
if let ScanEventParent::Star(id) = parent {
return self.target_system.stars_in_system.get(id);
}
None
})
}
}