mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Calendar based gear for villagers
This commit is contained in:
parent
ba02d083da
commit
9b485456eb
@ -1,8 +1,12 @@
|
|||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
|
||||||
#![enable(implicit_some)]
|
#![enable(implicit_some)]
|
||||||
(
|
(
|
||||||
head: Item("common.items.armor.pirate.hat"),
|
head: Seasonal([
|
||||||
|
(Some(Christmas), Choice([
|
||||||
|
(1, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||||
|
(1, Some(Item("common.items.armor.pirate.hat")))
|
||||||
|
])),
|
||||||
|
(None, Item("common.items.armor.pirate.hat")),
|
||||||
|
]),
|
||||||
shoulders: Item("common.items.armor.mail.orichalcum.shoulder"),
|
shoulders: Item("common.items.armor.mail.orichalcum.shoulder"),
|
||||||
chest: Item("common.items.armor.mail.orichalcum.chest"),
|
chest: Item("common.items.armor.mail.orichalcum.chest"),
|
||||||
gloves: Item("common.items.armor.mail.orichalcum.hand"),
|
gloves: Item("common.items.armor.mail.orichalcum.hand"),
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
|
||||||
#![enable(implicit_some)]
|
#![enable(implicit_some)]
|
||||||
(
|
(
|
||||||
head: Choice([
|
head: Seasonal([
|
||||||
|
(Some(Christmas), Choice([
|
||||||
|
(9, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||||
(3, Item("common.items.armor.misc.head.straw")),
|
(3, Item("common.items.armor.misc.head.straw")),
|
||||||
(3, Item("common.items.armor.misc.head.bamboo_twig")),
|
(3, Item("common.items.armor.misc.head.bamboo_twig")),
|
||||||
(2, None),
|
(2, None),
|
||||||
|
])),
|
||||||
|
(None, Choice([
|
||||||
|
(3, Item("common.items.armor.misc.head.straw")),
|
||||||
|
(3, Item("common.items.armor.misc.head.bamboo_twig")),
|
||||||
|
(2, None),
|
||||||
|
])),
|
||||||
]),
|
]),
|
||||||
chest: Choice([
|
chest: Choice([
|
||||||
(1, Item("common.items.armor.misc.chest.worker_green_0")),
|
(1, Item("common.items.armor.misc.chest.worker_green_0")),
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
|
||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.lantern.blue_0"))),
|
|
||||||
//(1.0, Some(Item("common.items.lantern.polaris"))),
|
|
||||||
//(2.0, Some(Item("common.items.lantern.red_0"))),
|
|
||||||
//(2.0, Some(Item("common.items.lantern.green_0"))),
|
|
||||||
#![enable(implicit_some)]
|
#![enable(implicit_some)]
|
||||||
(
|
(
|
||||||
head: Choice([
|
head: Seasonal([
|
||||||
(1, Item("common.items.armor.misc.head.helmet")),
|
(Some(Christmas), Choice([
|
||||||
|
(1, Some(Item("common.items.armor.misc.head.helmet"))),
|
||||||
|
(1, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||||
|
])),
|
||||||
|
(None, Item("common.items.armor.misc.head.helmet")),
|
||||||
]),
|
]),
|
||||||
shoulders: Item("common.items.armor.leather_plate.shoulder"),
|
shoulders: Item("common.items.armor.leather_plate.shoulder"),
|
||||||
chest: Item("common.items.armor.leather_plate.chest"),
|
chest: Item("common.items.armor.leather_plate.chest"),
|
||||||
@ -16,8 +13,18 @@
|
|||||||
belt: Item("common.items.armor.leather_plate.belt"),
|
belt: Item("common.items.armor.leather_plate.belt"),
|
||||||
legs: Item("common.items.armor.leather_plate.pants"),
|
legs: Item("common.items.armor.leather_plate.pants"),
|
||||||
feet: Item("common.items.armor.leather_plate.foot"),
|
feet: Item("common.items.armor.leather_plate.foot"),
|
||||||
lantern: Choice([
|
lantern: Seasonal([
|
||||||
|
(Some(Christmas), Choice([
|
||||||
|
(1, Some(Item("common.items.lantern.blue_0"))),
|
||||||
|
(1, Some(Item("common.items.lantern.polaris"))),
|
||||||
|
(2, Some(Item("common.items.lantern.red_0"))),
|
||||||
|
(2, Some(Item("common.items.lantern.green_0"))),
|
||||||
(1, Item("common.items.lantern.black_0")),
|
(1, Item("common.items.lantern.black_0")),
|
||||||
(2, None),
|
(2, None),
|
||||||
]),
|
])),
|
||||||
|
(None, Choice([
|
||||||
|
(1, Item("common.items.lantern.black_0")),
|
||||||
|
(2, None),
|
||||||
|
])),
|
||||||
|
])
|
||||||
)
|
)
|
@ -1,11 +1,17 @@
|
|||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
|
||||||
#![enable(implicit_some)]
|
#![enable(implicit_some)]
|
||||||
(
|
(
|
||||||
head: Choice([
|
head: Seasonal([
|
||||||
|
(Some(Christmas), Choice([
|
||||||
|
(9, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||||
(3, Item("common.items.armor.misc.head.straw")),
|
(3, Item("common.items.armor.misc.head.straw")),
|
||||||
(3, Item("common.items.armor.misc.head.hood")),
|
(3, Item("common.items.armor.misc.head.hood")),
|
||||||
(2, None),
|
(2, None),
|
||||||
|
])),
|
||||||
|
(None, Choice([
|
||||||
|
(3, Item("common.items.armor.misc.head.straw")),
|
||||||
|
(3, Item("common.items.armor.misc.head.hood")),
|
||||||
|
(2, None),
|
||||||
|
])),
|
||||||
]),
|
]),
|
||||||
chest: Choice([
|
chest: Choice([
|
||||||
(1, Item("common.items.armor.twigs.chest")),
|
(1, Item("common.items.armor.twigs.chest")),
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
|
||||||
#![enable(implicit_some)]
|
#![enable(implicit_some)]
|
||||||
(
|
(
|
||||||
head: Choice([
|
head: Seasonal([
|
||||||
|
(Some(Christmas), Choice([
|
||||||
|
(15, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||||
(6, None),
|
(6, None),
|
||||||
(2, Item("common.items.armor.misc.head.straw")),
|
(2, Item("common.items.armor.misc.head.straw")),
|
||||||
(3, Item("common.items.armor.misc.head.hood")),
|
(3, Item("common.items.armor.misc.head.hood")),
|
||||||
(3, Item("common.items.armor.misc.head.hood_dark")),
|
(3, Item("common.items.armor.misc.head.hood_dark")),
|
||||||
|
])),
|
||||||
|
(None, Choice([
|
||||||
|
(6, None),
|
||||||
|
(2, Item("common.items.armor.misc.head.straw")),
|
||||||
|
(3, Item("common.items.armor.misc.head.hood")),
|
||||||
|
(3, Item("common.items.armor.misc.head.hood_dark")),
|
||||||
|
])),
|
||||||
]),
|
]),
|
||||||
chest: Choice([
|
chest: Choice([
|
||||||
(1, Item("common.items.armor.hide.leather.chest")),
|
(1, Item("common.items.armor.hide.leather.chest")),
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
|
||||||
#![enable(implicit_some)]
|
#![enable(implicit_some)]
|
||||||
(
|
(
|
||||||
head: Choice([
|
head: Seasonal([
|
||||||
(1, Item("common.items.armor.misc.head.headband")),
|
(Some(Christmas), Choice([
|
||||||
|
(3, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||||
(2, None),
|
(2, None),
|
||||||
|
(1, Item("common.items.armor.misc.head.headband")),
|
||||||
|
])),
|
||||||
|
(None, Choice([
|
||||||
|
(2, None),
|
||||||
|
(1, Item("common.items.armor.misc.head.headband")),
|
||||||
|
])),
|
||||||
]),
|
]),
|
||||||
shoulders: Choice([
|
shoulders: Choice([
|
||||||
(1, Item("common.items.armor.cloth_blue.shoulder_0")),
|
(1, Item("common.items.armor.cloth_blue.shoulder_0")),
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
// Christmas event
|
|
||||||
//(1.0, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
|
||||||
#![enable(implicit_some)]
|
#![enable(implicit_some)]
|
||||||
(
|
(
|
||||||
head: Choice([
|
head: Seasonal([
|
||||||
|
(Some(Christmas), Choice([
|
||||||
|
(3, Some(Item("common.items.calendar.christmas.armor.misc.head.woolly_wintercap"))),
|
||||||
(1, Item("common.items.armor.misc.head.straw")),
|
(1, Item("common.items.armor.misc.head.straw")),
|
||||||
(2, None),
|
(2, None),
|
||||||
|
])),
|
||||||
|
(None, Choice([
|
||||||
|
(1, Item("common.items.armor.misc.head.straw")),
|
||||||
|
(2, None),
|
||||||
|
])),
|
||||||
]),
|
]),
|
||||||
chest: Choice([
|
chest: Choice([
|
||||||
(1, Item("common.items.armor.misc.chest.worker_green_0")),
|
(1, Item("common.items.armor.misc.chest.worker_green_0")),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
assets::{self, AssetExt},
|
assets::{self, AssetExt},
|
||||||
|
calendar::{Calendar, CalendarEvent},
|
||||||
comp::{
|
comp::{
|
||||||
arthropod, biped_large, biped_small, bird_large, bird_medium, golem,
|
arthropod, biped_large, biped_small, bird_large, bird_medium, golem,
|
||||||
inventory::{
|
inventory::{
|
||||||
@ -9,7 +10,7 @@ use crate::{
|
|||||||
item::{self, Item},
|
item::{self, Item},
|
||||||
object, quadruped_low, quadruped_medium, quadruped_small, theropod, Body,
|
object, quadruped_low, quadruped_medium, quadruped_small, theropod, Body,
|
||||||
},
|
},
|
||||||
resources::Time,
|
resources::{Time, TimeOfDay},
|
||||||
trade::SiteInformation,
|
trade::SiteInformation,
|
||||||
};
|
};
|
||||||
use rand::{self, distributions::WeightedError, seq::SliceRandom, Rng};
|
use rand::{self, distributions::WeightedError, seq::SliceRandom, Rng};
|
||||||
@ -48,10 +49,15 @@ enum ItemSpec {
|
|||||||
hands: Option<item::tool::Hands>,
|
hands: Option<item::tool::Hands>,
|
||||||
},
|
},
|
||||||
Choice(Vec<(Weight, Option<ItemSpec>)>),
|
Choice(Vec<(Weight, Option<ItemSpec>)>),
|
||||||
|
Seasonal(Vec<(Option<CalendarEvent>, ItemSpec)>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemSpec {
|
impl ItemSpec {
|
||||||
fn try_to_item(&self, rng: &mut impl Rng) -> Result<Option<Item>, SpecError> {
|
fn try_to_item(
|
||||||
|
&self,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Result<Option<Item>, SpecError> {
|
||||||
match self {
|
match self {
|
||||||
ItemSpec::Item(item_asset) => {
|
ItemSpec::Item(item_asset) => {
|
||||||
let item = Item::new_from_asset(item_asset).map_err(SpecError::ItemAssetError)?;
|
let item = Item::new_from_asset(item_asset).map_err(SpecError::ItemAssetError)?;
|
||||||
@ -63,7 +69,7 @@ impl ItemSpec {
|
|||||||
.map_err(SpecError::ItemChoiceError)?;
|
.map_err(SpecError::ItemChoiceError)?;
|
||||||
|
|
||||||
let item = if let Some(item_spec) = item_spec {
|
let item = if let Some(item_spec) = item_spec {
|
||||||
item_spec.try_to_item(rng)?
|
item_spec.try_to_item(rng, time)?
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -76,12 +82,28 @@ impl ItemSpec {
|
|||||||
} => item::modular::random_weapon(*tool, *material, *hands, rng)
|
} => item::modular::random_weapon(*tool, *material, *hands, rng)
|
||||||
.map(Some)
|
.map(Some)
|
||||||
.map_err(SpecError::ModularWeaponCreationError),
|
.map_err(SpecError::ModularWeaponCreationError),
|
||||||
|
ItemSpec::Seasonal(specs) => specs
|
||||||
|
.iter()
|
||||||
|
.find_map(|(season, spec)| match (season, time) {
|
||||||
|
(Some(season), Some((_time, calendar))) => {
|
||||||
|
if calendar.is_event(*season) {
|
||||||
|
Some(spec.try_to_item(rng, time))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(Some(_season), None) => None,
|
||||||
|
(None, _) => Some(spec.try_to_item(rng, time)),
|
||||||
|
})
|
||||||
|
.unwrap_or(Ok(None)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if ItemSpec is valid and can be turned into Item
|
// Check if ItemSpec is valid and can be turned into Item
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn validate(&self) -> Result<(), ValidationError> {
|
fn validate(&self) -> Result<(), ValidationError> {
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
match self {
|
match self {
|
||||||
ItemSpec::Item(item_asset) => Item::new_from_asset(item_asset)
|
ItemSpec::Item(item_asset) => Item::new_from_asset(item_asset)
|
||||||
@ -103,6 +125,9 @@ impl ItemSpec {
|
|||||||
} => item::modular::random_weapon(*tool, *material, *hands, &mut rng)
|
} => item::modular::random_weapon(*tool, *material, *hands, &mut rng)
|
||||||
.map(drop)
|
.map(drop)
|
||||||
.map_err(ValidationError::ModularWeaponCreationError),
|
.map_err(ValidationError::ModularWeaponCreationError),
|
||||||
|
ItemSpec::Seasonal(specs) => {
|
||||||
|
specs.iter().try_for_each(|(_season, spec)| spec.validate())
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,10 +141,14 @@ enum Hands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Hands {
|
impl Hands {
|
||||||
fn try_to_pair(&self, rng: &mut impl Rng) -> Result<(Option<Item>, Option<Item>), SpecError> {
|
fn try_to_pair(
|
||||||
|
&self,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Result<(Option<Item>, Option<Item>), SpecError> {
|
||||||
match self {
|
match self {
|
||||||
Hands::InHands((mainhand, offhand)) => {
|
Hands::InHands((mainhand, offhand)) => {
|
||||||
let mut from_spec = |i: &ItemSpec| i.try_to_item(rng);
|
let mut from_spec = |i: &ItemSpec| i.try_to_item(rng, time);
|
||||||
|
|
||||||
let mainhand = mainhand.as_ref().map(&mut from_spec).transpose()?.flatten();
|
let mainhand = mainhand.as_ref().map(&mut from_spec).transpose()?.flatten();
|
||||||
let offhand = offhand.as_ref().map(&mut from_spec).transpose()?.flatten();
|
let offhand = offhand.as_ref().map(&mut from_spec).transpose()?.flatten();
|
||||||
@ -130,7 +159,7 @@ impl Hands {
|
|||||||
.choose_weighted(rng, |(weight, _)| *weight)
|
.choose_weighted(rng, |(weight, _)| *weight)
|
||||||
.map_err(SpecError::ItemChoiceError)?;
|
.map_err(SpecError::ItemChoiceError)?;
|
||||||
|
|
||||||
pair_spec.try_to_pair(rng)
|
pair_spec.try_to_pair(rng, time)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -893,14 +922,22 @@ impl LoadoutBuilder {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
/// Construct new `LoadoutBuilder` from `asset_specifier`
|
/// Construct new `LoadoutBuilder` from `asset_specifier`
|
||||||
/// Will panic if asset is broken
|
/// Will panic if asset is broken
|
||||||
pub fn from_asset_expect(asset_specifier: &str, rng: &mut impl Rng) -> Self {
|
pub fn from_asset_expect(
|
||||||
Self::from_asset(asset_specifier, rng).expect("failed to load loadut config")
|
asset_specifier: &str,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Self {
|
||||||
|
Self::from_asset(asset_specifier, rng, time).expect("failed to load loadut config")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct new `LoadoutBuilder` from `asset_specifier`
|
/// Construct new `LoadoutBuilder` from `asset_specifier`
|
||||||
pub fn from_asset(asset_specifier: &str, rng: &mut impl Rng) -> Result<Self, SpecError> {
|
pub fn from_asset(
|
||||||
|
asset_specifier: &str,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Result<Self, SpecError> {
|
||||||
let loadout = Self::empty();
|
let loadout = Self::empty();
|
||||||
loadout.with_asset(asset_specifier, rng)
|
loadout.with_asset(asset_specifier, rng, time)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -919,17 +956,22 @@ impl LoadoutBuilder {
|
|||||||
pub fn from_loadout_spec(
|
pub fn from_loadout_spec(
|
||||||
loadout_spec: LoadoutSpec,
|
loadout_spec: LoadoutSpec,
|
||||||
rng: &mut impl Rng,
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> Result<Self, SpecError> {
|
) -> Result<Self, SpecError> {
|
||||||
let loadout = Self::empty();
|
let loadout = Self::empty();
|
||||||
loadout.with_loadout_spec(loadout_spec, rng)
|
loadout.with_loadout_spec(loadout_spec, rng, time)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
/// Construct new `LoadoutBuilder` from `asset_specifier`
|
/// Construct new `LoadoutBuilder` from `asset_specifier`
|
||||||
///
|
///
|
||||||
/// Will panic if asset is broken
|
/// Will panic if asset is broken
|
||||||
pub fn from_loadout_spec_expect(loadout_spec: LoadoutSpec, rng: &mut impl Rng) -> Self {
|
pub fn from_loadout_spec_expect(
|
||||||
Self::from_loadout_spec(loadout_spec, rng).expect("failed to load loadout spec")
|
loadout_spec: LoadoutSpec,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Self {
|
||||||
|
Self::from_loadout_spec(loadout_spec, rng, time).expect("failed to load loadout spec")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use = "Method consumes builder and returns updated builder."]
|
#[must_use = "Method consumes builder and returns updated builder."]
|
||||||
@ -1045,14 +1087,18 @@ impl LoadoutBuilder {
|
|||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
match preset {
|
match preset {
|
||||||
Preset::HuskSummon => {
|
Preset::HuskSummon => {
|
||||||
self = self.with_asset_expect("common.loadout.dungeon.cultist.husk", rng);
|
self = self.with_asset_expect("common.loadout.dungeon.cultist.husk", rng, None);
|
||||||
},
|
},
|
||||||
Preset::BorealSummon => {
|
Preset::BorealSummon => {
|
||||||
self = self.with_asset_expect("common.loadout.world.boreal.boreal_warrior", rng);
|
self =
|
||||||
|
self.with_asset_expect("common.loadout.world.boreal.boreal_warrior", rng, None);
|
||||||
},
|
},
|
||||||
Preset::ClockworkSummon => {
|
Preset::ClockworkSummon => {
|
||||||
self =
|
self = self.with_asset_expect(
|
||||||
self.with_asset_expect("common.loadout.dungeon.dwarven_quarry.clockwork", rng);
|
"common.loadout.dungeon.dwarven_quarry.clockwork",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1062,10 +1108,15 @@ impl LoadoutBuilder {
|
|||||||
#[must_use = "Method consumes builder and returns updated builder."]
|
#[must_use = "Method consumes builder and returns updated builder."]
|
||||||
pub fn with_creator(
|
pub fn with_creator(
|
||||||
mut self,
|
mut self,
|
||||||
creator: fn(LoadoutBuilder, Option<&SiteInformation>) -> LoadoutBuilder,
|
creator: fn(
|
||||||
|
LoadoutBuilder,
|
||||||
|
Option<&SiteInformation>,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
self = creator(self, economy);
|
self = creator(self, economy, time);
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -1075,6 +1126,7 @@ impl LoadoutBuilder {
|
|||||||
mut self,
|
mut self,
|
||||||
spec: LoadoutSpec,
|
spec: LoadoutSpec,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> Result<Self, SpecError> {
|
) -> Result<Self, SpecError> {
|
||||||
// Include any inheritance
|
// Include any inheritance
|
||||||
let spec = spec.eval(rng)?;
|
let spec = spec.eval(rng)?;
|
||||||
@ -1082,7 +1134,7 @@ impl LoadoutBuilder {
|
|||||||
// Utility function to unwrap our itemspec
|
// Utility function to unwrap our itemspec
|
||||||
let mut to_item = |maybe_item: Option<ItemSpec>| {
|
let mut to_item = |maybe_item: Option<ItemSpec>| {
|
||||||
if let Some(item) = maybe_item {
|
if let Some(item) = maybe_item {
|
||||||
item.try_to_item(rng)
|
item.try_to_item(rng, time)
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -1090,7 +1142,7 @@ impl LoadoutBuilder {
|
|||||||
|
|
||||||
let to_pair = |maybe_hands: Option<Hands>, rng: &mut R| {
|
let to_pair = |maybe_hands: Option<Hands>, rng: &mut R| {
|
||||||
if let Some(hands) = maybe_hands {
|
if let Some(hands) = maybe_hands {
|
||||||
hands.try_to_pair(rng)
|
hands.try_to_pair(rng, time)
|
||||||
} else {
|
} else {
|
||||||
Ok((None, None))
|
Ok((None, None))
|
||||||
}
|
}
|
||||||
@ -1170,10 +1222,15 @@ impl LoadoutBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use = "Method consumes builder and returns updated builder."]
|
#[must_use = "Method consumes builder and returns updated builder."]
|
||||||
pub fn with_asset(self, asset_specifier: &str, rng: &mut impl Rng) -> Result<Self, SpecError> {
|
pub fn with_asset(
|
||||||
|
self,
|
||||||
|
asset_specifier: &str,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Result<Self, SpecError> {
|
||||||
let spec =
|
let spec =
|
||||||
LoadoutSpec::load_cloned(asset_specifier).map_err(SpecError::LoadoutAssetError)?;
|
LoadoutSpec::load_cloned(asset_specifier).map_err(SpecError::LoadoutAssetError)?;
|
||||||
self.with_loadout_spec(spec, rng)
|
self.with_loadout_spec(spec, rng, time)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Usage
|
/// # Usage
|
||||||
@ -1184,8 +1241,13 @@ impl LoadoutBuilder {
|
|||||||
/// 1) Will panic if there is no asset with such `asset_specifier`
|
/// 1) Will panic if there is no asset with such `asset_specifier`
|
||||||
/// 2) Will panic if path to item specified in loadout file doesn't exist
|
/// 2) Will panic if path to item specified in loadout file doesn't exist
|
||||||
#[must_use = "Method consumes builder and returns updated builder."]
|
#[must_use = "Method consumes builder and returns updated builder."]
|
||||||
pub fn with_asset_expect(self, asset_specifier: &str, rng: &mut impl Rng) -> Self {
|
pub fn with_asset_expect(
|
||||||
self.with_asset(asset_specifier, rng)
|
self,
|
||||||
|
asset_specifier: &str,
|
||||||
|
rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Self {
|
||||||
|
self.with_asset(asset_specifier, rng, time)
|
||||||
.expect("failed loading loadout config")
|
.expect("failed loading loadout config")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1194,7 +1256,7 @@ impl LoadoutBuilder {
|
|||||||
#[must_use = "Method consumes builder and returns updated builder."]
|
#[must_use = "Method consumes builder and returns updated builder."]
|
||||||
pub fn defaults(self) -> Self {
|
pub fn defaults(self) -> Self {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
self.with_asset_expect("common.loadout.default", rng)
|
self.with_asset_expect("common.loadout.default", rng, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use = "Method consumes builder and returns updated builder."]
|
#[must_use = "Method consumes builder and returns updated builder."]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
assets::{self, AssetExt, Error},
|
assets::{self, AssetExt, Error},
|
||||||
|
calendar::Calendar,
|
||||||
comp::{
|
comp::{
|
||||||
self, agent, humanoid,
|
self, agent, humanoid,
|
||||||
inventory::loadout_builder::{LoadoutBuilder, LoadoutSpec},
|
inventory::loadout_builder::{LoadoutBuilder, LoadoutSpec},
|
||||||
@ -8,6 +9,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
lottery::LootSpec,
|
lottery::LootSpec,
|
||||||
npc::{self, NPC_NAMES},
|
npc::{self, NPC_NAMES},
|
||||||
|
resources::TimeOfDay,
|
||||||
rtsim,
|
rtsim,
|
||||||
trade::SiteInformation,
|
trade::SiteInformation,
|
||||||
};
|
};
|
||||||
@ -189,7 +191,13 @@ pub struct EntityInfo {
|
|||||||
// Loadout
|
// Loadout
|
||||||
pub inventory: Vec<(u32, Item)>,
|
pub inventory: Vec<(u32, Item)>,
|
||||||
pub loadout: LoadoutBuilder,
|
pub loadout: LoadoutBuilder,
|
||||||
pub make_loadout: Option<fn(LoadoutBuilder, Option<&SiteInformation>) -> LoadoutBuilder>,
|
pub make_loadout: Option<
|
||||||
|
fn(
|
||||||
|
LoadoutBuilder,
|
||||||
|
Option<&SiteInformation>,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> LoadoutBuilder,
|
||||||
|
>,
|
||||||
// Skills
|
// Skills
|
||||||
pub skillset_asset: Option<String>,
|
pub skillset_asset: Option<String>,
|
||||||
|
|
||||||
@ -234,13 +242,18 @@ impl EntityInfo {
|
|||||||
/// Helper function for applying config from asset
|
/// Helper function for applying config from asset
|
||||||
/// with specified Rng for managing loadout.
|
/// with specified Rng for managing loadout.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_asset_expect<R>(self, asset_specifier: &str, loadout_rng: &mut R) -> Self
|
pub fn with_asset_expect<R>(
|
||||||
|
self,
|
||||||
|
asset_specifier: &str,
|
||||||
|
loadout_rng: &mut R,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> Self
|
||||||
where
|
where
|
||||||
R: rand::Rng,
|
R: rand::Rng,
|
||||||
{
|
{
|
||||||
let config = EntityConfig::load_expect_cloned(asset_specifier);
|
let config = EntityConfig::load_expect_cloned(asset_specifier);
|
||||||
|
|
||||||
self.with_entity_config(config, Some(asset_specifier), loadout_rng)
|
self.with_entity_config(config, Some(asset_specifier), loadout_rng, time)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate and apply EntityConfig
|
/// Evaluate and apply EntityConfig
|
||||||
@ -250,6 +263,7 @@ impl EntityInfo {
|
|||||||
config: EntityConfig,
|
config: EntityConfig,
|
||||||
config_asset: Option<&str>,
|
config_asset: Option<&str>,
|
||||||
loadout_rng: &mut R,
|
loadout_rng: &mut R,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
R: rand::Rng,
|
R: rand::Rng,
|
||||||
@ -297,7 +311,7 @@ impl EntityInfo {
|
|||||||
self = self.with_loot_drop(loot);
|
self = self.with_loot_drop(loot);
|
||||||
|
|
||||||
// NOTE: set loadout after body, as it's used with default equipement
|
// NOTE: set loadout after body, as it's used with default equipement
|
||||||
self = self.with_inventory(inventory, config_asset, loadout_rng);
|
self = self.with_inventory(inventory, config_asset, loadout_rng, time);
|
||||||
|
|
||||||
// Prefer the new configuration, if possible
|
// Prefer the new configuration, if possible
|
||||||
let AgentConfig {
|
let AgentConfig {
|
||||||
@ -330,6 +344,7 @@ impl EntityInfo {
|
|||||||
inventory: InventorySpec,
|
inventory: InventorySpec,
|
||||||
config_asset: Option<&str>,
|
config_asset: Option<&str>,
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
R: rand::Rng,
|
R: rand::Rng,
|
||||||
@ -350,14 +365,14 @@ impl EntityInfo {
|
|||||||
self = self.with_default_equip();
|
self = self.with_default_equip();
|
||||||
},
|
},
|
||||||
LoadoutKind::Asset(loadout) => {
|
LoadoutKind::Asset(loadout) => {
|
||||||
let loadout = LoadoutBuilder::from_asset(&loadout, rng).unwrap_or_else(|e| {
|
let loadout = LoadoutBuilder::from_asset(&loadout, rng, time).unwrap_or_else(|e| {
|
||||||
panic!("failed to load loadout for {config_asset}: {e:?}");
|
panic!("failed to load loadout for {config_asset}: {e:?}");
|
||||||
});
|
});
|
||||||
self.loadout = loadout;
|
self.loadout = loadout;
|
||||||
},
|
},
|
||||||
LoadoutKind::Inline(loadout_spec) => {
|
LoadoutKind::Inline(loadout_spec) => {
|
||||||
let loadout =
|
let loadout = LoadoutBuilder::from_loadout_spec(*loadout_spec, rng, time)
|
||||||
LoadoutBuilder::from_loadout_spec(*loadout_spec, rng).unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
panic!("failed to load loadout for {config_asset}: {e:?}");
|
panic!("failed to load loadout for {config_asset}: {e:?}");
|
||||||
});
|
});
|
||||||
self.loadout = loadout;
|
self.loadout = loadout;
|
||||||
@ -436,7 +451,11 @@ impl EntityInfo {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_lazy_loadout(
|
pub fn with_lazy_loadout(
|
||||||
mut self,
|
mut self,
|
||||||
creator: fn(LoadoutBuilder, Option<&SiteInformation>) -> LoadoutBuilder,
|
creator: fn(
|
||||||
|
LoadoutBuilder,
|
||||||
|
Option<&SiteInformation>,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> LoadoutBuilder,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.make_loadout = Some(creator);
|
self.make_loadout = Some(creator);
|
||||||
self
|
self
|
||||||
|
@ -654,6 +654,7 @@ fn handle_make_npc(
|
|||||||
config.clone(),
|
config.clone(),
|
||||||
Some(&entity_config),
|
Some(&entity_config),
|
||||||
&mut loadout_rng,
|
&mut loadout_rng,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
match NpcData::from_entity_info(entity_info) {
|
match NpcData::from_entity_info(entity_info) {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::sys::terrain::NpcData;
|
use crate::sys::terrain::NpcData;
|
||||||
use common::{
|
use common::{
|
||||||
|
calendar::Calendar,
|
||||||
comp::{self, Agent, Body, Presence, PresenceKind},
|
comp::{self, Agent, Body, Presence, PresenceKind},
|
||||||
event::{EventBus, NpcBuilder, ServerEvent},
|
event::{EventBus, NpcBuilder, ServerEvent},
|
||||||
generation::{BodyBuilder, EntityConfig, EntityInfo},
|
generation::{BodyBuilder, EntityConfig, EntityInfo},
|
||||||
@ -53,13 +54,18 @@ fn humanoid_config(profession: &Profession) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadout_default(loadout: LoadoutBuilder, _economy: Option<&SiteInformation>) -> LoadoutBuilder {
|
fn loadout_default(
|
||||||
|
loadout: LoadoutBuilder,
|
||||||
|
_economy: Option<&SiteInformation>,
|
||||||
|
_time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> LoadoutBuilder {
|
||||||
loadout
|
loadout
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merchant_loadout(
|
fn merchant_loadout(
|
||||||
loadout_builder: LoadoutBuilder,
|
loadout_builder: LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
_time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
trader_loadout(loadout_builder, economy, |_| true)
|
trader_loadout(loadout_builder, economy, |_| true)
|
||||||
}
|
}
|
||||||
@ -67,6 +73,7 @@ fn merchant_loadout(
|
|||||||
fn farmer_loadout(
|
fn farmer_loadout(
|
||||||
loadout_builder: LoadoutBuilder,
|
loadout_builder: LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
_time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
trader_loadout(loadout_builder, economy, |good| matches!(good, Good::Food))
|
trader_loadout(loadout_builder, economy, |good| matches!(good, Good::Food))
|
||||||
}
|
}
|
||||||
@ -74,6 +81,7 @@ fn farmer_loadout(
|
|||||||
fn herbalist_loadout(
|
fn herbalist_loadout(
|
||||||
loadout_builder: LoadoutBuilder,
|
loadout_builder: LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
_time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
trader_loadout(loadout_builder, economy, |good| {
|
trader_loadout(loadout_builder, economy, |good| {
|
||||||
matches!(good, Good::Ingredients)
|
matches!(good, Good::Ingredients)
|
||||||
@ -83,6 +91,7 @@ fn herbalist_loadout(
|
|||||||
fn chef_loadout(
|
fn chef_loadout(
|
||||||
loadout_builder: LoadoutBuilder,
|
loadout_builder: LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
_time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
trader_loadout(loadout_builder, economy, |good| matches!(good, Good::Food))
|
trader_loadout(loadout_builder, economy, |good| matches!(good, Good::Food))
|
||||||
}
|
}
|
||||||
@ -90,6 +99,7 @@ fn chef_loadout(
|
|||||||
fn blacksmith_loadout(
|
fn blacksmith_loadout(
|
||||||
loadout_builder: LoadoutBuilder,
|
loadout_builder: LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
_time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
trader_loadout(loadout_builder, economy, |good| {
|
trader_loadout(loadout_builder, economy, |good| {
|
||||||
matches!(good, Good::Tools | Good::Armor)
|
matches!(good, Good::Tools | Good::Armor)
|
||||||
@ -99,6 +109,7 @@ fn blacksmith_loadout(
|
|||||||
fn alchemist_loadout(
|
fn alchemist_loadout(
|
||||||
loadout_builder: LoadoutBuilder,
|
loadout_builder: LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
_time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
trader_loadout(loadout_builder, economy, |good| {
|
trader_loadout(loadout_builder, economy, |good| {
|
||||||
matches!(good, Good::Potions)
|
matches!(good, Good::Potions)
|
||||||
@ -107,7 +118,11 @@ fn alchemist_loadout(
|
|||||||
|
|
||||||
fn profession_extra_loadout(
|
fn profession_extra_loadout(
|
||||||
profession: Option<&Profession>,
|
profession: Option<&Profession>,
|
||||||
) -> fn(LoadoutBuilder, Option<&SiteInformation>) -> LoadoutBuilder {
|
) -> fn(
|
||||||
|
LoadoutBuilder,
|
||||||
|
Option<&SiteInformation>,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> LoadoutBuilder {
|
||||||
match profession {
|
match profession {
|
||||||
Some(Profession::Merchant) => merchant_loadout,
|
Some(Profession::Merchant) => merchant_loadout,
|
||||||
Some(Profession::Farmer) => farmer_loadout,
|
Some(Profession::Farmer) => farmer_loadout,
|
||||||
@ -134,7 +149,7 @@ fn profession_agent_mark(profession: Option<&Profession>) -> Option<comp::agent:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_npc_entity_info(npc: &Npc, sites: &Sites, index: IndexRef) -> EntityInfo {
|
fn get_npc_entity_info(npc: &Npc, sites: &Sites, index: IndexRef, time: Option<&(TimeOfDay, Calendar)>) -> EntityInfo {
|
||||||
let pos = comp::Pos(npc.wpos);
|
let pos = comp::Pos(npc.wpos);
|
||||||
|
|
||||||
let mut rng = npc.rng(Npc::PERM_ENTITY_CONFIG);
|
let mut rng = npc.rng(Npc::PERM_ENTITY_CONFIG);
|
||||||
@ -149,7 +164,7 @@ fn get_npc_entity_info(npc: &Npc, sites: &Sites, index: IndexRef) -> EntityInfo
|
|||||||
let entity_config = EntityConfig::from_asset_expect_owned(config_asset)
|
let entity_config = EntityConfig::from_asset_expect_owned(config_asset)
|
||||||
.with_body(BodyBuilder::Exact(npc.body));
|
.with_body(BodyBuilder::Exact(npc.body));
|
||||||
EntityInfo::at(pos.0)
|
EntityInfo::at(pos.0)
|
||||||
.with_entity_config(entity_config, Some(config_asset), &mut rng)
|
.with_entity_config(entity_config, Some(config_asset), &mut rng, time)
|
||||||
.with_alignment(if matches!(profession, Profession::Cultist) {
|
.with_alignment(if matches!(profession, Profession::Cultist) {
|
||||||
comp::Alignment::Enemy
|
comp::Alignment::Enemy
|
||||||
} else {
|
} else {
|
||||||
@ -204,7 +219,7 @@ fn get_npc_entity_info(npc: &Npc, sites: &Sites, index: IndexRef) -> EntityInfo
|
|||||||
let entity_config = EntityConfig::from_asset_expect_owned(config_asset)
|
let entity_config = EntityConfig::from_asset_expect_owned(config_asset)
|
||||||
.with_body(BodyBuilder::Exact(npc.body));
|
.with_body(BodyBuilder::Exact(npc.body));
|
||||||
|
|
||||||
EntityInfo::at(pos.0).with_entity_config(entity_config, Some(config_asset), &mut rng)
|
EntityInfo::at(pos.0).with_entity_config(entity_config, Some(config_asset), &mut rng, time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,6 +240,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadStorage<'a, RtSimEntity>,
|
ReadStorage<'a, RtSimEntity>,
|
||||||
WriteStorage<'a, comp::Agent>,
|
WriteStorage<'a, comp::Agent>,
|
||||||
ReadStorage<'a, Presence>,
|
ReadStorage<'a, Presence>,
|
||||||
|
ReadExpect<'a, Calendar>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const NAME: &'static str = "rtsim::tick";
|
const NAME: &'static str = "rtsim::tick";
|
||||||
@ -247,10 +263,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
rtsim_entities,
|
rtsim_entities,
|
||||||
mut agents,
|
mut agents,
|
||||||
presences,
|
presences,
|
||||||
|
calendar,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut emitter = server_event_bus.emitter();
|
let mut emitter = server_event_bus.emitter();
|
||||||
let rtsim = &mut *rtsim;
|
let rtsim = &mut *rtsim;
|
||||||
|
let calendar_data = (*time_of_day, (*calendar).clone());
|
||||||
|
|
||||||
// Set up rtsim inputs
|
// Set up rtsim inputs
|
||||||
{
|
{
|
||||||
@ -303,7 +321,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let entity_info = get_npc_entity_info(npc, &data.sites, index.as_index_ref());
|
let entity_info = get_npc_entity_info(npc, &data.sites, index.as_index_ref(), Some(&calendar_data));
|
||||||
|
|
||||||
emitter.emit(match NpcData::from_entity_info(entity_info) {
|
emitter.emit(match NpcData::from_entity_info(entity_info) {
|
||||||
NpcData::Data {
|
NpcData::Data {
|
||||||
@ -360,7 +378,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
if matches!(npc.mode, SimulationMode::Simulated) {
|
if matches!(npc.mode, SimulationMode::Simulated) {
|
||||||
npc.mode = SimulationMode::Loaded;
|
npc.mode = SimulationMode::Loaded;
|
||||||
let entity_info =
|
let entity_info =
|
||||||
get_npc_entity_info(npc, &data.sites, index.as_index_ref());
|
get_npc_entity_info(npc, &data.sites, index.as_index_ref(), Some(&calendar_data));
|
||||||
|
|
||||||
Some(match NpcData::from_entity_info(entity_info) {
|
Some(match NpcData::from_entity_info(entity_info) {
|
||||||
NpcData::Data {
|
NpcData::Data {
|
||||||
|
@ -476,7 +476,8 @@ impl NpcData {
|
|||||||
let inventory = {
|
let inventory = {
|
||||||
// Evaluate lazy function for loadout creation
|
// Evaluate lazy function for loadout creation
|
||||||
if let Some(make_loadout) = make_loadout {
|
if let Some(make_loadout) = make_loadout {
|
||||||
loadout_builder = loadout_builder.with_creator(make_loadout, economy.as_ref());
|
loadout_builder =
|
||||||
|
loadout_builder.with_creator(make_loadout, economy.as_ref(), None);
|
||||||
}
|
}
|
||||||
let loadout = loadout_builder.build();
|
let loadout = loadout_builder.build();
|
||||||
let mut inventory = comp::inventory::Inventory::with_loadout(loadout, body);
|
let mut inventory = comp::inventory::Inventory::with_loadout(loadout, body);
|
||||||
|
@ -305,7 +305,7 @@ impl<'a> Canvas<'a> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (pos, spec) in entities.drain(..) {
|
for (pos, spec) in entities.drain(..) {
|
||||||
self.spawn(EntityInfo::at(pos).with_asset_expect(&spec, &mut rng));
|
self.spawn(EntityInfo::at(pos).with_asset_expect(&spec, &mut rng, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,8 +942,11 @@ fn apply_entity_spawns<R: Rng>(canvas: &mut Canvas, wpos: Vec3<i32>, biome: &Bio
|
|||||||
.ok()
|
.ok()
|
||||||
.and_then(|s| s.0)
|
.and_then(|s| s.0)
|
||||||
{
|
{
|
||||||
canvas
|
canvas.spawn(EntityInfo::at(wpos.map(|e| e as f32)).with_asset_expect(
|
||||||
.spawn(EntityInfo::at(wpos.map(|e| e as f32)).with_asset_expect(entity_asset, rng));
|
entity_asset,
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,7 +668,7 @@ pub fn apply_caves_supplement<'a>(
|
|||||||
_ => "common.entity.wild.aggressive.cave_troll",
|
_ => "common.entity.wild.aggressive.cave_troll",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
entity.with_asset_expect(asset, dynamic_rng)
|
entity.with_asset_expect(asset, dynamic_rng, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
supplement.add_entity(entity);
|
supplement.add_entity(entity);
|
||||||
|
@ -618,7 +618,7 @@ pub fn apply_spots_to(canvas: &mut Canvas, _dynamic_rng: &mut impl Rng) {
|
|||||||
{
|
{
|
||||||
canvas.spawn(
|
canvas.spawn(
|
||||||
EntityInfo::at(wpos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0))
|
EntityInfo::at(wpos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0))
|
||||||
.with_asset_expect(spec, &mut rng),
|
.with_asset_expect(spec, &mut rng, None),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ impl Pack {
|
|||||||
.groups
|
.groups
|
||||||
.choose_weighted(dynamic_rng, |(p, _group)| *p)
|
.choose_weighted(dynamic_rng, |(p, _group)| *p)
|
||||||
.expect("Failed to choose group");
|
.expect("Failed to choose group");
|
||||||
let entity = EntityInfo::at(pos).with_asset_expect(entity_asset, dynamic_rng);
|
let entity = EntityInfo::at(pos).with_asset_expect(entity_asset, dynamic_rng, None);
|
||||||
let group_size = dynamic_rng.gen_range(*from..=*to);
|
let group_size = dynamic_rng.gen_range(*from..=*to);
|
||||||
|
|
||||||
(entity, group_size)
|
(entity, group_size)
|
||||||
@ -665,7 +665,8 @@ mod tests {
|
|||||||
let (_, (_, _, asset)) = group;
|
let (_, (_, _, asset)) = group;
|
||||||
let dummy_pos = Vec3::new(0.0, 0.0, 0.0);
|
let dummy_pos = Vec3::new(0.0, 0.0, 0.0);
|
||||||
let mut dummy_rng = thread_rng();
|
let mut dummy_rng = thread_rng();
|
||||||
let entity = EntityInfo::at(dummy_pos).with_asset_expect(asset, &mut dummy_rng);
|
let entity =
|
||||||
|
EntityInfo::at(dummy_pos).with_asset_expect(asset, &mut dummy_rng, None);
|
||||||
drop(entity);
|
drop(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -542,6 +542,7 @@ impl World {
|
|||||||
sample_get,
|
sample_get,
|
||||||
&mut supplement,
|
&mut supplement,
|
||||||
site.id(),
|
site.id(),
|
||||||
|
time.as_ref(),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ pub use self::{
|
|||||||
pub use common::terrain::site::{DungeonKindMeta, SettlementKindMeta, SiteKindMeta};
|
pub use common::terrain::site::{DungeonKindMeta, SettlementKindMeta, SiteKindMeta};
|
||||||
|
|
||||||
use crate::{column::ColumnSample, site2, Canvas};
|
use crate::{column::ColumnSample, site2, Canvas};
|
||||||
use common::generation::ChunkSupplement;
|
use common::{calendar::Calendar, generation::ChunkSupplement, resources::TimeOfDay};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -378,13 +378,14 @@ impl Site {
|
|||||||
get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||||
supplement: &mut ChunkSupplement,
|
supplement: &mut ChunkSupplement,
|
||||||
site_id: common::trade::SiteId,
|
site_id: common::trade::SiteId,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) {
|
) {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
SiteKind::Settlement(s) => {
|
SiteKind::Settlement(s) => {
|
||||||
let economy = self
|
let economy = self
|
||||||
.trade_information(site_id)
|
.trade_information(site_id)
|
||||||
.expect("Settlement has no economy");
|
.expect("Settlement has no economy");
|
||||||
s.apply_supplement(dynamic_rng, wpos2d, get_column, supplement, economy)
|
s.apply_supplement(dynamic_rng, wpos2d, get_column, supplement, economy, time)
|
||||||
},
|
},
|
||||||
SiteKind::Dungeon(d) => d.apply_supplement(dynamic_rng, wpos2d, supplement),
|
SiteKind::Dungeon(d) => d.apply_supplement(dynamic_rng, wpos2d, supplement),
|
||||||
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
SiteKind::Castle(c) => c.apply_supplement(dynamic_rng, wpos2d, get_column, supplement),
|
||||||
|
@ -15,6 +15,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
astar::Astar,
|
astar::Astar,
|
||||||
|
calendar::Calendar,
|
||||||
comp::{
|
comp::{
|
||||||
self, agent, bird_medium,
|
self, agent, bird_medium,
|
||||||
inventory::{
|
inventory::{
|
||||||
@ -24,6 +25,7 @@ use common::{
|
|||||||
},
|
},
|
||||||
generation::{ChunkSupplement, EntityInfo},
|
generation::{ChunkSupplement, EntityInfo},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
resources::TimeOfDay,
|
||||||
spiral::Spiral2d,
|
spiral::Spiral2d,
|
||||||
store::{Id, Store},
|
store::{Id, Store},
|
||||||
terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
|
terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
|
||||||
@ -853,6 +855,7 @@ impl Settlement {
|
|||||||
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||||
supplement: &mut ChunkSupplement,
|
supplement: &mut ChunkSupplement,
|
||||||
economy: SiteInformation,
|
economy: SiteInformation,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) {
|
) {
|
||||||
// let economy: HashMap<Good, (f32, f32)> = SiteInformation::economy
|
// let economy: HashMap<Good, (f32, f32)> = SiteInformation::economy
|
||||||
// .values
|
// .values
|
||||||
@ -893,12 +896,12 @@ impl Settlement {
|
|||||||
let entity = if is_dummy {
|
let entity = if is_dummy {
|
||||||
EntityInfo::at(entity_wpos)
|
EntityInfo::at(entity_wpos)
|
||||||
.with_agency(false)
|
.with_agency(false)
|
||||||
.with_asset_expect("common.entity.village.dummy", dynamic_rng)
|
.with_asset_expect("common.entity.village.dummy", dynamic_rng, time)
|
||||||
} else {
|
} else {
|
||||||
match dynamic_rng.gen_range(0..=4) {
|
match dynamic_rng.gen_range(0..=4) {
|
||||||
0 => barnyard(entity_wpos, dynamic_rng),
|
0 => barnyard(entity_wpos, dynamic_rng),
|
||||||
1 => bird(entity_wpos, dynamic_rng),
|
1 => bird(entity_wpos, dynamic_rng),
|
||||||
_ => humanoid(entity_wpos, &economy, dynamic_rng),
|
_ => humanoid(entity_wpos, &economy, dynamic_rng, time),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -993,27 +996,37 @@ fn bird(pos: Vec3<f32>, dynamic_rng: &mut impl Rng) -> EntityInfo {
|
|||||||
.with_automatic_name(None)
|
.with_automatic_name(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn humanoid(pos: Vec3<f32>, economy: &SiteInformation, dynamic_rng: &mut impl Rng) -> EntityInfo {
|
fn humanoid(
|
||||||
|
pos: Vec3<f32>,
|
||||||
|
economy: &SiteInformation,
|
||||||
|
dynamic_rng: &mut impl Rng,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
|
) -> EntityInfo {
|
||||||
let entity = EntityInfo::at(pos);
|
let entity = EntityInfo::at(pos);
|
||||||
match dynamic_rng.gen_range(0..8) {
|
match dynamic_rng.gen_range(0..8) {
|
||||||
0 | 1 => entity
|
0 | 1 => entity
|
||||||
.with_agent_mark(agent::Mark::Guard)
|
.with_agent_mark(agent::Mark::Guard)
|
||||||
.with_asset_expect("common.entity.village.guard", dynamic_rng),
|
.with_asset_expect("common.entity.village.guard", dynamic_rng, time),
|
||||||
2 => entity
|
2 => entity
|
||||||
.with_agent_mark(agent::Mark::Merchant)
|
.with_agent_mark(agent::Mark::Merchant)
|
||||||
.with_economy(economy)
|
.with_economy(economy)
|
||||||
.with_lazy_loadout(merchant_loadout)
|
.with_lazy_loadout(merchant_loadout)
|
||||||
.with_asset_expect("common.entity.village.merchant", dynamic_rng),
|
.with_asset_expect("common.entity.village.merchant", dynamic_rng, time),
|
||||||
_ => entity.with_asset_expect("common.entity.village.villager", dynamic_rng),
|
_ => entity.with_asset_expect("common.entity.village.villager", dynamic_rng, time),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn merchant_loadout(
|
pub fn merchant_loadout(
|
||||||
loadout_builder: LoadoutBuilder,
|
loadout_builder: LoadoutBuilder,
|
||||||
economy: Option<&SiteInformation>,
|
economy: Option<&SiteInformation>,
|
||||||
|
time: Option<&(TimeOfDay, Calendar)>,
|
||||||
) -> LoadoutBuilder {
|
) -> LoadoutBuilder {
|
||||||
trader_loadout(
|
trader_loadout(
|
||||||
loadout_builder.with_asset_expect("common.loadout.village.merchant", &mut thread_rng()),
|
loadout_builder.with_asset_expect(
|
||||||
|
"common.loadout.village.merchant",
|
||||||
|
&mut thread_rng(),
|
||||||
|
time,
|
||||||
|
),
|
||||||
economy,
|
economy,
|
||||||
|_| true,
|
|_| true,
|
||||||
)
|
)
|
||||||
|
@ -44,6 +44,7 @@ impl Tree {
|
|||||||
|
|
||||||
pub fn render(&self, canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
pub fn render(&self, canvas: &mut Canvas, dynamic_rng: &mut impl Rng) {
|
||||||
let nz = FastNoise::new(self.seed);
|
let nz = FastNoise::new(self.seed);
|
||||||
|
let calendar = None;
|
||||||
|
|
||||||
canvas.foreach_col(|canvas, wpos2d, col| {
|
canvas.foreach_col(|canvas, wpos2d, col| {
|
||||||
let rpos2d = wpos2d - self.origin;
|
let rpos2d = wpos2d - self.origin;
|
||||||
@ -81,6 +82,7 @@ impl Tree {
|
|||||||
_ => "common.entity.wild.aggressive.maneater",
|
_ => "common.entity.wild.aggressive.maneater",
|
||||||
},
|
},
|
||||||
dynamic_rng,
|
dynamic_rng,
|
||||||
|
calendar,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else if above && dynamic_rng.gen_bool(0.0001) {
|
} else if above && dynamic_rng.gen_bool(0.0001) {
|
||||||
@ -89,6 +91,7 @@ impl Tree {
|
|||||||
.with_asset_expect(
|
.with_asset_expect(
|
||||||
"common.entity.wild.aggressive.swamp_troll",
|
"common.entity.wild.aggressive.swamp_troll",
|
||||||
dynamic_rng,
|
dynamic_rng,
|
||||||
|
calendar,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1639,6 +1639,7 @@ impl Site {
|
|||||||
(-border..TILE_SIZE as i32 + border)
|
(-border..TILE_SIZE as i32 + border)
|
||||||
.map(move |x| (twpos + Vec2::new(x, y), Vec2::new(x, y)))
|
.map(move |x| (twpos + Vec2::new(x, y), Vec2::new(x, y)))
|
||||||
});
|
});
|
||||||
|
let calendar = None;
|
||||||
|
|
||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
match &tile.kind {
|
match &tile.kind {
|
||||||
@ -1693,7 +1694,7 @@ impl Site {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
canvas.spawn(
|
canvas.spawn(
|
||||||
EntityInfo::at(Vec3::new(wpos2d.x, wpos2d.y, alt).as_())
|
EntityInfo::at(Vec3::new(wpos2d.x, wpos2d.y, alt).as_())
|
||||||
.with_asset_expect(spec, dynamic_rng)
|
.with_asset_expect(spec, dynamic_rng, calendar)
|
||||||
.with_alignment(Alignment::Tame),
|
.with_alignment(Alignment::Tame),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2290,18 +2290,27 @@ impl RibCageGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn adlet_hunter<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn adlet_hunter<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.adlet.hunter", rng)
|
"common.entity.dungeon.adlet.hunter",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adlet_icepicker<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn adlet_icepicker<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.adlet.icepicker", rng)
|
"common.entity.dungeon.adlet.icepicker",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adlet_tracker<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn adlet_tracker<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.adlet.tracker", rng)
|
"common.entity.dungeon.adlet.tracker",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_adlet<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn random_adlet<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
@ -2313,42 +2322,67 @@ fn random_adlet<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn adlet_elder<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn adlet_elder<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.adlet.elder", rng)
|
"common.entity.dungeon.adlet.elder",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rat<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn rat<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect("common.entity.wild.peaceful.rat", rng)
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
|
"common.entity.wild.peaceful.rat",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wolf<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn wolf<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.wolf", rng)
|
"common.entity.wild.aggressive.wolf",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bear<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn bear<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.bear", rng)
|
"common.entity.wild.aggressive.bear",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn frostfang<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn frostfang<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.frostfang", rng)
|
"common.entity.wild.aggressive.frostfang",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn roshwalr<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn roshwalr<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.roshwalr", rng)
|
"common.entity.wild.aggressive.roshwalr",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn icedrake<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn icedrake<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.icedrake", rng)
|
"common.entity.wild.aggressive.icedrake",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tursus<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn tursus<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.tursus", rng)
|
"common.entity.wild.aggressive.tursus",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_yetipit_mob<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn random_yetipit_mob<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
@ -2361,7 +2395,11 @@ fn random_yetipit_mob<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn yeti<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn yeti<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect("common.entity.dungeon.adlet.yeti", rng)
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
|
"common.entity.dungeon.adlet.yeti",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -511,8 +511,11 @@ fn render_heightened_viaduct(bridge: &Bridge, painter: &Painter, data: &Heighten
|
|||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
if rng.gen_bool(0.1) {
|
if rng.gen_bool(0.1) {
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(c.with_z(bridge.center.z).as_())
|
EntityInfo::at(c.with_z(bridge.center.z).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.swamp_troll", &mut rng),
|
"common.entity.wild.aggressive.swamp_troll",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,8 +88,11 @@ impl Structure for Camp {
|
|||||||
CampType::Pirate => {
|
CampType::Pirate => {
|
||||||
for p in 0..npc_rng {
|
for p in 0..npc_rng {
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at((center + p).with_z(base + 2).as_())
|
EntityInfo::at((center + p).with_z(base + 2).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.spot.pirate", &mut thread_rng),
|
"common.entity.spot.pirate",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
let pet = if npc_rng < 3 {
|
let pet = if npc_rng < 3 {
|
||||||
@ -98,21 +101,30 @@ impl Structure for Camp {
|
|||||||
"common.entity.wild.peaceful.rat"
|
"common.entity.wild.peaceful.rat"
|
||||||
};
|
};
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(center.with_z(base + 2).as_())
|
EntityInfo::at(center.with_z(base + 2).as_()).with_asset_expect(
|
||||||
.with_asset_expect(pet, &mut thread_rng),
|
pet,
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
if npc_rng > 2 {
|
if npc_rng > 2 {
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at((center - 1).with_z(base + 2).as_())
|
EntityInfo::at((center - 1).with_z(base + 2).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.village.bowman", &mut thread_rng),
|
"common.entity.village.bowman",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if npc_rng < 4 {
|
if npc_rng < 4 {
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at((center + 1).with_z(base + 2).as_())
|
EntityInfo::at((center + 1).with_z(base + 2).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.village.skinner", &mut thread_rng),
|
"common.entity.village.skinner",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -704,9 +704,19 @@ fn enemy_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInf
|
|||||||
// TODO: give enemies health skills?
|
// TODO: give enemies health skills?
|
||||||
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
||||||
match dynamic_rng.gen_range(0..=4) {
|
match dynamic_rng.gen_range(0..=4) {
|
||||||
0 => entity.with_asset_expect("common.entity.dungeon.sahagin.sniper", dynamic_rng),
|
0 => {
|
||||||
1 => entity.with_asset_expect("common.entity.dungeon.sahagin.sorcerer", dynamic_rng),
|
entity.with_asset_expect("common.entity.dungeon.sahagin.sniper", dynamic_rng, None)
|
||||||
_ => entity.with_asset_expect("common.entity.dungeon.sahagin.spearman", dynamic_rng),
|
},
|
||||||
|
1 => entity.with_asset_expect(
|
||||||
|
"common.entity.dungeon.sahagin.sorcerer",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
_ => entity.with_asset_expect(
|
||||||
|
"common.entity.dungeon.sahagin.spearman",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -720,9 +730,11 @@ fn enemy_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInf
|
|||||||
// TODO: give enemies health skills?
|
// TODO: give enemies health skills?
|
||||||
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
||||||
match dynamic_rng.gen_range(0..=4) {
|
match dynamic_rng.gen_range(0..=4) {
|
||||||
0 => entity.with_asset_expect("common.entity.dungeon.haniwa.archer", dynamic_rng),
|
0 => entity.with_asset_expect("common.entity.dungeon.haniwa.archer", dynamic_rng, None),
|
||||||
1 => entity.with_asset_expect("common.entity.dungeon.haniwa.soldier", dynamic_rng),
|
1 => {
|
||||||
_ => entity.with_asset_expect("common.entity.dungeon.haniwa.guard", dynamic_rng),
|
entity.with_asset_expect("common.entity.dungeon.haniwa.soldier", dynamic_rng, None)
|
||||||
|
},
|
||||||
|
_ => entity.with_asset_expect("common.entity.dungeon.haniwa.guard", dynamic_rng, None),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -736,9 +748,21 @@ fn enemy_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInf
|
|||||||
// TODO: give enemies health skills?
|
// TODO: give enemies health skills?
|
||||||
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
||||||
match dynamic_rng.gen_range(0..=4) {
|
match dynamic_rng.gen_range(0..=4) {
|
||||||
0 => entity.with_asset_expect("common.entity.dungeon.myrmidon.marksman", dynamic_rng),
|
0 => entity.with_asset_expect(
|
||||||
1 => entity.with_asset_expect("common.entity.dungeon.myrmidon.strategian", dynamic_rng),
|
"common.entity.dungeon.myrmidon.marksman",
|
||||||
_ => entity.with_asset_expect("common.entity.dungeon.myrmidon.hoplite", dynamic_rng),
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
1 => entity.with_asset_expect(
|
||||||
|
"common.entity.dungeon.myrmidon.strategian",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
_ => entity.with_asset_expect(
|
||||||
|
"common.entity.dungeon.myrmidon.hoplite",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -752,9 +776,15 @@ fn enemy_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInf
|
|||||||
// TODO: give enemies health skills?
|
// TODO: give enemies health skills?
|
||||||
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
||||||
match dynamic_rng.gen_range(0..=4) {
|
match dynamic_rng.gen_range(0..=4) {
|
||||||
0 => entity.with_asset_expect("common.entity.dungeon.cultist.warlock", dynamic_rng),
|
0 => {
|
||||||
1 => entity.with_asset_expect("common.entity.dungeon.cultist.warlord", dynamic_rng),
|
entity.with_asset_expect("common.entity.dungeon.cultist.warlock", dynamic_rng, None)
|
||||||
_ => entity.with_asset_expect("common.entity.dungeon.cultist.cultist", dynamic_rng),
|
},
|
||||||
|
1 => {
|
||||||
|
entity.with_asset_expect("common.entity.dungeon.cultist.warlord", dynamic_rng, None)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
entity.with_asset_expect("common.entity.dungeon.cultist.cultist", dynamic_rng, None)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -766,31 +796,37 @@ fn enemy_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<En
|
|||||||
let mut entities = Vec::new();
|
let mut entities = Vec::new();
|
||||||
entities.resize_with(number, || {
|
entities.resize_with(number, || {
|
||||||
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
let entity = EntityInfo::at(tile_wcenter.map(|e| e as f32));
|
||||||
entity.with_asset_expect("common.entity.dungeon.fallback.enemy", dynamic_rng)
|
entity.with_asset_expect("common.entity.dungeon.fallback.enemy", dynamic_rng, None)
|
||||||
});
|
});
|
||||||
|
|
||||||
entities
|
entities
|
||||||
}
|
}
|
||||||
|
|
||||||
fn turret_3(dynamic_rng: &mut impl Rng, pos: Vec3<f32>) -> EntityInfo {
|
fn turret_3(dynamic_rng: &mut impl Rng, pos: Vec3<f32>) -> EntityInfo {
|
||||||
EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.haniwa.sentry", dynamic_rng)
|
EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.haniwa.sentry", dynamic_rng, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn turret_5(dynamic_rng: &mut impl Rng, pos: Vec3<f32>) -> EntityInfo {
|
fn turret_5(dynamic_rng: &mut impl Rng, pos: Vec3<f32>) -> EntityInfo {
|
||||||
EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.cultist.turret", dynamic_rng)
|
EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.cultist.turret", dynamic_rng, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
vec![
|
vec![
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sahagin.tidalwarrior", dynamic_rng),
|
"common.entity.dungeon.sahagin.tidalwarrior",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
fn boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
let mut entities = Vec::new();
|
let mut entities = Vec::new();
|
||||||
entities.resize_with(2, || {
|
entities.resize_with(2, || {
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.haniwa.claygolem", dynamic_rng)
|
"common.entity.dungeon.haniwa.claygolem",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
entities
|
entities
|
||||||
@ -798,30 +834,42 @@ fn boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo
|
|||||||
|
|
||||||
fn boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
vec![
|
vec![
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.myrmidon.minotaur", dynamic_rng),
|
"common.entity.dungeon.myrmidon.minotaur",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
vec![
|
vec![
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.cultist.mindflayer", dynamic_rng),
|
"common.entity.dungeon.cultist.mindflayer",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
vec![
|
vec![
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.fallback.boss", dynamic_rng),
|
"common.entity.dungeon.fallback.boss",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mini_boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn mini_boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
let mut entities = Vec::new();
|
let mut entities = Vec::new();
|
||||||
entities.resize_with(6, || {
|
entities.resize_with(6, || {
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sahagin.hakulaq", dynamic_rng)
|
"common.entity.dungeon.sahagin.hakulaq",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
entities
|
entities
|
||||||
}
|
}
|
||||||
@ -829,16 +877,22 @@ fn mini_boss_2(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<Entit
|
|||||||
fn mini_boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn mini_boss_3(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
let mut entities = Vec::new();
|
let mut entities = Vec::new();
|
||||||
entities.resize_with(3, || {
|
entities.resize_with(3, || {
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.haniwa.bonerattler", dynamic_rng)
|
"common.entity.dungeon.haniwa.bonerattler",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
entities
|
entities
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mini_boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn mini_boss_4(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
vec![
|
vec![
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.myrmidon.cyclops", dynamic_rng),
|
"common.entity.dungeon.myrmidon.cyclops",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,24 +901,36 @@ fn mini_boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<Entit
|
|||||||
match dynamic_rng.gen_range(0..=2) {
|
match dynamic_rng.gen_range(0..=2) {
|
||||||
0 => {
|
0 => {
|
||||||
entities.push(
|
entities.push(
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.cultist.beastmaster", dynamic_rng),
|
"common.entity.dungeon.cultist.beastmaster",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
entities.resize_with(entities.len() + 4, || {
|
entities.resize_with(entities.len() + 4, || {
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.cultist.hound", dynamic_rng)
|
"common.entity.dungeon.cultist.hound",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
1 => {
|
1 => {
|
||||||
entities.resize_with(2, || {
|
entities.resize_with(2, || {
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.cultist.husk_brute", dynamic_rng)
|
"common.entity.dungeon.cultist.husk_brute",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
entities.resize_with(10, || {
|
entities.resize_with(10, || {
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.cultist.husk", dynamic_rng)
|
"common.entity.dungeon.cultist.husk",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -873,8 +939,11 @@ fn mini_boss_5(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<Entit
|
|||||||
|
|
||||||
fn mini_boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
fn mini_boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
|
||||||
vec![
|
vec![
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.fallback.miniboss", dynamic_rng),
|
"common.entity.dungeon.fallback.miniboss",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ fn spawn_entity(pos: Vec3<f32>, painter: &Painter, entity_path: &str) {
|
|||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(pos)
|
EntityInfo::at(pos)
|
||||||
.with_asset_expect(entity_path, &mut rng)
|
.with_asset_expect(entity_path, &mut rng, None)
|
||||||
.with_no_flee(),
|
.with_no_flee(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -668,7 +668,7 @@ fn spawn_entities(
|
|||||||
|
|
||||||
let spawn_pos = pos + Vec3::new(x_offset, y_offset, 0.0);
|
let spawn_pos = pos + Vec3::new(x_offset, y_offset, 0.0);
|
||||||
|
|
||||||
painter.spawn(EntityInfo::at(spawn_pos).with_asset_expect(entity_path, &mut rng));
|
painter.spawn(EntityInfo::at(spawn_pos).with_asset_expect(entity_path, &mut rng, None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,27 +49,31 @@ impl GiantTree {
|
|||||||
if above_block.kind() == BlockKind::Leaves && dynamic_rng.gen_bool(0.001) {
|
if above_block.kind() == BlockKind::Leaves && dynamic_rng.gen_bool(0.001) {
|
||||||
let entity = EntityInfo::at(pos.as_());
|
let entity = EntityInfo::at(pos.as_());
|
||||||
match dynamic_rng.gen_range(0..=4) {
|
match dynamic_rng.gen_range(0..=4) {
|
||||||
0 => {
|
0 => Some(entity.with_asset_expect(
|
||||||
Some(entity.with_asset_expect(
|
|
||||||
"common.entity.wild.aggressive.horn_beetle",
|
"common.entity.wild.aggressive.horn_beetle",
|
||||||
dynamic_rng,
|
dynamic_rng,
|
||||||
))
|
None,
|
||||||
},
|
)),
|
||||||
1 => {
|
1 => Some(entity.with_asset_expect(
|
||||||
Some(entity.with_asset_expect(
|
|
||||||
"common.entity.wild.aggressive.stag_beetle",
|
"common.entity.wild.aggressive.stag_beetle",
|
||||||
dynamic_rng,
|
dynamic_rng,
|
||||||
))
|
None,
|
||||||
},
|
)),
|
||||||
2 => Some(
|
2 => Some(entity.with_asset_expect(
|
||||||
entity.with_asset_expect("common.entity.wild.aggressive.deadwood", dynamic_rng),
|
"common.entity.wild.aggressive.deadwood",
|
||||||
),
|
dynamic_rng,
|
||||||
3 => Some(
|
None,
|
||||||
entity.with_asset_expect("common.entity.wild.aggressive.maneater", dynamic_rng),
|
)),
|
||||||
),
|
3 => Some(entity.with_asset_expect(
|
||||||
4 => Some(
|
"common.entity.wild.aggressive.maneater",
|
||||||
entity.with_asset_expect("common.entity.wild.peaceful.parrot", dynamic_rng),
|
dynamic_rng,
|
||||||
),
|
None,
|
||||||
|
)),
|
||||||
|
4 => Some(entity.with_asset_expect(
|
||||||
|
"common.entity.wild.peaceful.parrot",
|
||||||
|
dynamic_rng,
|
||||||
|
None,
|
||||||
|
)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1874,18 +1874,27 @@ impl Structure for GnarlingFortification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gnarling_mugger<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn gnarling_mugger<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.gnarling.mugger", rng)
|
"common.entity.dungeon.gnarling.mugger",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gnarling_stalker<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn gnarling_stalker<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.gnarling.stalker", rng)
|
"common.entity.dungeon.gnarling.stalker",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gnarling_logger<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn gnarling_logger<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.gnarling.logger", rng)
|
"common.entity.dungeon.gnarling.logger",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn random_gnarling<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn random_gnarling<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
@ -1898,28 +1907,40 @@ fn random_gnarling<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
|||||||
|
|
||||||
fn gnarling_chieftain<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn gnarling_chieftain<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32))
|
||||||
.with_asset_expect("common.entity.dungeon.gnarling.chieftain", rng)
|
.with_asset_expect("common.entity.dungeon.gnarling.chieftain", rng, None)
|
||||||
.with_no_flee()
|
.with_no_flee()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deadwood<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn deadwood<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.deadwood", rng)
|
"common.entity.wild.aggressive.deadwood",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mandragora<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn mandragora<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.gnarling.mandragora", rng)
|
"common.entity.dungeon.gnarling.mandragora",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wood_golem<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn wood_golem<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.gnarling.woodgolem", rng)
|
"common.entity.dungeon.gnarling.woodgolem",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn harvester_boss<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
fn harvester_boss<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
|
||||||
EntityInfo::at(pos.map(|x| x as f32))
|
EntityInfo::at(pos.map(|x| x as f32)).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.gnarling.harvester", rng)
|
"common.entity.dungeon.gnarling.harvester",
|
||||||
|
rng,
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -240,17 +240,24 @@ impl Structure for JungleRuin {
|
|||||||
EntityInfo::at(npc_pos.with_z(plot_base + 5).as_()).with_asset_expect(
|
EntityInfo::at(npc_pos.with_z(plot_base + 5).as_()).with_asset_expect(
|
||||||
"common.entity.spot.dwarf_grave_robber",
|
"common.entity.spot.dwarf_grave_robber",
|
||||||
&mut thread_rng,
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// sauroks
|
// sauroks
|
||||||
1 => painter.spawn(
|
1 => painter.spawn(
|
||||||
EntityInfo::at(npc_pos.with_z(plot_base + 5).as_())
|
EntityInfo::at(npc_pos.with_z(plot_base + 5).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.spot.saurok", &mut thread_rng),
|
"common.entity.spot.saurok",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// grim salvager
|
// grim salvager
|
||||||
2 => painter.spawn(
|
2 => painter.spawn(
|
||||||
EntityInfo::at(npc_pos.with_z(plot_base + 5).as_())
|
EntityInfo::at(npc_pos.with_z(plot_base + 5).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.spot.grim_salvager", &mut thread_rng),
|
"common.entity.spot.grim_salvager",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
@ -68,18 +68,27 @@ impl Structure for PirateHideout {
|
|||||||
match RandomField::new(0).get(npc_pos.with_z(base)) % 10 {
|
match RandomField::new(0).get(npc_pos.with_z(base)) % 10 {
|
||||||
// rat
|
// rat
|
||||||
0 => painter.spawn(
|
0 => painter.spawn(
|
||||||
EntityInfo::at(npc_pos.with_z(base).as_())
|
EntityInfo::at(npc_pos.with_z(base).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.peaceful.rat", &mut thread_rng),
|
"common.entity.wild.peaceful.rat",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// parrot
|
// parrot
|
||||||
1 => painter.spawn(
|
1 => painter.spawn(
|
||||||
EntityInfo::at(npc_pos.with_z(base).as_())
|
EntityInfo::at(npc_pos.with_z(base).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.peaceful.parrot", &mut thread_rng),
|
"common.entity.wild.peaceful.parrot",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// pirates
|
// pirates
|
||||||
_ => painter.spawn(
|
_ => painter.spawn(
|
||||||
EntityInfo::at(npc_pos.with_z(base).as_())
|
EntityInfo::at(npc_pos.with_z(base).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.spot.pirate", &mut thread_rng),
|
"common.entity.spot.pirate",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,11 @@ impl Structure for RockCircle {
|
|||||||
if thread_rng.gen_range(0..=8) < 1 {
|
if thread_rng.gen_range(0..=8) < 1 {
|
||||||
// dullahan
|
// dullahan
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(center.with_z(base + 2).as_())
|
EntityInfo::at(center.with_z(base + 2).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.dullahan", &mut thread_rng),
|
"common.entity.wild.aggressive.dullahan",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,10 +611,11 @@ impl Structure for SeaChapel {
|
|||||||
// cellar sea crocodiles
|
// cellar sea crocodiles
|
||||||
let cellar_sea_croc_pos = (center - (diameter / 4)).with_z(base - (diameter / 2));
|
let cellar_sea_croc_pos = (center - (diameter / 4)).with_z(base - (diameter / 2));
|
||||||
for _ in 0..(3 + ((RandomField::new(0).get((cellar_sea_croc_pos).with_z(base))) % 5)) {
|
for _ in 0..(3 + ((RandomField::new(0).get((cellar_sea_croc_pos).with_z(base))) % 5)) {
|
||||||
painter.spawn(
|
painter.spawn(EntityInfo::at(cellar_sea_croc_pos.as_()).with_asset_expect(
|
||||||
EntityInfo::at(cellar_sea_croc_pos.as_())
|
"common.entity.wild.aggressive.sea_crocodile",
|
||||||
.with_asset_expect("common.entity.wild.aggressive.sea_crocodile", &mut rng),
|
&mut rng,
|
||||||
)
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
// clear chapel main room
|
// clear chapel main room
|
||||||
painter
|
painter
|
||||||
@ -681,20 +682,29 @@ impl Structure for SeaChapel {
|
|||||||
// organ on chapel top floor organ podium
|
// organ on chapel top floor organ podium
|
||||||
let first_floor_organ_pos = center_o2.with_z(base - (diameter / 8) + diameter - 4);
|
let first_floor_organ_pos = center_o2.with_z(base - (diameter / 8) + diameter - 4);
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(first_floor_organ_pos.as_())
|
EntityInfo::at(first_floor_organ_pos.as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.organ", &mut rng),
|
"common.entity.dungeon.sea_chapel.organ",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// sea clerics, bishop on top floor
|
// sea clerics, bishop on top floor
|
||||||
let first_floor_spawn_pos = (center_o2 - 2).with_z(base - (diameter / 8) + diameter - 4);
|
let first_floor_spawn_pos = (center_o2 - 2).with_z(base - (diameter / 8) + diameter - 4);
|
||||||
for _ in 0..(2 + ((RandomField::new(0).get((first_floor_spawn_pos).with_z(base))) % 2)) {
|
for _ in 0..(2 + ((RandomField::new(0).get((first_floor_spawn_pos).with_z(base))) % 2)) {
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(first_floor_spawn_pos.as_())
|
EntityInfo::at(first_floor_spawn_pos.as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.sea_cleric", &mut rng),
|
"common.entity.dungeon.sea_chapel.sea_cleric",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(first_floor_spawn_pos.as_())
|
EntityInfo::at(first_floor_spawn_pos.as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.sea_bishop", &mut rng),
|
"common.entity.dungeon.sea_chapel.sea_bishop",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// chapel main room gold decor ring and floor
|
// chapel main room gold decor ring and floor
|
||||||
painter
|
painter
|
||||||
@ -739,26 +749,38 @@ impl Structure for SeaChapel {
|
|||||||
// organ on chapel main room organ podium
|
// organ on chapel main room organ podium
|
||||||
let first_floor_organ_pos = center_o1.with_z(base + 2);
|
let first_floor_organ_pos = center_o1.with_z(base + 2);
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(first_floor_organ_pos.as_())
|
EntityInfo::at(first_floor_organ_pos.as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.organ", &mut rng),
|
"common.entity.dungeon.sea_chapel.organ",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// sea clerics on main floor
|
// sea clerics on main floor
|
||||||
let main_room_sea_clerics_pos = (center_o1 - 2).with_z(base + 2);
|
let main_room_sea_clerics_pos = (center_o1 - 2).with_z(base + 2);
|
||||||
for _ in 0..(3 + ((RandomField::new(0).get((main_room_sea_clerics_pos).with_z(base))) % 3))
|
for _ in 0..(3 + ((RandomField::new(0).get((main_room_sea_clerics_pos).with_z(base))) % 3))
|
||||||
{
|
{
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(main_room_sea_clerics_pos.as_())
|
EntityInfo::at(main_room_sea_clerics_pos.as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.sea_cleric", &mut rng),
|
"common.entity.dungeon.sea_chapel.sea_cleric",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// coral golem on main floor
|
// coral golem on main floor
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at((first_floor_organ_pos + 2).as_())
|
EntityInfo::at((first_floor_organ_pos + 2).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.coralgolem", &mut rng),
|
"common.entity.dungeon.sea_chapel.coralgolem",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at((first_floor_organ_pos + 4).as_())
|
EntityInfo::at((first_floor_organ_pos + 4).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.sea_bishop", &mut rng),
|
"common.entity.dungeon.sea_chapel.sea_bishop",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// chapel main room glassbarrier to cellar
|
// chapel main room glassbarrier to cellar
|
||||||
let center_g = center - diameter / 7;
|
let center_g = center - diameter / 7;
|
||||||
@ -833,17 +855,19 @@ impl Structure for SeaChapel {
|
|||||||
// cardinals room sea clerics
|
// cardinals room sea clerics
|
||||||
let cr_sea_clerics_pos = (center - (diameter / 5)).with_z(base - (diameter / 4) - 3);
|
let cr_sea_clerics_pos = (center - (diameter / 5)).with_z(base - (diameter / 4) - 3);
|
||||||
for _ in 0..(2 + ((RandomField::new(0).get((cr_sea_clerics_pos).with_z(base))) % 3)) {
|
for _ in 0..(2 + ((RandomField::new(0).get((cr_sea_clerics_pos).with_z(base))) % 3)) {
|
||||||
painter.spawn(
|
painter.spawn(EntityInfo::at(cr_sea_clerics_pos.as_()).with_asset_expect(
|
||||||
EntityInfo::at(cr_sea_clerics_pos.as_())
|
"common.entity.dungeon.sea_chapel.sea_cleric",
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.sea_cleric", &mut rng),
|
&mut rng,
|
||||||
)
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
// Cardinal
|
// Cardinal
|
||||||
let cr_cardinal_pos = (center - (diameter / 6)).with_z(base - (diameter / 4) - 3);
|
let cr_cardinal_pos = (center - (diameter / 6)).with_z(base - (diameter / 4) - 3);
|
||||||
painter.spawn(
|
painter.spawn(EntityInfo::at(cr_cardinal_pos.as_()).with_asset_expect(
|
||||||
EntityInfo::at(cr_cardinal_pos.as_())
|
"common.entity.dungeon.sea_chapel.cardinal",
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.cardinal", &mut rng),
|
&mut rng,
|
||||||
);
|
None,
|
||||||
|
));
|
||||||
// glassbarrier to water basin
|
// glassbarrier to water basin
|
||||||
painter
|
painter
|
||||||
.cylinder(Aabb {
|
.cylinder(Aabb {
|
||||||
@ -1394,6 +1418,7 @@ impl Structure for SeaChapel {
|
|||||||
painter.spawn(EntityInfo::at(room_clerics_pos.as_()).with_asset_expect(
|
painter.spawn(EntityInfo::at(room_clerics_pos.as_()).with_asset_expect(
|
||||||
"common.entity.dungeon.sea_chapel.sea_cleric",
|
"common.entity.dungeon.sea_chapel.sea_cleric",
|
||||||
&mut rng,
|
&mut rng,
|
||||||
|
None,
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
// decor for top rooms
|
// decor for top rooms
|
||||||
@ -1668,8 +1693,11 @@ impl Structure for SeaChapel {
|
|||||||
let underwater_organ_pos =
|
let underwater_organ_pos =
|
||||||
(center - (diameter / 4)).with_z(base - (3 * diameter) + (diameter / 2) + 1);
|
(center - (diameter / 4)).with_z(base - (3 * diameter) + (diameter / 2) + 1);
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(underwater_organ_pos.as_())
|
EntityInfo::at(underwater_organ_pos.as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.organ", &mut rng),
|
"common.entity.dungeon.sea_chapel.organ",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// underwater chamber decor ring
|
// underwater chamber decor ring
|
||||||
painter
|
painter
|
||||||
@ -1724,10 +1752,11 @@ impl Structure for SeaChapel {
|
|||||||
.fill(gold_chain);
|
.fill(gold_chain);
|
||||||
// underwater chamber dagon
|
// underwater chamber dagon
|
||||||
let cellar_miniboss_pos = (center + 6).with_z(base - (3 * diameter) + (diameter / 2) + 1);
|
let cellar_miniboss_pos = (center + 6).with_z(base - (3 * diameter) + (diameter / 2) + 1);
|
||||||
painter.spawn(
|
painter.spawn(EntityInfo::at(cellar_miniboss_pos.as_()).with_asset_expect(
|
||||||
EntityInfo::at(cellar_miniboss_pos.as_())
|
"common.entity.dungeon.sea_chapel.dagon",
|
||||||
.with_asset_expect("common.entity.dungeon.sea_chapel.dagon", &mut rng),
|
&mut rng,
|
||||||
);
|
None,
|
||||||
|
));
|
||||||
// underwater chamber floor entry
|
// underwater chamber floor entry
|
||||||
painter
|
painter
|
||||||
.cylinder_with_radius(
|
.cylinder_with_radius(
|
||||||
@ -2764,8 +2793,11 @@ impl Structure for SeaChapel {
|
|||||||
0..(2 + ((RandomField::new(0).get((bldg_cellar_sea_croc_pos).with_z(base))) % 2))
|
0..(2 + ((RandomField::new(0).get((bldg_cellar_sea_croc_pos).with_z(base))) % 2))
|
||||||
{
|
{
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(bldg_cellar_sea_croc_pos.as_())
|
EntityInfo::at(bldg_cellar_sea_croc_pos.as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.sea_crocodile", &mut rng),
|
"common.entity.wild.aggressive.sea_crocodile",
|
||||||
|
&mut rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
match bldg_variant {
|
match bldg_variant {
|
||||||
@ -2821,6 +2853,7 @@ impl Structure for SeaChapel {
|
|||||||
EntityInfo::at(bldg_floor_sea_cleric_pos.as_()).with_asset_expect(
|
EntityInfo::at(bldg_floor_sea_cleric_pos.as_()).with_asset_expect(
|
||||||
"common.entity.dungeon.sea_chapel.sea_cleric",
|
"common.entity.dungeon.sea_chapel.sea_cleric",
|
||||||
&mut rng,
|
&mut rng,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -2962,6 +2995,7 @@ impl Structure for SeaChapel {
|
|||||||
EntityInfo::at(bldg_floor_sea_cleric_pos.as_()).with_asset_expect(
|
EntityInfo::at(bldg_floor_sea_cleric_pos.as_()).with_asset_expect(
|
||||||
"common.entity.dungeon.sea_chapel.sea_cleric",
|
"common.entity.dungeon.sea_chapel.sea_cleric",
|
||||||
&mut rng,
|
&mut rng,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -2974,6 +3008,7 @@ impl Structure for SeaChapel {
|
|||||||
EntityInfo::at(bldg_floor3_sea_cleric_pos.as_()).with_asset_expect(
|
EntityInfo::at(bldg_floor3_sea_cleric_pos.as_()).with_asset_expect(
|
||||||
"common.entity.dungeon.sea_chapel.sea_cleric",
|
"common.entity.dungeon.sea_chapel.sea_cleric",
|
||||||
&mut rng,
|
&mut rng,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -3319,6 +3354,7 @@ impl Structure for SeaChapel {
|
|||||||
EntityInfo::at(prisoner_pos.as_()).with_asset_expect(
|
EntityInfo::at(prisoner_pos.as_()).with_asset_expect(
|
||||||
"common.entity.dungeon.sea_chapel.prisoner",
|
"common.entity.dungeon.sea_chapel.prisoner",
|
||||||
&mut rng,
|
&mut rng,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -73,13 +73,19 @@ impl Structure for TrollCave {
|
|||||||
|
|
||||||
// troll
|
// troll
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at(center.with_z(base - 15).as_())
|
EntityInfo::at(center.with_z(base - 15).as_()).with_asset_expect(
|
||||||
.with_asset_expect(troll, &mut thread_rng),
|
troll,
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
// bat
|
// bat
|
||||||
painter.spawn(
|
painter.spawn(
|
||||||
EntityInfo::at((center - 2).with_z(base + 5).as_())
|
EntityInfo::at((center - 2).with_z(base + 5).as_()).with_asset_expect(
|
||||||
.with_asset_expect("common.entity.wild.aggressive.bat", &mut thread_rng),
|
"common.entity.wild.aggressive.bat",
|
||||||
|
&mut thread_rng,
|
||||||
|
None,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user