mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added experimental worldgen caves
This commit is contained in:
parent
a9126f7e25
commit
10757d0325
@ -76,6 +76,10 @@ impl Civs {
|
||||
let rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
||||
let mut ctx = GenCtx { sim, rng };
|
||||
|
||||
for _ in 0..100 {
|
||||
this.generate_cave(&mut ctx);
|
||||
}
|
||||
|
||||
for _ in 0..INITIAL_CIV_COUNT {
|
||||
debug!("Creating civilisation...");
|
||||
if this.birth_civ(&mut ctx.reseed()).is_none() {
|
||||
@ -208,6 +212,62 @@ impl Civs {
|
||||
this
|
||||
}
|
||||
|
||||
// TODO: Move this
|
||||
fn generate_cave(&self, ctx: &mut GenCtx<impl Rng>) {
|
||||
let mut pos = ctx.sim
|
||||
.get_size()
|
||||
.map(|sz| ctx.rng.gen_range(0, sz as i32) as f32);
|
||||
let mut vel = pos
|
||||
.map2(ctx.sim.get_size(), |pos, sz| sz as f32 / 2.0 - pos)
|
||||
.try_normalized()
|
||||
.unwrap_or_else(Vec2::unit_y);
|
||||
|
||||
let path = (-100..100)
|
||||
.filter_map(|i: i32| {
|
||||
let depth = (i.abs() as f32 / 100.0 * std::f32::consts::PI / 2.0).cos();
|
||||
vel = (vel + Vec2::new(
|
||||
ctx.rng.gen_range(-0.25, 0.25),
|
||||
ctx.rng.gen_range(-0.25, 0.25),
|
||||
))
|
||||
.try_normalized()
|
||||
.unwrap_or_else(Vec2::unit_y);
|
||||
let old_pos = pos.map(|e| e as i32);
|
||||
pos = (pos + vel * 0.5).clamped(Vec2::zero(), ctx.sim.get_size().map(|e| e as f32 - 1.0));
|
||||
Some((pos.map(|e| e as i32), depth)).filter(|(pos, _)| *pos != old_pos)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for locs in path.windows(3) {
|
||||
let to_prev_idx = NEIGHBORS
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, dir)| **dir == locs[0].0 - locs[1].0)
|
||||
.expect("Track locations must be neighbors")
|
||||
.0;
|
||||
let to_next_idx = NEIGHBORS
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, dir)| **dir == locs[2].0 - locs[1].0)
|
||||
.expect("Track locations must be neighbors")
|
||||
.0;
|
||||
|
||||
ctx.sim.get_mut(locs[0].0).unwrap().cave.0.neighbors |=
|
||||
1 << ((to_prev_idx as u8 + 4) % 8);
|
||||
ctx.sim.get_mut(locs[2].0).unwrap().cave.0.neighbors |=
|
||||
1 << ((to_next_idx as u8 + 4) % 8);
|
||||
let mut chunk = ctx.sim.get_mut(locs[1].0).unwrap();
|
||||
chunk.cave.0.neighbors |=
|
||||
(1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
|
||||
let depth = locs[1].1 * 250.0;
|
||||
chunk.cave.1.alt = chunk.alt - depth + ctx.rng.gen_range(-4.0, 4.0) * (depth > 10.0) as i32 as f32;
|
||||
chunk.cave.1.width = ctx.rng.gen_range(12.0, 32.0);
|
||||
chunk.cave.0.offset = Vec2::new(
|
||||
ctx.rng.gen_range(-16, 17),
|
||||
ctx.rng.gen_range(-16, 17),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn place(&self, id: Id<Place>) -> &Place { self.places.get(id) }
|
||||
|
||||
pub fn sites(&self) -> impl Iterator<Item = &Site> + '_ { self.sites.values() }
|
||||
@ -425,16 +485,16 @@ impl Civs {
|
||||
.expect("Track locations must be neighbors")
|
||||
.0;
|
||||
|
||||
ctx.sim.get_mut(locs[0]).unwrap().path.neighbors |=
|
||||
ctx.sim.get_mut(locs[0]).unwrap().path.0.neighbors |=
|
||||
1 << ((to_prev_idx as u8 + 4) % 8);
|
||||
ctx.sim.get_mut(locs[2]).unwrap().path.neighbors |=
|
||||
ctx.sim.get_mut(locs[2]).unwrap().path.0.neighbors |=
|
||||
1 << ((to_next_idx as u8 + 4) % 8);
|
||||
let mut chunk = ctx.sim.get_mut(locs[1]).unwrap();
|
||||
chunk.path.neighbors |=
|
||||
chunk.path.0.neighbors |=
|
||||
(1 << (to_prev_idx as u8)) | (1 << (to_next_idx as u8));
|
||||
chunk.path.offset = Vec2::new(
|
||||
ctx.rng.gen_range(-16.0, 16.0),
|
||||
ctx.rng.gen_range(-16.0, 16.0),
|
||||
chunk.path.0.offset = Vec2::new(
|
||||
ctx.rng.gen_range(-16, 17),
|
||||
ctx.rng.gen_range(-16, 17),
|
||||
);
|
||||
}
|
||||
|
||||
@ -570,7 +630,7 @@ fn walk_in_dir(sim: &WorldSim, a: Vec2<i32>, dir: Vec2<i32>) -> Option<f32> {
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let wild_cost = if b_chunk.path.is_path() {
|
||||
let wild_cost = if b_chunk.path.0.is_way() {
|
||||
0.0 // Traversing existing paths has no additional cost!
|
||||
} else {
|
||||
2.0
|
||||
|
@ -2,7 +2,8 @@ use crate::{
|
||||
all::ForestKind,
|
||||
block::StructureMeta,
|
||||
sim::{
|
||||
local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx, Path, RiverKind, SimChunk, WorldSim,
|
||||
local_cells, uniform_idx_as_vec2, vec2_as_uniform_idx,
|
||||
Path, Cave, RiverKind, SimChunk, WorldSim,
|
||||
},
|
||||
util::Sampler,
|
||||
Index, CONFIG,
|
||||
@ -1082,6 +1083,7 @@ where
|
||||
};
|
||||
|
||||
let path = sim.get_nearest_path(wpos);
|
||||
let cave = sim.get_nearest_cave(wpos);
|
||||
|
||||
Some(ColumnSample {
|
||||
alt,
|
||||
@ -1131,6 +1133,7 @@ where
|
||||
stone_col,
|
||||
water_dist,
|
||||
path,
|
||||
cave,
|
||||
|
||||
chunk: sim_chunk,
|
||||
})
|
||||
@ -1165,6 +1168,7 @@ pub struct ColumnSample<'a> {
|
||||
pub stone_col: Rgb<u8>,
|
||||
pub water_dist: Option<f32>,
|
||||
pub path: Option<(f32, Vec2<f32>, Path, Vec2<f32>)>,
|
||||
pub cave: Option<(f32, Vec2<f32>, Cave, Vec2<f32>)>,
|
||||
|
||||
pub chunk: &'a SimChunk,
|
||||
}
|
||||
|
@ -95,3 +95,40 @@ pub fn apply_paths_to<'a>(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_caves_to<'a>(
|
||||
wpos2d: Vec2<i32>,
|
||||
mut get_column: impl FnMut(Vec2<i32>) -> Option<&'a ColumnSample<'a>>,
|
||||
vol: &mut (impl BaseVol<Vox = Block> + RectSizedVol + ReadVol + WriteVol),
|
||||
) {
|
||||
for y in 0..vol.size_xy().y as i32 {
|
||||
for x in 0..vol.size_xy().x as i32 {
|
||||
let offs = Vec2::new(x, y);
|
||||
|
||||
let wpos2d = wpos2d + offs;
|
||||
|
||||
// Sample terrain
|
||||
let col_sample = if let Some(col_sample) = get_column(offs) {
|
||||
col_sample
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let surface_z = col_sample.riverless_alt.floor() as i32;
|
||||
|
||||
if let Some((cave_dist, cave_nearest, cave, _)) = col_sample
|
||||
.cave
|
||||
.filter(|(dist, _, cave, _)| *dist < cave.width)
|
||||
{
|
||||
let cave_x = (cave_dist / cave.width).min(1.0);
|
||||
let height = (1.0 - cave_x.powf(2.0)).max(0.0).sqrt() * cave.width;
|
||||
|
||||
for z in (cave.alt - height) as i32..(cave.alt + height) as i32 {
|
||||
let _ = vol.set(
|
||||
Vec3::new(offs.x, offs.y, z),
|
||||
Block::empty(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -175,8 +175,9 @@ impl World {
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
// Apply paths
|
||||
// Apply layers (paths, caves, etc.)
|
||||
layer::apply_paths_to(chunk_wpos2d, sample_get, &mut chunk);
|
||||
layer::apply_caves_to(chunk_wpos2d, sample_get, &mut chunk);
|
||||
|
||||
// Apply site generation
|
||||
sim_chunk.sites.iter().for_each(|site| {
|
||||
|
@ -157,6 +157,7 @@ impl MapConfig {
|
||||
downhill,
|
||||
river_kind,
|
||||
is_path,
|
||||
is_cave,
|
||||
near_site,
|
||||
) = sampler
|
||||
.get(pos)
|
||||
@ -169,7 +170,8 @@ impl MapConfig {
|
||||
sample.temp,
|
||||
sample.downhill,
|
||||
sample.river.river_kind,
|
||||
sample.path.is_path(),
|
||||
sample.path.0.is_way(),
|
||||
sample.cave.0.is_way(),
|
||||
sample.sites.iter().any(|site| {
|
||||
index.sites[*site]
|
||||
.get_origin()
|
||||
@ -188,6 +190,7 @@ impl MapConfig {
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
));
|
||||
let humidity = humidity.min(1.0).max(0.0);
|
||||
let temperature = temperature.min(1.0).max(-1.0) * 0.5 + 0.5;
|
||||
@ -317,6 +320,8 @@ impl MapConfig {
|
||||
(0x57, 0x39, 0x33, 0xFF)
|
||||
} else if is_path {
|
||||
(0x37, 0x29, 0x23, 0xFF)
|
||||
} else if is_cave {
|
||||
(0x37, 0x37, 0x37, 0xFF)
|
||||
} else {
|
||||
rgba
|
||||
};
|
||||
|
@ -2,7 +2,7 @@ mod diffusion;
|
||||
mod erosion;
|
||||
mod location;
|
||||
mod map;
|
||||
mod path;
|
||||
mod way;
|
||||
mod util;
|
||||
|
||||
// Reexports
|
||||
@ -15,7 +15,7 @@ pub use self::{
|
||||
},
|
||||
location::Location,
|
||||
map::{MapConfig, MapDebug},
|
||||
path::{Path, PathData},
|
||||
way::{Way, Path, Cave},
|
||||
util::{
|
||||
cdf_irwin_hall, downhill, get_oceans, local_cells, map_edge_factor, neighbors,
|
||||
uniform_idx_as_vec2, uniform_noise, uphill, vec2_as_uniform_idx, InverseCdf, ScaleBias,
|
||||
@ -1700,10 +1700,14 @@ impl WorldSim {
|
||||
Some(z0 + z1 + z2 + z3)
|
||||
}
|
||||
|
||||
/// Return the distance to the nearest path in blocks, along with the
|
||||
/// 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>)> {
|
||||
/// Return the distance to the nearest way in blocks, along with the
|
||||
/// closest point on the way, the way metadata, and the tangent vector
|
||||
/// of that way.
|
||||
pub fn get_nearest_way<M: Clone + Lerp<Output=M>>(
|
||||
&self,
|
||||
wpos: Vec2<i32>,
|
||||
get_way: impl Fn(&SimChunk) -> Option<(Way, M)>,
|
||||
) -> Option<(f32, Vec2<f32>, M, Vec2<f32>)> {
|
||||
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
|
||||
e.div_euclid(sz as i32)
|
||||
});
|
||||
@ -1713,32 +1717,34 @@ impl WorldSim {
|
||||
})
|
||||
};
|
||||
|
||||
let get_way = &get_way;
|
||||
LOCALITY
|
||||
.iter()
|
||||
.filter_map(|ctrl| {
|
||||
let chunk = self.get(chunk_pos + *ctrl)?;
|
||||
let ctrl_pos =
|
||||
get_chunk_centre(chunk_pos + *ctrl).map(|e| e as f32) + chunk.path.offset;
|
||||
let (way, meta) = get_way(self.get(chunk_pos + *ctrl)?)?;
|
||||
let ctrl_pos = get_chunk_centre(chunk_pos + *ctrl).map(|e| e as f32) + way.offset.map(|e| e as f32);
|
||||
|
||||
let chunk_connections = chunk.path.neighbors.count_ones();
|
||||
let chunk_connections = way.neighbors.count_ones();
|
||||
if chunk_connections == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (start_pos, _start_idx) = if chunk_connections != 2 {
|
||||
(ctrl_pos, None)
|
||||
let (start_pos, _start_idx, start_meta) = if chunk_connections != 2 {
|
||||
(ctrl_pos, None, meta.clone())
|
||||
} else {
|
||||
let (start_idx, start_rpos) = NEIGHBORS
|
||||
.iter()
|
||||
.copied()
|
||||
.enumerate()
|
||||
.find(|(i, _)| chunk.path.neighbors & (1 << *i as u8) != 0)
|
||||
.find(|(i, _)| way.neighbors & (1 << *i as u8) != 0)
|
||||
.unwrap();
|
||||
let start_pos_chunk = chunk_pos + *ctrl + start_rpos;
|
||||
let (start_way, start_meta) = get_way(self.get(start_pos_chunk)?)?;
|
||||
(
|
||||
get_chunk_centre(start_pos_chunk).map(|e| e as f32)
|
||||
+ self.get(start_pos_chunk)?.path.offset,
|
||||
+ start_way.offset.map(|e| e as f32),
|
||||
Some(start_idx),
|
||||
start_meta,
|
||||
)
|
||||
};
|
||||
|
||||
@ -1746,11 +1752,12 @@ impl WorldSim {
|
||||
NEIGHBORS
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(move |(i, _)| chunk.path.neighbors & (1 << *i as u8) != 0)
|
||||
.filter(move |(i, _)| way.neighbors & (1 << *i as u8) != 0)
|
||||
.filter_map(move |(_, end_rpos)| {
|
||||
let end_pos_chunk = chunk_pos + *ctrl + end_rpos;
|
||||
let (end_way, end_meta) = get_way(self.get(end_pos_chunk)?)?;
|
||||
let end_pos = get_chunk_centre(end_pos_chunk).map(|e| e as f32)
|
||||
+ self.get(end_pos_chunk)?.path.offset;
|
||||
+ end_way.offset.map(|e| e as f32);
|
||||
|
||||
let bez = QuadraticBezier2 {
|
||||
start: (start_pos + ctrl_pos) / 2.0,
|
||||
@ -1763,7 +1770,12 @@ impl WorldSim {
|
||||
.clamped(0.0, 1.0);
|
||||
let pos = bez.evaluate(nearest_interval);
|
||||
let dist_sqrd = pos.distance_squared(wpos.map(|e| e as f32));
|
||||
Some((dist_sqrd, pos, chunk.path.path, move || {
|
||||
let meta = if nearest_interval < 0.5 {
|
||||
Lerp::lerp(start_meta.clone(), meta.clone(), 0.5 + nearest_interval)
|
||||
} else {
|
||||
Lerp::lerp(meta.clone(), end_meta, nearest_interval - 0.5)
|
||||
};
|
||||
Some((dist_sqrd, pos, meta, move || {
|
||||
bez.evaluate_derivative(nearest_interval).normalized()
|
||||
}))
|
||||
}),
|
||||
@ -1771,7 +1783,15 @@ impl WorldSim {
|
||||
})
|
||||
.flatten()
|
||||
.min_by_key(|(dist_sqrd, _, _, _)| (dist_sqrd * 1024.0) as i32)
|
||||
.map(|(dist, pos, path, calc_tangent)| (dist.sqrt(), pos, path, calc_tangent()))
|
||||
.map(|(dist, pos, meta, calc_tangent)| (dist.sqrt(), pos, meta, calc_tangent()))
|
||||
}
|
||||
|
||||
pub fn get_nearest_path(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>, Path, Vec2<f32>)> {
|
||||
self.get_nearest_way(wpos, |chunk| Some(chunk.path))
|
||||
}
|
||||
|
||||
pub fn get_nearest_cave(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>, Cave, Vec2<f32>)> {
|
||||
self.get_nearest_way(wpos, |chunk| Some(chunk.cave))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1797,7 +1817,10 @@ pub struct SimChunk {
|
||||
|
||||
pub sites: Vec<Id<Site>>,
|
||||
pub place: Option<Id<Place>>,
|
||||
pub path: PathData,
|
||||
|
||||
pub path: (Way, Path),
|
||||
pub cave: (Way, Cave),
|
||||
|
||||
pub contains_waypoint: bool,
|
||||
}
|
||||
|
||||
@ -2033,7 +2056,8 @@ impl SimChunk {
|
||||
|
||||
sites: Vec::new(),
|
||||
place: None,
|
||||
path: PathData::default(),
|
||||
path: Default::default(),
|
||||
cave: Default::default(),
|
||||
contains_waypoint: false,
|
||||
}
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
use vek::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Path {
|
||||
pub width: f32, // Actually radius
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PathData {
|
||||
pub offset: Vec2<f32>, /* Offset from centre of chunk: must not be more than half chunk
|
||||
* width in any direction */
|
||||
pub path: Path,
|
||||
pub neighbors: u8, // One bit for each neighbor
|
||||
}
|
||||
|
||||
impl PathData {
|
||||
pub fn is_path(&self) -> bool { self.neighbors != 0 }
|
||||
|
||||
pub fn clear(&mut self) { self.neighbors = 0; }
|
||||
}
|
||||
|
||||
impl Default for PathData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
offset: Vec2::zero(),
|
||||
path: Path { width: 5.0 },
|
||||
neighbors: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Path {
|
||||
/// Return the number of blocks of headspace required at the given path
|
||||
/// distance
|
||||
pub fn head_space(&self, dist: f32) -> i32 {
|
||||
(8 - (dist * 0.25).powf(6.0).round() as i32).max(1)
|
||||
}
|
||||
|
||||
/// Get the surface colour of a path given the surrounding surface color
|
||||
pub fn surface_color(&self, col: Rgb<u8>) -> Rgb<u8> { col.map(|e| (e as f32 * 0.7) as u8) }
|
||||
}
|
72
world/src/sim/way.rs
Normal file
72
world/src/sim/way.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use vek::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct Way {
|
||||
/// Offset from chunk center in blocks (no more than half chunk width)
|
||||
pub offset: Vec2<i8>,
|
||||
/// Neighbor connections, one bit each
|
||||
pub neighbors: u8,
|
||||
}
|
||||
|
||||
impl Way {
|
||||
pub fn is_way(&self) -> bool { self.neighbors != 0 }
|
||||
|
||||
pub fn clear(&mut self) { self.neighbors = 0; }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Path {
|
||||
pub width: f32, // Actually radius
|
||||
}
|
||||
|
||||
impl Default for Path {
|
||||
fn default() -> Self {
|
||||
Self { width: 5.0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Lerp for Path {
|
||||
type Output = Self;
|
||||
|
||||
fn lerp_unclamped(from: Self, to: Self, factor: f32) -> Self::Output {
|
||||
Self { width: Lerp::lerp(from.width, to.width, factor) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Path {
|
||||
/// Return the number of blocks of headspace required at the given path
|
||||
/// distance
|
||||
/// TODO: make this generic over width
|
||||
pub fn head_space(&self, dist: f32) -> i32 {
|
||||
(8 - (dist * 0.25).powf(6.0).round() as i32).max(1)
|
||||
}
|
||||
|
||||
/// Get the surface colour of a path given the surrounding surface color
|
||||
pub fn surface_color(&self, col: Rgb<u8>) -> Rgb<u8> { col.map(|e| (e as f32 * 0.7) as u8) }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Cave {
|
||||
pub width: f32, // Actually radius
|
||||
pub alt: f32, // Actually radius
|
||||
}
|
||||
|
||||
impl Default for Cave {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
width: 32.0,
|
||||
alt: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Lerp for Cave {
|
||||
type Output = Self;
|
||||
|
||||
fn lerp_unclamped(from: Self, to: Self, factor: f32) -> Self::Output {
|
||||
Self {
|
||||
width: Lerp::lerp(from.width, to.width, factor),
|
||||
alt: Lerp::lerp(from.alt, to.alt, factor),
|
||||
}
|
||||
}
|
||||
}
|
@ -121,7 +121,7 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
||||
}
|
||||
}
|
||||
|
||||
let mut supply = site.economy.stocks.clone();//MapVec::from_default(0.0);
|
||||
let mut supply = site.economy.stocks.clone(); //MapVec::from_default(0.0);
|
||||
for (labor, (output_good, _)) in productivity.iter() {
|
||||
supply[*output_good] +=
|
||||
site.economy.yields[labor] * site.economy.labors[labor] * site.economy.pop;
|
||||
@ -231,7 +231,8 @@ pub fn tick_site_economy(index: &mut Index, site: Id<Site>, dt: f32) {
|
||||
let (stock, rate) = productivity[*labor];
|
||||
let workers = site.economy.labors[*labor] * site.economy.pop;
|
||||
let final_rate = rate;
|
||||
let yield_per_worker = labor_productivity * final_rate * (1.0 + workers / 100.0).min(3.0);
|
||||
let yield_per_worker =
|
||||
labor_productivity * final_rate * (1.0 + workers / 100.0).min(3.0);
|
||||
site.economy.yields[*labor] = yield_per_worker;
|
||||
site.economy.productivity[*labor] = labor_productivity;
|
||||
let total_output = yield_per_worker * workers;
|
||||
|
@ -102,9 +102,15 @@ impl Economy {
|
||||
|
||||
pub fn replenish(&mut self, time: f32) {
|
||||
use rand::Rng;
|
||||
for (i, (g, v)) in [(Wheat, 50.0), (Logs, 20.0), (Rock, 120.0), (Game, 12.0), (Fish, 10.0)]
|
||||
.iter()
|
||||
.enumerate()
|
||||
for (i, (g, v)) in [
|
||||
(Wheat, 50.0),
|
||||
(Logs, 20.0),
|
||||
(Rock, 120.0),
|
||||
(Game, 12.0),
|
||||
(Fish, 10.0),
|
||||
]
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
self.stocks[*g] = (*v
|
||||
* (1.25 + (((time * 0.0001 + i as f32).sin() + 1.0) % 1.0) * 0.5)
|
||||
|
Loading…
Reference in New Issue
Block a user