Merge branch 'site_rock_circle' into 'master'

site_rock_circle

See merge request veloren/veloren!4175
This commit is contained in:
Christof Petig 2023-11-10 00:31:04 +00:00
commit 424006e000
10 changed files with 156 additions and 27 deletions

View File

@ -0,0 +1,8 @@
#![enable(unwrap_newtypes)]
[
(
specifier: "world.structure.natural.rock-circle",
center: (30, 30, 4),
),
]

View File

@ -33,6 +33,7 @@ impl Site {
| SiteKind::Gnarling(_)
| SiteKind::PirateHideout(_)
| SiteKind::JungleRuin(_)
| SiteKind::RockCircle(_)
| SiteKind::Adlet(_) => Some(false),
SiteKind::DwarvenMine(_) => Some(false),
// Neutral

View File

@ -276,7 +276,7 @@ impl Civs {
let world_dims = ctx.sim.get_aabr();
for _ in 0..initial_civ_count * 3 {
attempt(5, || {
let (loc, kind) = match ctx.rng.gen_range(0..79) {
let (loc, kind) = match ctx.rng.gen_range(0..85) {
0..=4 => {
if index.features().site2_giant_trees {
(
@ -352,7 +352,17 @@ impl Civs {
)?,
SiteKind::JungleRuin,
),
/*43..=48 => (
43..=49 => (
find_site_loc(
&mut ctx,
&ProximityRequirementsBuilder::new()
.avoid_all_of(this.rock_circle_enemies(), 40)
.finalize(&world_dims),
&SiteKind::RockCircle,
)?,
SiteKind::RockCircle,
),
/*50..=55 => (
find_site_loc(
&mut ctx,
&ProximityRequirementsBuilder::new()
@ -362,7 +372,7 @@ impl Civs {
)?,
SiteKind::DwarvenMine,
),
49..=54 => (
56..=61 => (
find_site_loc(
&mut ctx,
&ProximityRequirementsBuilder::new()
@ -373,7 +383,7 @@ impl Civs {
)?,
SiteKind::Castle,
),
55..=60 => (SiteKind::Citadel, (&castle_enemies, 20)),
62..=67 => (SiteKind::Citadel, (&castle_enemies, 20)),
*/
_ => (
find_site_loc(
@ -422,6 +432,7 @@ impl Civs {
SiteKind::Bridge(_, _) => (0, 0.0),
SiteKind::Adlet => (16i32, 0.0),
SiteKind::PirateHideout => (8i32, 3.0),
SiteKind::RockCircle => (8i32, 3.0),
//SiteKind::DwarvenMine => (8i32, 3.0),
};
@ -540,6 +551,9 @@ impl Civs {
SiteKind::JungleRuin => WorldSite::jungle_ruin(
site2::Site::generate_jungle_ruin(&Land::from_sim(ctx.sim), &mut rng, wpos),
),
SiteKind::RockCircle => WorldSite::rock_circle(
site2::Site::generate_rock_circle(&Land::from_sim(ctx.sim), &mut rng, wpos),
),
SiteKind::DesertCity => WorldSite::desert_city(
site2::Site::generate_desert_city(&Land::from_sim(ctx.sim), &mut rng, wpos),
),
@ -1510,6 +1524,13 @@ impl Civs {
_ => Some(s.center),
})
}
fn rock_circle_enemies(&self) -> impl Iterator<Item = Vec2<i32>> + '_ {
self.sites().filter_map(|s| match s.kind {
SiteKind::Tree | SiteKind::GiantTree => None,
_ => Some(s.center),
})
}
}
/// Attempt to find a path between two locations
@ -1842,6 +1863,7 @@ pub enum SiteKind {
Bridge(Vec2<i32>, Vec2<i32>),
Adlet,
PirateHideout,
RockCircle,
//DwarvenMine,
JungleRuin,
}
@ -1922,6 +1944,7 @@ impl SiteKind {
SiteKind::JungleRuin => {
matches!(chunk.get_biome(), BiomeKind::Jungle)
},
SiteKind::RockCircle => !chunk.near_cliffs() && !chunk.river.near_water(),
SiteKind::DesertCity => {
(0.9..1.0).contains(&chunk.temp) && !chunk.near_cliffs() && suitable_for_town()
},

View File

@ -38,7 +38,6 @@ use vek::*;
pub enum Spot {
DwarvenGrave,
SaurokAltar,
RockCircle,
MyrmidonTemple,
GnarlingTotem,
WitchHouse,
@ -175,19 +174,6 @@ impl Spot {
},
false,
);
Self::generate_spots(
Spot::RockCircle,
world,
0.5,
|g, c| {
g < 0.1
&& !c.near_cliffs()
&& !c.river.near_water()
&& !c.path.0.is_way()
&& c.sites.is_empty()
},
false,
);
Self::generate_spots(
Spot::MyrmidonTemple,
world,
@ -573,11 +559,6 @@ pub fn apply_spots_to(canvas: &mut Canvas, _dynamic_rng: &mut impl Rng) {
(2..8, "common.entity.wild.aggressive.mighty_saurok"),
],
},
Spot::RockCircle => SpotConfig {
base_structures: Some("spots.rock-circle"),
entity_radius: 20.0,
entities: &[(-8..2, "common.entity.wild.aggressive.dullahan")],
},
Spot::MyrmidonTemple => SpotConfig {
base_structures: Some("spots.myrmidon-temple"),
entity_radius: 10.0,

View File

@ -176,14 +176,14 @@ impl World {
.civs()
.sites
.iter()
.filter(|(_, site)| !matches!(&site.kind, civ::SiteKind::PirateHideout | civ::SiteKind::JungleRuin))
.filter(|(_, site)| !matches!(&site.kind, civ::SiteKind::PirateHideout | civ::SiteKind::JungleRuin | civ::SiteKind::RockCircle))
.map(|(_, site)| {
world_msg::SiteInfo {
id: site.site_tmp.map(|i| i.id()).unwrap_or_default(),
name: site.site_tmp.map(|id| index.sites[id].name().to_string()),
// TODO: Probably unify these, at some point
kind: match &site.kind {
civ::SiteKind::Settlement | civ::SiteKind::Refactor | civ::SiteKind::CliffTown | civ::SiteKind::SavannahPit | civ::SiteKind::CoastalTown | civ::SiteKind::DesertCity | civ::SiteKind::PirateHideout | civ::SiteKind::JungleRuin => world_msg::SiteKind::Town,
civ::SiteKind::Settlement | civ::SiteKind::Refactor | civ::SiteKind::CliffTown | civ::SiteKind::SavannahPit | civ::SiteKind::CoastalTown | civ::SiteKind::DesertCity | civ::SiteKind::PirateHideout | civ::SiteKind::JungleRuin | civ::SiteKind::RockCircle => world_msg::SiteKind::Town,
civ::SiteKind::Dungeon => world_msg::SiteKind::Dungeon {
difficulty: match site.site_tmp.map(|id| &index.sites[id].kind) {
Some(SiteKind::Dungeon(d)) => d.dungeon_difficulty().unwrap_or(0),

View File

@ -136,6 +136,7 @@ impl Environment {
SiteKind::DwarvenMine(_) => {},
SiteKind::Bridge(_) => {},
SiteKind::PirateHideout(_) => {},
SiteKind::RockCircle(_) => {},
}
}
if towns.valid() {

View File

@ -79,6 +79,7 @@ pub enum SiteKind {
Adlet(site2::Site),
PirateHideout(site2::Site),
JungleRuin(site2::Site),
RockCircle(site2::Site),
}
impl Site {
@ -159,6 +160,13 @@ impl Site {
}
}
pub fn rock_circle(rc: site2::Site) -> Self {
Self {
kind: SiteKind::RockCircle(rc),
economy: Economy::default(),
}
}
pub fn desert_city(dc: site2::Site) -> Self {
Self {
kind: SiteKind::DesertCity(dc),
@ -212,6 +220,7 @@ impl Site {
SiteKind::CoastalTown(ct) => ct.radius(),
SiteKind::PirateHideout(ph) => ph.radius(),
SiteKind::JungleRuin(jr) => jr.radius(),
SiteKind::RockCircle(rc) => rc.radius(),
SiteKind::DesertCity(dc) => dc.radius(),
SiteKind::ChapelSite(p) => p.radius(),
SiteKind::DwarvenMine(dm) => dm.radius(),
@ -234,6 +243,7 @@ impl Site {
SiteKind::CoastalTown(ct) => ct.origin,
SiteKind::PirateHideout(ph) => ph.origin,
SiteKind::JungleRuin(jr) => jr.origin,
SiteKind::RockCircle(rc) => rc.origin,
SiteKind::DesertCity(dc) => dc.origin,
SiteKind::ChapelSite(p) => p.origin,
SiteKind::DwarvenMine(dm) => dm.origin,
@ -256,6 +266,7 @@ impl Site {
SiteKind::CoastalTown(ct) => ct.spawn_rules(wpos),
SiteKind::PirateHideout(ph) => ph.spawn_rules(wpos),
SiteKind::JungleRuin(jr) => jr.spawn_rules(wpos),
SiteKind::RockCircle(rc) => rc.spawn_rules(wpos),
SiteKind::DesertCity(dc) => dc.spawn_rules(wpos),
SiteKind::ChapelSite(p) => p.spawn_rules(wpos),
SiteKind::DwarvenMine(dm) => dm.spawn_rules(wpos),
@ -278,6 +289,7 @@ impl Site {
SiteKind::CoastalTown(ct) => ct.name(),
SiteKind::PirateHideout(ph) => ph.name(),
SiteKind::JungleRuin(jr) => jr.name(),
SiteKind::RockCircle(rc) => rc.name(),
SiteKind::DesertCity(dc) => dc.name(),
SiteKind::ChapelSite(p) => p.name(),
SiteKind::DwarvenMine(dm) => dm.name(),
@ -320,6 +332,7 @@ impl Site {
SiteKind::CoastalTown(ct) => ct.render(canvas, dynamic_rng),
SiteKind::PirateHideout(ph) => ph.render(canvas, dynamic_rng),
SiteKind::JungleRuin(jr) => jr.render(canvas, dynamic_rng),
SiteKind::RockCircle(rc) => rc.render(canvas, dynamic_rng),
SiteKind::DesertCity(dc) => dc.render(canvas, dynamic_rng),
SiteKind::ChapelSite(p) => p.render(canvas, dynamic_rng),
SiteKind::DwarvenMine(dm) => dm.render(canvas, dynamic_rng),
@ -355,6 +368,7 @@ impl Site {
SiteKind::CoastalTown(_) => {},
SiteKind::PirateHideout(_) => {},
SiteKind::JungleRuin(_) => {},
SiteKind::RockCircle(_) => {},
SiteKind::DesertCity(_) => {},
SiteKind::ChapelSite(p) => p.apply_supplement(dynamic_rng, wpos2d, supplement),
SiteKind::DwarvenMine(dm) => dm.apply_supplement(dynamic_rng, wpos2d, supplement),
@ -391,6 +405,7 @@ impl Site {
SiteKind::CoastalTown(site2) => Some(site2),
SiteKind::PirateHideout(site2) => Some(site2),
SiteKind::JungleRuin(site2) => Some(site2),
SiteKind::RockCircle(site2) => Some(site2),
SiteKind::Tree(_) => None,
SiteKind::DesertCity(site2) => Some(site2),
SiteKind::ChapelSite(site2) => Some(site2),

View File

@ -1395,6 +1395,37 @@ impl Site {
site
}
pub fn generate_rock_circle(land: &Land, rng: &mut impl Rng, origin: Vec2<i32>) -> Self {
let mut rng = reseed(rng);
let mut site = Site {
origin,
name: "".to_string(),
..Site::default()
};
let size = 8.0 as i32;
let aabr = Aabr {
min: Vec2::broadcast(-size),
max: Vec2::broadcast(size),
};
{
let rock_circle = plot::RockCircle::generate(land, &mut reseed(&mut rng), &site, aabr);
let rock_circle_alt = rock_circle.alt;
let plot = site.create_plot(Plot {
kind: PlotKind::RockCircle(rock_circle),
root_tile: aabr.center(),
tiles: aabr_tiles(aabr).collect(),
seed: rng.gen(),
});
site.blit_aabr(aabr, Tile {
kind: TileKind::Building,
plot: Some(plot),
hard_alt: Some(rock_circle_alt),
});
}
site
}
pub fn generate_bridge(
land: &Land,
index: IndexRef,
@ -1755,6 +1786,7 @@ impl Site {
PlotKind::PirateHideout(pirate_hideout) => {
pirate_hideout.render_collect(self, canvas)
},
PlotKind::RockCircle(rock_circle) => rock_circle.render_collect(self, canvas),
PlotKind::Plaza | PlotKind::Road(_) => continue,
// _ => continue, Avoid using a wildcard here!!
};

View File

@ -16,6 +16,7 @@ mod gnarling;
mod house;
mod jungle_ruin;
mod pirate_hideout;
mod rock_circle;
mod savannah_hut;
mod savannah_pit;
mod savannah_workshop;
@ -29,8 +30,9 @@ pub use self::{
desert_city_multiplot::DesertCityMultiPlot, desert_city_temple::DesertCityTemple,
dungeon::Dungeon, dwarven_mine::DwarvenMine, giant_tree::GiantTree,
gnarling::GnarlingFortification, house::House, jungle_ruin::JungleRuin,
pirate_hideout::PirateHideout, savannah_hut::SavannahHut, savannah_pit::SavannahPit,
savannah_workshop::SavannahWorkshop, sea_chapel::SeaChapel, workshop::Workshop,
pirate_hideout::PirateHideout, rock_circle::RockCircle, savannah_hut::SavannahHut,
savannah_pit::SavannahPit, savannah_workshop::SavannahWorkshop, sea_chapel::SeaChapel,
workshop::Workshop,
};
use super::*;
@ -95,5 +97,6 @@ pub enum PlotKind {
SavannahWorkshop(SavannahWorkshop),
Bridge(Bridge),
PirateHideout(PirateHideout),
RockCircle(RockCircle),
//DwarvenMine(DwarvenMine),
}

View File

@ -0,0 +1,65 @@
use super::*;
use crate::{
assets::AssetHandle,
site2::gen::PrimitiveTransform,
util::{sampler::Sampler, RandomField},
Land,
};
use common::{
generation::EntityInfo,
terrain::{Structure as PrefabStructure, StructuresGroup},
};
use lazy_static::lazy_static;
use rand::prelude::*;
use vek::*;
pub struct RockCircle {
bounds: Aabr<i32>,
pub(crate) alt: i32,
}
impl RockCircle {
pub fn generate(land: &Land, _rng: &mut impl Rng, site: &Site, tile_aabr: Aabr<i32>) -> Self {
let bounds = Aabr {
min: site.tile_wpos(tile_aabr.min),
max: site.tile_wpos(tile_aabr.max),
};
Self {
bounds,
alt: land.get_alt_approx(site.tile_center_wpos(tile_aabr.center())) as i32 + 2,
}
}
}
impl Structure for RockCircle {
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"render_rock_circle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_rock_circle_hideout")]
fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
let center = self.bounds.center();
let base = land.get_alt_approx(center) as i32;
let mut thread_rng = thread_rng();
let model_pos = center.with_z(base);
// model
lazy_static! {
pub static ref MODEL: AssetHandle<StructuresGroup> =
PrefabStructure::load_group("site_structures.rock_circle.rock_circle");
}
let rng = RandomField::new(0).get(model_pos) % 10;
let model = MODEL.read();
let model = model[rng as usize % model.len()].clone();
painter
.prim(Primitive::Prefab(Box::new(model.clone())))
.translate(model_pos)
.fill(Fill::Prefab(Box::new(model), model_pos, rng));
// npcs
if thread_rng.gen_range(0..=8) < 1 {
// dullahan
painter.spawn(
EntityInfo::at(center.with_z(base + 2).as_())
.with_asset_expect("common.entity.wild.aggressive.dullahan", &mut thread_rng),
)
}
}
}