mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added labour value to economy, castle improvements
This commit is contained in:
parent
bdb39b8e7f
commit
1763693f5f
@ -1 +0,0 @@
|
|||||||
,joshua,archbox.localdomain,17.06.2020 16:07,file:///home/joshua/.config/libreoffice/4;
|
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
sync::{Uid, WorldSyncExt},
|
sync::{Uid, WorldSyncExt},
|
||||||
terrain::{Block, BlockKind, TerrainChunkSize},
|
terrain::{Block, BlockKind, TerrainChunkSize},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
vol::{RectVolSize, WriteVol},
|
vol::RectVolSize,
|
||||||
LoadoutBuilder,
|
LoadoutBuilder,
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
@ -127,7 +127,7 @@ impl Civs {
|
|||||||
let wpos = site.center * TerrainChunkSize::RECT_SIZE.map(|e: u32| e as i32);
|
let wpos = site.center * TerrainChunkSize::RECT_SIZE.map(|e: u32| e as i32);
|
||||||
|
|
||||||
let flatten_radius = match &site.kind {
|
let flatten_radius = match &site.kind {
|
||||||
SiteKind::Settlement => 8.0,
|
SiteKind::Settlement => 10.0,
|
||||||
SiteKind::Dungeon => 2.0,
|
SiteKind::Dungeon => 2.0,
|
||||||
SiteKind::Castle => 5.0,
|
SiteKind::Castle => 5.0,
|
||||||
};
|
};
|
||||||
@ -148,9 +148,10 @@ impl Civs {
|
|||||||
0.0
|
0.0
|
||||||
}; // Raise the town centre up a little
|
}; // Raise the town centre up a little
|
||||||
let pos = site.center + offs;
|
let pos = site.center + offs;
|
||||||
let factor = (1.0
|
let factor = ((1.0
|
||||||
- (site.center - pos).map(|e| e as f32).magnitude() / flatten_radius)
|
- (site.center - pos).map(|e| e as f32).magnitude() / flatten_radius)
|
||||||
* 0.8;
|
* 1.25)
|
||||||
|
.min(1.0);
|
||||||
ctx.sim
|
ctx.sim
|
||||||
.get_mut(pos)
|
.get_mut(pos)
|
||||||
// Don't disrupt chunks that are near water
|
// Don't disrupt chunks that are near water
|
||||||
@ -170,9 +171,11 @@ impl Civs {
|
|||||||
let mut cnt = 0;
|
let mut cnt = 0;
|
||||||
for sim_site in this.sites.values() {
|
for sim_site in this.sites.values() {
|
||||||
cnt += 1;
|
cnt += 1;
|
||||||
let wpos = sim_site.center.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
let wpos = sim_site
|
||||||
e * sz as i32 + sz as i32 / 2
|
.center
|
||||||
});
|
.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
||||||
|
e * sz as i32 + sz as i32 / 2
|
||||||
|
});
|
||||||
|
|
||||||
let mut rng = ctx.reseed().rng;
|
let mut rng = ctx.reseed().rng;
|
||||||
let site = index.sites.insert(match &sim_site.kind {
|
let site = index.sites.insert(match &sim_site.kind {
|
||||||
|
@ -26,6 +26,7 @@ pub use self::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
all::ForestKind,
|
all::ForestKind,
|
||||||
civ::Place,
|
civ::Place,
|
||||||
|
column::{ColumnGen, ColumnSample},
|
||||||
site::Site,
|
site::Site,
|
||||||
util::{seed_expan, FastNoise, RandomField, StructureGen2d, LOCALITY, NEIGHBORS},
|
util::{seed_expan, FastNoise, RandomField, StructureGen2d, LOCALITY, NEIGHBORS},
|
||||||
Index, CONFIG,
|
Index, CONFIG,
|
||||||
@ -1699,8 +1700,9 @@ impl WorldSim {
|
|||||||
Some(z0 + z1 + z2 + z3)
|
Some(z0 + z1 + z2 + z3)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the distance to the nearest path in blocks, along with the closest point on the
|
/// Return the distance to the nearest path in blocks, along with the
|
||||||
/// path, the path metadata, and the tangent vector of that path.
|
/// closest point on the path, the path metadata, and the tangent vector
|
||||||
|
/// of that path.
|
||||||
pub fn get_nearest_path(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>, Path, Vec2<f32>)> {
|
pub fn get_nearest_path(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>, Path, Vec2<f32>)> {
|
||||||
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
||||||
e.div_euclid(sz as i32)
|
e.div_euclid(sz as i32)
|
||||||
|
@ -23,7 +23,7 @@ pub fn simulate(index: &mut Index, world: &mut WorldSim) {
|
|||||||
write!(f, "{:?} Value,", g).unwrap();
|
write!(f, "{:?} Value,", g).unwrap();
|
||||||
}
|
}
|
||||||
for g in Good::list() {
|
for g in Good::list() {
|
||||||
write!(f, "{:?} Price,", g).unwrap();
|
write!(f, "{:?} LaborVal,", g).unwrap();
|
||||||
}
|
}
|
||||||
for g in Good::list() {
|
for g in Good::list() {
|
||||||
write!(f, "{:?} Stock,", g).unwrap();
|
write!(f, "{:?} Stock,", g).unwrap();
|
||||||
@ -37,6 +37,9 @@ pub fn simulate(index: &mut Index, world: &mut WorldSim) {
|
|||||||
for l in Labor::list() {
|
for l in Labor::list() {
|
||||||
write!(f, "{:?} Productivity,", l).unwrap();
|
write!(f, "{:?} Productivity,", l).unwrap();
|
||||||
}
|
}
|
||||||
|
for l in Labor::list() {
|
||||||
|
write!(f, "{:?} Yields,", l).unwrap();
|
||||||
|
}
|
||||||
writeln!(f, "").unwrap();
|
writeln!(f, "").unwrap();
|
||||||
|
|
||||||
for i in 0..(HISTORY_DAYS / TICK_PERIOD) as i32 {
|
for i in 0..(HISTORY_DAYS / TICK_PERIOD) as i32 {
|
||||||
@ -53,7 +56,7 @@ pub fn simulate(index: &mut Index, world: &mut WorldSim) {
|
|||||||
write!(f, "{:?},", site.economy.values[*g].unwrap_or(-1.0)).unwrap();
|
write!(f, "{:?},", site.economy.values[*g].unwrap_or(-1.0)).unwrap();
|
||||||
}
|
}
|
||||||
for g in Good::list() {
|
for g in Good::list() {
|
||||||
write!(f, "{:?},", site.economy.prices[*g]).unwrap();
|
write!(f, "{:?},", site.economy.labor_values[*g]).unwrap();
|
||||||
}
|
}
|
||||||
for g in Good::list() {
|
for g in Good::list() {
|
||||||
write!(f, "{:?},", site.economy.stocks[*g]).unwrap();
|
write!(f, "{:?},", site.economy.stocks[*g]).unwrap();
|
||||||
@ -67,6 +70,9 @@ pub fn simulate(index: &mut Index, world: &mut WorldSim) {
|
|||||||
for l in Labor::list() {
|
for l in Labor::list() {
|
||||||
write!(f, "{:?},", site.economy.productivity[*l]).unwrap();
|
write!(f, "{:?},", site.economy.productivity[*l]).unwrap();
|
||||||
}
|
}
|
||||||
|
for l in Labor::list() {
|
||||||
|
write!(f, "{:?},", site.economy.yields[*l]).unwrap();
|
||||||
|
}
|
||||||
writeln!(f, "").unwrap();
|
writeln!(f, "").unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,11 +150,6 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
site.economy.prices = site.economy.stocks.clone().map(|g, stock| {
|
|
||||||
// Price rationalisation
|
|
||||||
demand[g] / (supply[g] + stocks[g])
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update export targets based on relative values
|
// Update export targets based on relative values
|
||||||
let value_avg = values
|
let value_avg = values
|
||||||
.iter()
|
.iter()
|
||||||
@ -169,7 +170,8 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
|||||||
|
|
||||||
// Redistribute workforce according to relative good values
|
// Redistribute workforce according to relative good values
|
||||||
let labor_ratios = productivity.clone().map(|labor, (output_good, _)| {
|
let labor_ratios = productivity.clone().map(|labor, (output_good, _)| {
|
||||||
site.economy.values[output_good].unwrap_or(0.0) * site.economy.productivity[labor]
|
site.economy.values[output_good].unwrap_or(0.0) * site.economy.yields[labor]
|
||||||
|
//(site.economy.prices[output_good] - site.economy.material_costs[output_good]) * site.economy.yields[labor]
|
||||||
//* demand[output_good] / supply[output_good].max(0.001)
|
//* demand[output_good] / supply[output_good].max(0.001)
|
||||||
});
|
});
|
||||||
let labor_ratio_sum = labor_ratios.iter().map(|(_, r)| *r).sum::<f32>().max(0.01);
|
let labor_ratio_sum = labor_ratios.iter().map(|(_, r)| *r).sum::<f32>().max(0.01);
|
||||||
@ -182,6 +184,7 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
|||||||
|
|
||||||
// Production
|
// Production
|
||||||
let stocks_before = site.economy.stocks.clone();
|
let stocks_before = site.economy.stocks.clone();
|
||||||
|
site.economy.labor_values = Default::default();
|
||||||
for (labor, orders) in orders.iter() {
|
for (labor, orders) in orders.iter() {
|
||||||
let scale = if let Some(labor) = labor {
|
let scale = if let Some(labor) = labor {
|
||||||
site.economy.labors[*labor]
|
site.economy.labors[*labor]
|
||||||
@ -207,12 +210,16 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
|||||||
.min_by(|a, b| a.partial_cmp(b).unwrap())
|
.min_by(|a, b| a.partial_cmp(b).unwrap())
|
||||||
.unwrap_or_else(|| panic!("Industry {:?} requires at least one input order", labor));
|
.unwrap_or_else(|| panic!("Industry {:?} requires at least one input order", labor));
|
||||||
|
|
||||||
|
let mut total_materials_cost = 0.0;
|
||||||
for (good, amount) in orders {
|
for (good, amount) in orders {
|
||||||
// What quantity is this order requesting?
|
// What quantity is this order requesting?
|
||||||
let quantity = *amount * scale;
|
let quantity = *amount * scale;
|
||||||
// What amount gets actually used in production?
|
// What amount gets actually used in production?
|
||||||
let used = quantity * labor_productivity;
|
let used = quantity * labor_productivity;
|
||||||
|
|
||||||
|
// Material cost of each factor of production
|
||||||
|
total_materials_cost += used * site.economy.labor_values[*good];
|
||||||
|
|
||||||
// Deplete stocks accordingly
|
// Deplete stocks accordingly
|
||||||
site.economy.stocks[*good] = (site.economy.stocks[*good] - used).max(0.0);
|
site.economy.stocks[*good] = (site.economy.stocks[*good] - used).max(0.0);
|
||||||
}
|
}
|
||||||
@ -222,10 +229,19 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
|||||||
let (stock, rate) = productivity[*labor];
|
let (stock, rate) = productivity[*labor];
|
||||||
let workers = site.economy.labors[*labor] * site.economy.pop;
|
let workers = site.economy.labors[*labor] * site.economy.pop;
|
||||||
let final_rate = rate;
|
let final_rate = rate;
|
||||||
let yield_per_worker = labor_productivity * final_rate;
|
let yield_per_worker = labor_productivity * final_rate * (1.0 + workers / 100.0);
|
||||||
site.economy.yields[*labor] = yield_per_worker;
|
site.economy.yields[*labor] = yield_per_worker;
|
||||||
site.economy.productivity[*labor] = labor_productivity;
|
site.economy.productivity[*labor] = labor_productivity;
|
||||||
site.economy.stocks[stock] += yield_per_worker * workers.powf(1.1);
|
let total_output = yield_per_worker * workers;
|
||||||
|
site.economy.stocks[stock] += total_output;
|
||||||
|
|
||||||
|
// Materials cost per unit
|
||||||
|
let material_cost_per_unit = total_materials_cost / total_output.max(0.001);
|
||||||
|
site.economy.material_costs[stock] = material_cost_per_unit;
|
||||||
|
site.economy.labor_values[stock] += material_cost_per_unit;
|
||||||
|
// Labor costs
|
||||||
|
let wages = 1.0;
|
||||||
|
site.economy.labor_values[stock] += workers * wages / total_output.max(0.001);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,19 +69,6 @@ impl Castle {
|
|||||||
|
|
||||||
let radius = 150;
|
let radius = 150;
|
||||||
|
|
||||||
// Adjust ground
|
|
||||||
if let Some(sim) = ctx.sim.as_mut() {
|
|
||||||
for rpos in Spiral2d::new()
|
|
||||||
.radius((radius as f32 * 0.7) as i32 / TerrainChunkSize::RECT_SIZE.x as i32)
|
|
||||||
{
|
|
||||||
sim.get_mut(wpos / TerrainChunkSize::RECT_SIZE.map(|e| e as i32) + rpos)
|
|
||||||
.map(|chunk| {
|
|
||||||
chunk.surface_veg = 0.0;
|
|
||||||
chunk.path.clear();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let this = Self {
|
let this = Self {
|
||||||
origin: wpos,
|
origin: wpos,
|
||||||
alt: ctx
|
alt: ctx
|
||||||
@ -157,6 +144,23 @@ impl Castle {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn contains_point(&self, wpos: Vec2<i32>) -> bool {
|
||||||
|
let lpos = wpos - self.origin;
|
||||||
|
for i in 0..self.towers.len() {
|
||||||
|
let tower0 = &self.towers[i];
|
||||||
|
let tower1 = &self.towers[(i + 1) % self.towers.len()];
|
||||||
|
|
||||||
|
if lpos.determine_side(Vec2::zero(), tower0.offset) > 0
|
||||||
|
&& lpos.determine_side(Vec2::zero(), tower1.offset) <= 0
|
||||||
|
&& lpos.determine_side(tower0.offset, tower1.offset) > 0
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_origin(&self) -> Vec2<i32> { self.origin }
|
pub fn get_origin(&self) -> Vec2<i32> { self.origin }
|
||||||
|
|
||||||
pub fn radius(&self) -> f32 { 1200.0 }
|
pub fn radius(&self) -> f32 { 1200.0 }
|
||||||
@ -182,13 +186,38 @@ impl Castle {
|
|||||||
let wpos2d = wpos2d + offs;
|
let wpos2d = wpos2d + offs;
|
||||||
let rpos = wpos2d - self.origin;
|
let rpos = wpos2d - self.origin;
|
||||||
|
|
||||||
// Apply the dungeon entrance
|
if rpos.magnitude_squared() > (self.radius + 64).pow(2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let col_sample = if let Some(col) = get_column(offs) {
|
let col_sample = if let Some(col) = get_column(offs) {
|
||||||
col
|
col
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Inner ground
|
||||||
|
if self.contains_point(wpos2d) {
|
||||||
|
let surface_z = col_sample.alt as i32;
|
||||||
|
for z in -5..3 {
|
||||||
|
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
|
||||||
|
|
||||||
|
if z >= 0 {
|
||||||
|
if vol.get(pos).unwrap().kind() != BlockKind::Water {
|
||||||
|
let _ = vol.set(pos, Block::empty());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let _ = vol.set(
|
||||||
|
pos,
|
||||||
|
Block::new(
|
||||||
|
BlockKind::Normal,
|
||||||
|
col_sample.sub_surface_color.map(|e| (e * 255.0) as u8),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let (wall_dist, wall_pos, wall_alt, wall_ori, towers) = (0..self.towers.len())
|
let (wall_dist, wall_pos, wall_alt, wall_ori, towers) = (0..self.towers.len())
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
let tower0 = &self.towers[i];
|
let tower0 = &self.towers[i];
|
||||||
|
@ -35,7 +35,9 @@ pub struct Economy {
|
|||||||
pub surplus: MapVec<Good, f32>,
|
pub surplus: MapVec<Good, f32>,
|
||||||
pub marginal_surplus: MapVec<Good, f32>,
|
pub marginal_surplus: MapVec<Good, f32>,
|
||||||
pub values: MapVec<Good, Option<f32>>,
|
pub values: MapVec<Good, Option<f32>>,
|
||||||
pub prices: MapVec<Good, f32>,
|
|
||||||
|
pub labor_values: MapVec<Good, f32>,
|
||||||
|
pub material_costs: MapVec<Good, f32>,
|
||||||
|
|
||||||
pub labors: MapVec<Labor, f32>,
|
pub labors: MapVec<Labor, f32>,
|
||||||
pub yields: MapVec<Labor, f32>,
|
pub yields: MapVec<Labor, f32>,
|
||||||
@ -51,7 +53,9 @@ impl Default for Economy {
|
|||||||
surplus: Default::default(),
|
surplus: Default::default(),
|
||||||
marginal_surplus: Default::default(),
|
marginal_surplus: Default::default(),
|
||||||
values: Default::default(),
|
values: Default::default(),
|
||||||
prices: Default::default(),
|
|
||||||
|
labor_values: Default::default(),
|
||||||
|
material_costs: Default::default(),
|
||||||
|
|
||||||
labors: Default::default(),
|
labors: Default::default(),
|
||||||
yields: Default::default(),
|
yields: Default::default(),
|
||||||
|
@ -12,28 +12,60 @@ use common::{
|
|||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
const COLOR_THEMES: [Rgb<u8>; 17] = [
|
pub struct ColorTheme {
|
||||||
Rgb::new(0x1D, 0x4D, 0x45),
|
roof: Rgb<u8>,
|
||||||
Rgb::new(0xB3, 0x7D, 0x60),
|
wall: Rgb<u8>,
|
||||||
Rgb::new(0xAC, 0x5D, 0x26),
|
support: Rgb<u8>,
|
||||||
Rgb::new(0x32, 0x46, 0x6B),
|
}
|
||||||
Rgb::new(0x2B, 0x19, 0x0F),
|
|
||||||
Rgb::new(0x93, 0x78, 0x51),
|
const ROOF_COLORS: &[Rgb<u8>] = &[
|
||||||
Rgb::new(0x92, 0x57, 0x24),
|
// Rgb::new(0x1D, 0x4D, 0x45),
|
||||||
Rgb::new(0x4A, 0x4E, 0x4E),
|
// Rgb::new(0xB3, 0x7D, 0x60),
|
||||||
Rgb::new(0x2F, 0x32, 0x47),
|
// Rgb::new(0xAC, 0x5D, 0x26),
|
||||||
Rgb::new(0x8F, 0x35, 0x43),
|
// Rgb::new(0x32, 0x46, 0x6B),
|
||||||
Rgb::new(0x6D, 0x1E, 0x3A),
|
// Rgb::new(0x2B, 0x19, 0x0F),
|
||||||
Rgb::new(0x6D, 0xA7, 0x80),
|
// Rgb::new(0x93, 0x78, 0x51),
|
||||||
Rgb::new(0x4F, 0xA0, 0x95),
|
// Rgb::new(0x92, 0x57, 0x24),
|
||||||
Rgb::new(0xE2, 0xB9, 0x99),
|
// Rgb::new(0x4A, 0x4E, 0x4E),
|
||||||
Rgb::new(0x7A, 0x30, 0x22),
|
// Rgb::new(0x2F, 0x32, 0x47),
|
||||||
Rgb::new(0x4A, 0x06, 0x08),
|
// Rgb::new(0x8F, 0x35, 0x43),
|
||||||
Rgb::new(0x8E, 0xB4, 0x57),
|
// Rgb::new(0x6D, 0x1E, 0x3A),
|
||||||
|
// Rgb::new(0x6D, 0xA7, 0x80),
|
||||||
|
// Rgb::new(0x4F, 0xA0, 0x95),
|
||||||
|
// Rgb::new(0xE2, 0xB9, 0x99),
|
||||||
|
// Rgb::new(0x7A, 0x30, 0x22),
|
||||||
|
// Rgb::new(0x4A, 0x06, 0x08),
|
||||||
|
// Rgb::new(0x8E, 0xB4, 0x57),
|
||||||
|
Rgb::new(0x99, 0x5E, 0x54),
|
||||||
|
Rgb::new(0x43, 0x63, 0x64),
|
||||||
|
Rgb::new(0x76, 0x6D, 0x68),
|
||||||
|
Rgb::new(0x7B, 0x41, 0x61),
|
||||||
|
Rgb::new(0x52, 0x20, 0x20),
|
||||||
|
Rgb::new(0x1A, 0x4A, 0x59),
|
||||||
|
Rgb::new(0xCC, 0x76, 0x4E),
|
||||||
|
];
|
||||||
|
|
||||||
|
const WALL_COLORS: &[Rgb<u8>] = &[
|
||||||
|
Rgb::new(200, 180, 150),
|
||||||
|
Rgb::new(0xB8, 0xB4, 0xA4),
|
||||||
|
Rgb::new(0x76, 0x6D, 0x68),
|
||||||
|
Rgb::new(0xF3, 0xC9, 0x8F),
|
||||||
|
Rgb::new(0xD3, 0xB7, 0x99),
|
||||||
|
Rgb::new(0xE1, 0xAB, 0x91),
|
||||||
|
Rgb::new(0x82, 0x57, 0x4C),
|
||||||
|
Rgb::new(0xB9, 0x96, 0x77),
|
||||||
|
Rgb::new(0x6E, 0x4D, 0x3C),
|
||||||
|
];
|
||||||
|
|
||||||
|
const SUPPORT_COLORS: &[Rgb<u8>] = &[
|
||||||
|
Rgb::new(60, 45, 30),
|
||||||
|
Rgb::new(0x65, 0x55, 0x56),
|
||||||
|
Rgb::new(0x53, 0x33, 0x13),
|
||||||
|
Rgb::new(0x58, 0x42, 0x33),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub struct House {
|
pub struct House {
|
||||||
pub roof_color: Rgb<u8>,
|
pub colors: ColorTheme,
|
||||||
pub noise: RandomField,
|
pub noise: RandomField,
|
||||||
pub roof_ribbing: bool,
|
pub roof_ribbing: bool,
|
||||||
pub roof_ribbing_diagonal: bool,
|
pub roof_ribbing_diagonal: bool,
|
||||||
@ -126,6 +158,7 @@ impl Archetype for House {
|
|||||||
let len = rng.gen_range(-8, 24).clamped(0, 20);
|
let len = rng.gen_range(-8, 24).clamped(0, 20);
|
||||||
let locus = 6 + rng.gen_range(0, 5);
|
let locus = 6 + rng.gen_range(0, 5);
|
||||||
let branches_per_side = 1 + len as usize / 20;
|
let branches_per_side = 1 + len as usize / 20;
|
||||||
|
let levels = rng.gen_range(1, 3);
|
||||||
let skel = Skeleton {
|
let skel = Skeleton {
|
||||||
offset: -rng.gen_range(0, len + 7).clamped(0, len),
|
offset: -rng.gen_range(0, len + 7).clamped(0, len),
|
||||||
ori: if rng.gen() { Ori::East } else { Ori::North },
|
ori: if rng.gen() { Ori::East } else { Ori::North },
|
||||||
@ -139,7 +172,7 @@ impl Archetype for House {
|
|||||||
1 => Pillar::Tower(5 + rng.gen_range(1, 5)),
|
1 => Pillar::Tower(5 + rng.gen_range(1, 5)),
|
||||||
_ => Pillar::None,
|
_ => Pillar::None,
|
||||||
},
|
},
|
||||||
levels: rng.gen_range(1, 4),
|
levels,
|
||||||
..Attr::generate(rng, locus)
|
..Attr::generate(rng, locus)
|
||||||
},
|
},
|
||||||
locus,
|
locus,
|
||||||
@ -154,7 +187,10 @@ impl Archetype for House {
|
|||||||
i as i32 * len / (branches_per_side - 1).max(1) as i32,
|
i as i32 * len / (branches_per_side - 1).max(1) as i32,
|
||||||
Branch {
|
Branch {
|
||||||
len: rng.gen_range(8, 16) * flip,
|
len: rng.gen_range(8, 16) * flip,
|
||||||
attr: Attr::generate(rng, locus),
|
attr: Attr {
|
||||||
|
levels: rng.gen_range(1, 4).min(levels),
|
||||||
|
..Attr::generate(rng, locus)
|
||||||
|
},
|
||||||
locus: (6 + rng.gen_range(0, 3)).min(locus),
|
locus: (6 + rng.gen_range(0, 3)).min(locus),
|
||||||
border: 4,
|
border: 4,
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
@ -169,7 +205,11 @@ impl Archetype for House {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let this = Self {
|
let this = Self {
|
||||||
roof_color: *COLOR_THEMES.choose(rng).unwrap(),
|
colors: ColorTheme {
|
||||||
|
roof: *ROOF_COLORS.choose(rng).unwrap(),
|
||||||
|
wall: *WALL_COLORS.choose(rng).unwrap(),
|
||||||
|
support: *SUPPORT_COLORS.choose(rng).unwrap(),
|
||||||
|
},
|
||||||
noise: RandomField::new(rng.gen()),
|
noise: RandomField::new(rng.gen()),
|
||||||
roof_ribbing: rng.gen(),
|
roof_ribbing: rng.gen(),
|
||||||
roof_ribbing_diagonal: rng.gen(),
|
roof_ribbing_diagonal: rng.gen(),
|
||||||
@ -205,7 +245,7 @@ impl Archetype for House {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let make_block = |r, g, b| {
|
let make_block = |(r, g, b)| {
|
||||||
let nz = self
|
let nz = self
|
||||||
.noise
|
.noise
|
||||||
.get(Vec3::new(center_offset.x, center_offset.y, z * 8));
|
.get(Vec3::new(center_offset.x, center_offset.y, z * 8));
|
||||||
@ -225,12 +265,11 @@ impl Archetype for House {
|
|||||||
let foundation_layer = internal_layer + 1;
|
let foundation_layer = internal_layer + 1;
|
||||||
let floor_layer = foundation_layer + 1;
|
let floor_layer = foundation_layer + 1;
|
||||||
|
|
||||||
let foundation = make_block(100, 100, 100).with_priority(foundation_layer);
|
let foundation = make_block((100, 100, 100)).with_priority(foundation_layer);
|
||||||
let log = make_block(60, 45, 30);
|
let log = make_block(self.colors.support.into_tuple());
|
||||||
let floor = make_block(100, 75, 50);
|
let floor = make_block((100, 75, 50));
|
||||||
let wall = make_block(200, 180, 150).with_priority(facade_layer);
|
let wall = make_block(self.colors.wall.into_tuple()).with_priority(facade_layer);
|
||||||
let roof = make_block(self.roof_color.r, self.roof_color.g, self.roof_color.b)
|
let roof = make_block(self.colors.roof.into_tuple()).with_priority(facade_layer - 1);
|
||||||
.with_priority(facade_layer - 1);
|
|
||||||
let empty = BlockMask::nothing();
|
let empty = BlockMask::nothing();
|
||||||
let internal = BlockMask::new(Block::empty(), internal_layer);
|
let internal = BlockMask::new(Block::empty(), internal_layer);
|
||||||
let end_window = BlockMask::new(
|
let end_window = BlockMask::new(
|
||||||
|
@ -2,15 +2,15 @@ pub mod archetype;
|
|||||||
pub mod skeleton;
|
pub mod skeleton;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
pub use self::{archetype::Archetype, skeleton::*};
|
pub use self::{
|
||||||
|
archetype::{house::House, keep::Keep, Archetype},
|
||||||
|
skeleton::*,
|
||||||
|
};
|
||||||
|
|
||||||
use common::terrain::Block;
|
use common::terrain::Block;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub type HouseBuilding = Building<archetype::house::House>;
|
|
||||||
pub type KeepBuilding = Building<archetype::keep::Keep>;
|
|
||||||
|
|
||||||
pub struct Building<A: Archetype> {
|
pub struct Building<A: Archetype> {
|
||||||
skel: Skeleton<A::Attr>,
|
skel: Skeleton<A::Attr>,
|
||||||
archetype: A,
|
archetype: A,
|
||||||
|
@ -2,7 +2,7 @@ pub mod building;
|
|||||||
mod town;
|
mod town;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
building::{HouseBuilding, KeepBuilding},
|
building::{Building, House, Keep},
|
||||||
town::{District, Town},
|
town::{District, Town},
|
||||||
};
|
};
|
||||||
use super::SpawnRules;
|
use super::SpawnRules;
|
||||||
@ -86,8 +86,8 @@ const AREA_SIZE: u32 = 32;
|
|||||||
fn to_tile(e: i32) -> i32 { ((e as f32).div_euclid(AREA_SIZE as f32)).floor() as i32 }
|
fn to_tile(e: i32) -> i32 { ((e as f32).div_euclid(AREA_SIZE as f32)).floor() as i32 }
|
||||||
|
|
||||||
pub enum StructureKind {
|
pub enum StructureKind {
|
||||||
House(HouseBuilding),
|
House(Building<House>),
|
||||||
Keep(KeepBuilding),
|
Keep(Building<Keep>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Structure {
|
pub struct Structure {
|
||||||
@ -403,12 +403,12 @@ impl Settlement {
|
|||||||
|
|
||||||
let structure = Structure {
|
let structure = Structure {
|
||||||
kind: if tile == town_center && i == 0 {
|
kind: if tile == town_center && i == 0 {
|
||||||
StructureKind::Keep(KeepBuilding::generate(
|
StructureKind::Keep(Building::<Keep>::generate(
|
||||||
ctx.rng,
|
ctx.rng,
|
||||||
Vec3::new(house_pos.x, house_pos.y, alt),
|
Vec3::new(house_pos.x, house_pos.y, alt),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
StructureKind::House(HouseBuilding::generate(
|
StructureKind::House(Building::<House>::generate(
|
||||||
ctx.rng,
|
ctx.rng,
|
||||||
Vec3::new(house_pos.x, house_pos.y, alt),
|
Vec3::new(house_pos.x, house_pos.y, alt),
|
||||||
))
|
))
|
||||||
@ -671,94 +671,79 @@ impl Settlement {
|
|||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
Some(Plot::Field { seed, crop, .. }) => {
|
Some(Plot::Field { seed, crop, .. }) => {
|
||||||
if let Some(color) = col_sample.path.and_then(|(dist, _, path, _)| {
|
let furrow_dirs = [
|
||||||
if dist < path.width {
|
Vec2::new(1, 0),
|
||||||
Some(path.surface_color(
|
Vec2::new(0, 1),
|
||||||
col_sample.sub_surface_color.map(|e| (e * 255.0) as u8),
|
Vec2::new(1, 1),
|
||||||
))
|
Vec2::new(-1, 1),
|
||||||
} else {
|
];
|
||||||
None
|
let furrow_dir = furrow_dirs[*seed as usize % furrow_dirs.len()];
|
||||||
}
|
let in_furrow = (wpos2d * furrow_dir).sum().rem_euclid(5) < 2;
|
||||||
}) {
|
|
||||||
Some(color)
|
|
||||||
} else {
|
|
||||||
let furrow_dirs = [
|
|
||||||
Vec2::new(1, 0),
|
|
||||||
Vec2::new(0, 1),
|
|
||||||
Vec2::new(1, 1),
|
|
||||||
Vec2::new(-1, 1),
|
|
||||||
];
|
|
||||||
let furrow_dir = furrow_dirs[*seed as usize % furrow_dirs.len()];
|
|
||||||
let in_furrow = (wpos2d * furrow_dir).sum().rem_euclid(5) < 2;
|
|
||||||
|
|
||||||
let dirt = Rgb::new(80, 55, 35).map(|e| {
|
let dirt = Rgb::new(80, 55, 35).map(|e| {
|
||||||
e + (self.noise.get(Vec3::broadcast((seed % 4096 + 0) as i32))
|
e + (self.noise.get(Vec3::broadcast((seed % 4096 + 0) as i32)) % 32)
|
||||||
|
as u8
|
||||||
|
});
|
||||||
|
let mound =
|
||||||
|
Rgb::new(70, 80, 30).map(|e| e + roll(0, 8) as u8).map(|e| {
|
||||||
|
e + (self.noise.get(Vec3::broadcast((seed % 4096 + 1) as i32))
|
||||||
% 32) as u8
|
% 32) as u8
|
||||||
});
|
});
|
||||||
let mound =
|
|
||||||
Rgb::new(70, 80, 30).map(|e| e + roll(0, 8) as u8).map(|e| {
|
|
||||||
e + (self
|
|
||||||
.noise
|
|
||||||
.get(Vec3::broadcast((seed % 4096 + 1) as i32))
|
|
||||||
% 32) as u8
|
|
||||||
});
|
|
||||||
|
|
||||||
if in_furrow {
|
if in_furrow {
|
||||||
if roll(0, 5) == 0 {
|
if roll(0, 5) == 0 {
|
||||||
surface_block = match crop {
|
surface_block = match crop {
|
||||||
Crop::Corn => Some(BlockKind::Corn),
|
Crop::Corn => Some(BlockKind::Corn),
|
||||||
Crop::Wheat if roll(1, 2) == 0 => {
|
Crop::Wheat if roll(1, 2) == 0 => {
|
||||||
Some(BlockKind::WheatYellow)
|
Some(BlockKind::WheatYellow)
|
||||||
},
|
},
|
||||||
Crop::Wheat => Some(BlockKind::WheatGreen),
|
Crop::Wheat => Some(BlockKind::WheatGreen),
|
||||||
Crop::Cabbage if roll(2, 2) == 0 => {
|
Crop::Cabbage if roll(2, 2) == 0 => {
|
||||||
Some(BlockKind::Cabbage)
|
Some(BlockKind::Cabbage)
|
||||||
},
|
},
|
||||||
Crop::Pumpkin if roll(3, 2) == 0 => {
|
Crop::Pumpkin if roll(3, 2) == 0 => {
|
||||||
Some(BlockKind::Pumpkin)
|
Some(BlockKind::Pumpkin)
|
||||||
},
|
},
|
||||||
Crop::Flax if roll(4, 2) == 0 => Some(BlockKind::Flax),
|
Crop::Flax if roll(4, 2) == 0 => Some(BlockKind::Flax),
|
||||||
Crop::Carrot if roll(5, 2) == 0 => {
|
Crop::Carrot if roll(5, 2) == 0 => Some(BlockKind::Carrot),
|
||||||
Some(BlockKind::Carrot)
|
Crop::Tomato if roll(6, 2) == 0 => Some(BlockKind::Tomato),
|
||||||
},
|
Crop::Radish if roll(7, 2) == 0 => Some(BlockKind::Radish),
|
||||||
Crop::Tomato if roll(6, 2) == 0 => {
|
Crop::Turnip if roll(8, 2) == 0 => Some(BlockKind::Turnip),
|
||||||
Some(BlockKind::Tomato)
|
Crop::Sunflower => Some(BlockKind::Sunflower),
|
||||||
},
|
_ => None,
|
||||||
Crop::Radish if roll(7, 2) == 0 => {
|
|
||||||
Some(BlockKind::Radish)
|
|
||||||
},
|
|
||||||
Crop::Turnip if roll(8, 2) == 0 => {
|
|
||||||
Some(BlockKind::Turnip)
|
|
||||||
},
|
|
||||||
Crop::Sunflower => Some(BlockKind::Sunflower),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
.or_else(|| {
|
|
||||||
if roll(9, 400) == 0 {
|
|
||||||
Some(BlockKind::Scarecrow)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(|kind| Block::new(kind, Rgb::white()));
|
|
||||||
}
|
}
|
||||||
} else if roll(0, 20) == 0 {
|
.or_else(|| {
|
||||||
surface_block =
|
if roll(9, 400) == 0 {
|
||||||
Some(Block::new(BlockKind::ShortGrass, Rgb::white()));
|
Some(BlockKind::Scarecrow)
|
||||||
} else if roll(1, 30) == 0 {
|
} else {
|
||||||
surface_block =
|
None
|
||||||
Some(Block::new(BlockKind::MediumGrass, Rgb::white()));
|
}
|
||||||
|
})
|
||||||
|
.map(|kind| Block::new(kind, Rgb::white()));
|
||||||
}
|
}
|
||||||
|
} else if roll(0, 20) == 0 {
|
||||||
Some(if in_furrow { dirt } else { mound })
|
surface_block =
|
||||||
|
Some(Block::new(BlockKind::ShortGrass, Rgb::white()));
|
||||||
|
} else if roll(1, 30) == 0 {
|
||||||
|
surface_block =
|
||||||
|
Some(Block::new(BlockKind::MediumGrass, Rgb::white()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(if in_furrow { dirt } else { mound })
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(color) = color {
|
if let Some(color) = color {
|
||||||
if col_sample.water_dist.map(|dist| dist > 2.0).unwrap_or(true) {
|
let is_path = col_sample
|
||||||
|
.path
|
||||||
|
.map(|(dist, _, path, _)| dist < path.width)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if col_sample.water_dist.map(|dist| dist > 2.0).unwrap_or(true) && !is_path
|
||||||
|
{
|
||||||
let diff = (surface_z - land_surface_z).abs();
|
let diff = (surface_z - land_surface_z).abs();
|
||||||
|
|
||||||
for z in -8 - diff..3 + diff {
|
for z in -8 - diff..3 + diff {
|
||||||
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
|
let pos = Vec3::new(offs.x, offs.y, surface_z + z);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user