mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fmt, make clippy happy
This commit is contained in:
parent
6215682619
commit
26fd40c0e3
@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{humanoid, quadruped_low, quadruped_medium, quadruped_small, Body},
|
comp::{humanoid, quadruped_low, quadruped_medium, quadruped_small, Body},
|
||||||
path::Chaser,
|
path::Chaser,
|
||||||
sync::Uid,
|
|
||||||
rtsim::RtSimController,
|
rtsim::RtSimController,
|
||||||
|
sync::Uid,
|
||||||
};
|
};
|
||||||
use specs::{Component, Entity as EcsEntity};
|
use specs::{Component, Entity as EcsEntity};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
use crate::{
|
use crate::{character::CharacterId, comp, rtsim::RtSimEntity, sync::Uid, util::Dir, Explosion};
|
||||||
character::CharacterId,
|
|
||||||
sync::Uid,
|
|
||||||
util::Dir,
|
|
||||||
comp,
|
|
||||||
Explosion,
|
|
||||||
rtsim::RtSimEntity,
|
|
||||||
};
|
|
||||||
use comp::{
|
use comp::{
|
||||||
item::{Item, Reagent},
|
item::{Item, Reagent},
|
||||||
Ori, Pos,
|
Ori, Pos,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{self, humanoid, Alignment, Body, Item},
|
comp::{self, humanoid, Alignment, Body, Item},
|
||||||
npc::{self, NPC_NAMES},
|
|
||||||
loadout_builder::LoadoutConfig,
|
loadout_builder::LoadoutConfig,
|
||||||
|
npc::{self, NPC_NAMES},
|
||||||
};
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ impl LoadoutBuilder {
|
|||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
pub fn build_loadout(
|
pub fn build_loadout(
|
||||||
body: Body,
|
body: Body,
|
||||||
alignment: Alignment,
|
_alignment: Alignment,
|
||||||
mut main_tool: Option<Item>,
|
mut main_tool: Option<Item>,
|
||||||
is_giant: bool,
|
is_giant: bool,
|
||||||
map: &AbilityMap,
|
map: &AbilityMap,
|
||||||
@ -410,13 +410,11 @@ impl LoadoutBuilder {
|
|||||||
back: None,
|
back: None,
|
||||||
ring: None,
|
ring: None,
|
||||||
neck: None,
|
neck: None,
|
||||||
lantern: Some(Item::new_from_asset_expect(
|
lantern: Some(Item::new_from_asset_expect("common.items.lantern.black_0")),
|
||||||
"common.items.lantern.black_0",
|
|
||||||
)),
|
|
||||||
glider: None,
|
glider: None,
|
||||||
head: None,
|
head: None,
|
||||||
tabard: None,
|
tabard: None,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match body {
|
match body {
|
||||||
|
@ -130,7 +130,8 @@ impl Route {
|
|||||||
|
|
||||||
// Determine whether we're close enough to the next to to consider it completed
|
// Determine whether we're close enough to the next to to consider it completed
|
||||||
let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy());
|
let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy());
|
||||||
if dist_sqrd < traversal_cfg.node_tolerance.powf(2.0) * if be_precise { 0.25 } else { 1.0 }
|
if dist_sqrd
|
||||||
|
< traversal_cfg.node_tolerance.powf(2.0) * if be_precise { 0.25 } else { 1.0 }
|
||||||
&& (((pos.z - closest_tgt.z > 1.2 || (pos.z - closest_tgt.z > -0.2 && traversal_cfg.on_ground))
|
&& (((pos.z - closest_tgt.z > 1.2 || (pos.z - closest_tgt.z > -0.2 && traversal_cfg.on_ground))
|
||||||
&& (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05))
|
&& (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05))
|
||||||
&& vel.z <= 0.0
|
&& vel.z <= 0.0
|
||||||
@ -142,7 +143,9 @@ impl Route {
|
|||||||
.0
|
.0
|
||||||
> pos.distance(closest_tgt) * 0.9 || dist_sqrd < 0.5)
|
> pos.distance(closest_tgt) * 0.9 || dist_sqrd < 0.5)
|
||||||
&& self.next_idx < self.path.len())
|
&& self.next_idx < self.path.len())
|
||||||
|| (traversal_cfg.in_liquid && pos.z < closest_tgt.z + 0.8 && pos.z > closest_tgt.z))
|
|| (traversal_cfg.in_liquid
|
||||||
|
&& pos.z < closest_tgt.z + 0.8
|
||||||
|
&& pos.z > closest_tgt.z))
|
||||||
{
|
{
|
||||||
// Node completed, move on to the next one
|
// Node completed, move on to the next one
|
||||||
self.next_idx += 1;
|
self.next_idx += 1;
|
||||||
@ -438,15 +441,14 @@ fn walkable<V>(vol: &V, pos: Vec3<i32>) -> bool
|
|||||||
where
|
where
|
||||||
V: BaseVol<Vox = Block> + ReadVol,
|
V: BaseVol<Vox = Block> + ReadVol,
|
||||||
{
|
{
|
||||||
let below = vol.get(pos - Vec3::unit_z())
|
let below = vol
|
||||||
|
.get(pos - Vec3::unit_z())
|
||||||
.ok()
|
.ok()
|
||||||
.copied()
|
.copied()
|
||||||
.unwrap_or_else(Block::empty);
|
.unwrap_or_else(Block::empty);
|
||||||
let a = vol.get(pos)
|
let a = vol.get(pos).ok().copied().unwrap_or_else(Block::empty);
|
||||||
.ok()
|
let b = vol
|
||||||
.copied()
|
.get(pos + Vec3::unit_z())
|
||||||
.unwrap_or_else(Block::empty);
|
|
||||||
let b = vol.get(pos + Vec3::unit_z())
|
|
||||||
.ok()
|
.ok()
|
||||||
.copied()
|
.copied()
|
||||||
.unwrap_or_else(Block::empty);
|
.unwrap_or_else(Block::empty);
|
||||||
@ -513,10 +515,10 @@ where
|
|||||||
];
|
];
|
||||||
|
|
||||||
const JUMPS: [Vec3<i32>; 4] = [
|
const JUMPS: [Vec3<i32>; 4] = [
|
||||||
Vec3::new(0, 1, 2), // Forward Upwardx2
|
Vec3::new(0, 1, 2), // Forward Upwardx2
|
||||||
Vec3::new(1, 0, 2), // Right Upwardx2
|
Vec3::new(1, 0, 2), // Right Upwardx2
|
||||||
Vec3::new(0, -1, 2), // Backward Upwardx2
|
Vec3::new(0, -1, 2), // Backward Upwardx2
|
||||||
Vec3::new(-1, 0, 2), // Left Upwardx2
|
Vec3::new(-1, 0, 2), // Left Upwardx2
|
||||||
];
|
];
|
||||||
|
|
||||||
// let walkable = [
|
// let walkable = [
|
||||||
@ -538,13 +540,15 @@ where
|
|||||||
// ];
|
// ];
|
||||||
|
|
||||||
DIRS.iter()
|
DIRS.iter()
|
||||||
.chain(Some(JUMPS.iter())
|
.chain(
|
||||||
.filter(|_| vol
|
Some(JUMPS.iter())
|
||||||
.get(pos)
|
.filter(|_| {
|
||||||
.map(|b| !b.is_liquid())
|
vol.get(pos).map(|b| !b.is_liquid()).unwrap_or(true)
|
||||||
.unwrap_or(true) || traversal_cfg.can_climb)
|
|| traversal_cfg.can_climb
|
||||||
.into_iter()
|
})
|
||||||
.flatten())
|
.into_iter()
|
||||||
|
.flatten(),
|
||||||
|
)
|
||||||
.map(move |dir| (pos, dir))
|
.map(move |dir| (pos, dir))
|
||||||
.filter(move |(pos, dir)| {
|
.filter(move |(pos, dir)| {
|
||||||
is_walkable(pos)
|
is_walkable(pos)
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
// `Agent`). When possible, this should be moved to the `rtsim`
|
// `Agent`). When possible, this should be moved to the `rtsim`
|
||||||
// module in `server`.
|
// module in `server`.
|
||||||
|
|
||||||
use specs_idvs::IdvStorage;
|
|
||||||
use specs::Component;
|
use specs::Component;
|
||||||
|
use specs_idvs::IdvStorage;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
pub type RtSimId = usize;
|
pub type RtSimId = usize;
|
||||||
@ -16,20 +16,20 @@ impl Component for RtSimEntity {
|
|||||||
type Storage = IdvStorage<Self>;
|
type Storage = IdvStorage<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This type is the map route through which the rtsim (real-time simulation) aspect
|
/// This type is the map route through which the rtsim (real-time simulation)
|
||||||
/// of the game communicates with the rest of the game. It is analagous to
|
/// aspect of the game communicates with the rest of the game. It is analagous
|
||||||
/// `comp::Controller` in that it provides a consistent interface for simulation NPCs
|
/// to `comp::Controller` in that it provides a consistent interface for
|
||||||
/// to control their actions. Unlike `comp::Controller`, it is very abstract and is
|
/// simulation NPCs to control their actions. Unlike `comp::Controller`, it is
|
||||||
/// intended for consumption by both the agent code and the internal rtsim simulation
|
/// very abstract and is intended for consumption by both the agent code and the
|
||||||
/// code (depending on whether the entity is loaded into the game as a physical entity
|
/// internal rtsim simulation code (depending on whether the entity is loaded
|
||||||
/// or not). Agent code should attempt to act upon its instructions where reasonable
|
/// into the game as a physical entity or not). Agent code should attempt to act
|
||||||
/// although deviations for various reasons (obstacle avoidance, counter-attacking,
|
/// upon its instructions where reasonable although deviations for various
|
||||||
/// etc.) are expected.
|
/// reasons (obstacle avoidance, counter-attacking, etc.) are expected.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct RtSimController {
|
pub struct RtSimController {
|
||||||
/// When this field is `Some(..)`, the agent should attempt to make progress
|
/// When this field is `Some(..)`, the agent should attempt to make progress
|
||||||
/// toward the given location, accounting for obstacles and other high-priority
|
/// toward the given location, accounting for obstacles and other
|
||||||
/// situations like being attacked.
|
/// high-priority situations like being attacked.
|
||||||
pub travel_to: Option<Vec3<f32>>,
|
pub travel_to: Option<Vec3<f32>>,
|
||||||
/// Proportion of full speed to move
|
/// Proportion of full speed to move
|
||||||
pub speed_factor: f32,
|
pub speed_factor: f32,
|
||||||
@ -45,7 +45,5 @@ impl Default for RtSimController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RtSimController {
|
impl RtSimController {
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) { *self = Self::default(); }
|
||||||
*self = Self::default();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,10 @@ use crate::{
|
|||||||
},
|
},
|
||||||
event::LocalEvent,
|
event::LocalEvent,
|
||||||
states::*,
|
states::*,
|
||||||
sys::{character_behavior::JoinData, phys::{GRAVITY, FRIC_GROUND}},
|
sys::{
|
||||||
|
character_behavior::JoinData,
|
||||||
|
phys::{FRIC_GROUND, GRAVITY},
|
||||||
|
},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -95,6 +98,7 @@ impl Body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::match_like_matches_macro)]
|
||||||
pub fn can_climb(&self) -> bool {
|
pub fn can_climb(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Body::Humanoid(_) => true,
|
Body::Humanoid(_) => true,
|
||||||
|
@ -223,24 +223,18 @@ impl<'a> System<'a> for Sys {
|
|||||||
match &mut agent.activity {
|
match &mut agent.activity {
|
||||||
Activity::Idle { bearing, chaser } => {
|
Activity::Idle { bearing, chaser } => {
|
||||||
if let Some(travel_to) = agent.rtsim_controller.travel_to {
|
if let Some(travel_to) = agent.rtsim_controller.travel_to {
|
||||||
if let Some((bearing, speed)) = chaser.chase(
|
if let Some((bearing, speed)) =
|
||||||
&*terrain,
|
chaser.chase(&*terrain, pos.0, vel.0, travel_to, TraversalConfig {
|
||||||
pos.0,
|
|
||||||
vel.0,
|
|
||||||
travel_to,
|
|
||||||
TraversalConfig {
|
|
||||||
min_tgt_dist: 1.25,
|
min_tgt_dist: 1.25,
|
||||||
..traversal_config
|
..traversal_config
|
||||||
},
|
})
|
||||||
) {
|
{
|
||||||
inputs.move_dir = bearing
|
inputs.move_dir =
|
||||||
.xy()
|
bearing.xy().try_normalized().unwrap_or(Vec2::zero())
|
||||||
.try_normalized()
|
* speed.min(agent.rtsim_controller.speed_factor);
|
||||||
.unwrap_or(Vec2::zero())
|
|
||||||
* speed.min(agent.rtsim_controller.speed_factor);
|
|
||||||
inputs.jump.set_state(bearing.z > 1.5);
|
inputs.jump.set_state(bearing.z > 1.5);
|
||||||
inputs.climb = Some(comp::Climb::Up);
|
inputs.climb = Some(comp::Climb::Up);
|
||||||
//.filter(|_| bearing.z > 0.1 || physics_state.in_liquid.is_some());
|
//.filter(|_| bearing.z > 0.1 || physics_state.in_liquid.is_some());
|
||||||
inputs.move_z = bearing.z + 0.05;
|
inputs.move_z = bearing.z + 0.05;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,7 +19,7 @@ use roots::find_roots_cubic;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
vol::{RectVolSize, ReadVol},
|
vol::{ReadVol, RectVolSize},
|
||||||
volumes::vol_grid_2d::VolGrid2d,
|
volumes::vol_grid_2d::VolGrid2d,
|
||||||
};
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
@ -437,14 +437,15 @@ fn handle_time(
|
|||||||
// Accept `u12345`, seconds since midnight day 0
|
// Accept `u12345`, seconds since midnight day 0
|
||||||
Err(_) => match n
|
Err(_) => match n
|
||||||
.get(1..)
|
.get(1..)
|
||||||
.filter(|_| n.chars().next() == Some('u'))
|
.filter(|_| n.starts_with('u'))
|
||||||
.and_then(|n| n.trim_left_matches('u').parse::<u64>().ok())
|
.and_then(|n| n.trim_start_matches('u').parse::<u64>().ok())
|
||||||
{
|
{
|
||||||
Some(n) => n as f64,
|
Some(n) => n as f64,
|
||||||
None => {
|
None => {
|
||||||
server.notify_client(
|
server.notify_client(
|
||||||
client,
|
client,
|
||||||
ChatType::CommandError.server_msg(format!("'{}' is not a valid time.", n)),
|
ChatType::CommandError
|
||||||
|
.server_msg(format!("'{}' is not a valid time.", n)),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
@ -454,9 +455,49 @@ fn handle_time(
|
|||||||
None => {
|
None => {
|
||||||
let time_in_seconds = server.state.ecs_mut().read_resource::<TimeOfDay>().0;
|
let time_in_seconds = server.state.ecs_mut().read_resource::<TimeOfDay>().0;
|
||||||
|
|
||||||
|
// Would this ever change? Perhaps in a few hundred thousand years some
|
||||||
|
// game archeologists of the future will resurrect the best game of all
|
||||||
|
// time which, obviously, would be Veloren. By that time, the inescapable
|
||||||
|
// laws of thermodynamics will mean that the earth's rotation period
|
||||||
|
// would be slower. Of course, a few hundred thousand years is enough
|
||||||
|
// for the circadian rhythm of human biology to have shifted to account
|
||||||
|
// accordingly. When booting up Veloren for the first time in 337,241
|
||||||
|
// years, they might feel a touch of anguish at the fact that their
|
||||||
|
// earth days and the days within the game do not neatly divide into
|
||||||
|
// one-another. Understandably, they'll want to change this. Who
|
||||||
|
// wouldn't? It would be like turning the TV volume up to an odd number
|
||||||
|
// or having a slightly untuned radio (assuming they haven't begun
|
||||||
|
// broadcasting information directly into their brains). Totally
|
||||||
|
// unacceptable. No, the correct and proper thing to do would be to
|
||||||
|
// release a retroactive definitive edition DLC for $99 with the very
|
||||||
|
// welcome addition of shorter day periods and a complementary
|
||||||
|
// 'developer commentary' mode created by digging up the long-decayed
|
||||||
|
// skeletons of the Veloren team, measuring various attributes of their
|
||||||
|
// jawlines, and using them to recreate their voices. But how to go about
|
||||||
|
// this Herculean task? This code is jibberish! The last of the core Rust
|
||||||
|
// dev team died exactly 337,194 years ago! Rust is now a long-forgotten
|
||||||
|
// dialect of the ancient ones, lost to the sands of time. Ashes to ashes,
|
||||||
|
// dust to dust. When all hope is lost, one particularly intrepid
|
||||||
|
// post-human hominid exployed by the 'Veloren Revival Corp' (no doubt we
|
||||||
|
// still won't have gotted rid of this blasted 'capitalism' thing by then)
|
||||||
|
// might notice, after years of searching, a particularly curious
|
||||||
|
// inscription within the code. The letters `D`, `A`, `Y`. Curious! She
|
||||||
|
// consults the post-human hominid scholars of the old. Care to empathise
|
||||||
|
// with her shock when she discovers that these symbols, as alien as they
|
||||||
|
// may seem, correspond exactly to the word `ⓕя𝐢ᵇᵇ𝔩E`, the word for
|
||||||
|
// 'day' in the post-human hominid language, which is of course universal.
|
||||||
|
// Imagine also her surprise when, after much further translating, she
|
||||||
|
// finds a comment predicting her very existence and her struggle to
|
||||||
|
// decode this great mystery. Rejoyce! The Veloren Revival Corp. may now
|
||||||
|
// persist with their great Ultimate Edition DLC because the day period
|
||||||
|
// might now be changed because they have found the constant that controls
|
||||||
|
// it! Everybody was henceforth happy until the end of time.
|
||||||
|
//
|
||||||
|
// This one's for you, xMac ;)
|
||||||
|
const DAY: u64 = 86400;
|
||||||
let current_time = NaiveTime::from_num_seconds_from_midnight_opt(
|
let current_time = NaiveTime::from_num_seconds_from_midnight_opt(
|
||||||
// Wraps around back to 0s if it exceeds 24 hours (24 hours = 86400s)
|
// Wraps around back to 0s if it exceeds 24 hours (24 hours = 86400s)
|
||||||
(time_in_seconds as u64 % 86400) as u32,
|
(time_in_seconds as u64 % DAY) as u32,
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
let msg = match current_time {
|
let msg = match current_time {
|
||||||
@ -470,14 +511,14 @@ fn handle_time(
|
|||||||
|
|
||||||
server.state.ecs_mut().write_resource::<TimeOfDay>().0 = new_time;
|
server.state.ecs_mut().write_resource::<TimeOfDay>().0 = new_time;
|
||||||
|
|
||||||
if let Some(new_time) = NaiveTime::from_num_seconds_from_midnight_opt(((new_time as u64) % 86400) as u32, 0) {
|
if let Some(new_time) =
|
||||||
|
NaiveTime::from_num_seconds_from_midnight_opt(((new_time as u64) % 86400) as u32, 0)
|
||||||
|
{
|
||||||
server.notify_client(
|
server.notify_client(
|
||||||
client,
|
client,
|
||||||
ChatType::CommandInfo.server_msg(format!(
|
ChatType::CommandInfo.server_msg(format!(
|
||||||
"Time changed to: {}",
|
"Time changed to: {}",
|
||||||
new_time
|
new_time.format("%H:%M").to_string(),
|
||||||
.format("%H:%M")
|
|
||||||
.to_string(),
|
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ use common::{
|
|||||||
LightEmitter, Loadout, Ori, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
LightEmitter, Loadout, Ori, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||||
},
|
},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
util::Dir,
|
|
||||||
rtsim::RtSimEntity,
|
rtsim::RtSimEntity,
|
||||||
|
util::Dir,
|
||||||
};
|
};
|
||||||
use comp::group;
|
use comp::group;
|
||||||
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::Client,
|
client::Client,
|
||||||
comp::{biped_large, quadruped_medium, quadruped_small, PhysicsState},
|
comp::{biped_large, quadruped_medium, quadruped_small, PhysicsState},
|
||||||
Server, SpawnPoint, StateExt,
|
|
||||||
rtsim::RtSim,
|
rtsim::RtSim,
|
||||||
|
Server, SpawnPoint, StateExt,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
assets::Asset,
|
assets::Asset,
|
||||||
@ -16,12 +16,12 @@ use common::{
|
|||||||
lottery::Lottery,
|
lottery::Lottery,
|
||||||
msg::{PlayerListUpdate, ServerGeneral},
|
msg::{PlayerListUpdate, ServerGeneral},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
|
rtsim::RtSimEntity,
|
||||||
state::BlockChange,
|
state::BlockChange,
|
||||||
sync::{Uid, UidAllocator, WorldSyncExt},
|
sync::{Uid, UidAllocator, WorldSyncExt},
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
|
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
|
||||||
rtsim::RtSimEntity,
|
|
||||||
};
|
};
|
||||||
use comp::item::Reagent;
|
use comp::item::Reagent;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
@ -462,8 +462,16 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
|||||||
};
|
};
|
||||||
|
|
||||||
if should_delete {
|
if should_delete {
|
||||||
if let Some(rtsim_entity) = state.ecs().read_storage::<RtSimEntity>().get(entity).copied() {
|
if let Some(rtsim_entity) = state
|
||||||
state.ecs().write_resource::<RtSim>().destroy_entity(rtsim_entity.0);
|
.ecs()
|
||||||
|
.read_storage::<RtSimEntity>()
|
||||||
|
.get(entity)
|
||||||
|
.copied()
|
||||||
|
{
|
||||||
|
state
|
||||||
|
.ecs()
|
||||||
|
.write_resource::<RtSim>()
|
||||||
|
.destroy_entity(rtsim_entity.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = state
|
let _ = state
|
||||||
|
@ -8,8 +8,8 @@ use entity_creation::{
|
|||||||
handle_loaded_character_data, handle_shockwave, handle_shoot,
|
handle_loaded_character_data, handle_shockwave, handle_shoot,
|
||||||
};
|
};
|
||||||
use entity_manipulation::{
|
use entity_manipulation::{
|
||||||
handle_buff, handle_damage, handle_destroy, handle_delete, handle_energy_change, handle_explosion,
|
handle_buff, handle_damage, handle_delete, handle_destroy, handle_energy_change,
|
||||||
handle_knockback, handle_land_on_ground, handle_level_up, handle_respawn,
|
handle_explosion, handle_knockback, handle_land_on_ground, handle_level_up, handle_respawn,
|
||||||
};
|
};
|
||||||
use group_manip::handle_group;
|
use group_manip::handle_group;
|
||||||
use interaction::{handle_lantern, handle_mount, handle_possess, handle_unmount};
|
use interaction::{handle_lantern, handle_mount, handle_possess, handle_unmount};
|
||||||
@ -120,8 +120,18 @@ impl Server {
|
|||||||
drop_item,
|
drop_item,
|
||||||
rtsim_entity,
|
rtsim_entity,
|
||||||
} => handle_create_npc(
|
} => handle_create_npc(
|
||||||
self, pos, stats, health, loadout, body, agent, alignment, scale, drop_item,
|
self,
|
||||||
home_chunk, rtsim_entity,
|
pos,
|
||||||
|
stats,
|
||||||
|
health,
|
||||||
|
loadout,
|
||||||
|
body,
|
||||||
|
agent,
|
||||||
|
alignment,
|
||||||
|
scale,
|
||||||
|
drop_item,
|
||||||
|
home_chunk,
|
||||||
|
rtsim_entity,
|
||||||
),
|
),
|
||||||
ServerEvent::CreateWaypoint(pos) => handle_create_waypoint(self, pos),
|
ServerEvent::CreateWaypoint(pos) => handle_create_waypoint(self, pos),
|
||||||
ServerEvent::ClientDisconnect(entity) => {
|
ServerEvent::ClientDisconnect(entity) => {
|
||||||
|
@ -52,9 +52,7 @@ use common::{
|
|||||||
comp::{self, ChatType},
|
comp::{self, ChatType},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
msg::{
|
msg::{
|
||||||
world_msg::{SiteInfo, SiteKind},
|
ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg,
|
||||||
ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg,
|
|
||||||
WorldMapMsg,
|
|
||||||
},
|
},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
recipe::default_recipe_book,
|
recipe::default_recipe_book,
|
||||||
@ -62,7 +60,7 @@ use common::{
|
|||||||
state::{State, TimeOfDay},
|
state::{State, TimeOfDay},
|
||||||
sync::WorldSyncExt,
|
sync::WorldSyncExt,
|
||||||
terrain::TerrainChunkSize,
|
terrain::TerrainChunkSize,
|
||||||
vol::{ReadVol, RectVolSize},
|
vol::RectVolSize,
|
||||||
};
|
};
|
||||||
use futures_executor::block_on;
|
use futures_executor::block_on;
|
||||||
use metrics::{PhysicsMetrics, ServerMetrics, StateTickMetrics, TickMetrics};
|
use metrics::{PhysicsMetrics, ServerMetrics, StateTickMetrics, TickMetrics};
|
||||||
@ -327,7 +325,7 @@ impl Server {
|
|||||||
|
|
||||||
// Insert the world into the ECS (todo: Maybe not an Arc?)
|
// Insert the world into the ECS (todo: Maybe not an Arc?)
|
||||||
let world = Arc::new(world);
|
let world = Arc::new(world);
|
||||||
state.ecs_mut().insert(world.clone());
|
state.ecs_mut().insert(Arc::clone(&world));
|
||||||
state.ecs_mut().insert(index.clone());
|
state.ecs_mut().insert(index.clone());
|
||||||
|
|
||||||
// Set starting time for the server.
|
// Set starting time for the server.
|
||||||
|
@ -10,9 +10,7 @@ pub struct Chunks {
|
|||||||
impl Chunks {
|
impl Chunks {
|
||||||
pub fn new(size: Vec2<u32>) -> Self {
|
pub fn new(size: Vec2<u32>) -> Self {
|
||||||
Chunks {
|
Chunks {
|
||||||
chunks: Grid::populate_from(size.map(|e| e as i32), |_| Chunk {
|
chunks: Grid::populate_from(size.map(|e| e as i32), |_| Chunk { is_loaded: false }),
|
||||||
is_loaded: false,
|
|
||||||
}),
|
|
||||||
chunks_to_load: Vec::new(),
|
chunks_to_load: Vec::new(),
|
||||||
chunks_to_unload: Vec::new(),
|
chunks_to_unload: Vec::new(),
|
||||||
}
|
}
|
||||||
@ -25,7 +23,9 @@ impl Chunks {
|
|||||||
pub fn chunk_mut(&mut self, key: Vec2<i32>) -> Option<&mut Chunk> { self.chunks.get_mut(key) }
|
pub fn chunk_mut(&mut self, key: Vec2<i32>) -> Option<&mut Chunk> { self.chunks.get_mut(key) }
|
||||||
|
|
||||||
pub fn chunk_at(&self, pos: Vec2<f32>) -> Option<&Chunk> {
|
pub fn chunk_at(&self, pos: Vec2<f32>) -> Option<&Chunk> {
|
||||||
self.chunks.get(pos.map2(TerrainChunk::RECT_SIZE, |e, sz| (e.floor() as i32).div_euclid(sz as i32)))
|
self.chunks.get(pos.map2(TerrainChunk::RECT_SIZE, |e, sz| {
|
||||||
|
(e.floor() as i32).div_euclid(sz as i32)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use common::event::{EventBus, ServerEvent};
|
use common::event::{EventBus, ServerEvent};
|
||||||
use specs::{Join, Read, ReadStorage, System, Write, WriteExpect};
|
use specs::{Read, System, WriteExpect};
|
||||||
|
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
type SystemData = (
|
#[allow(clippy::type_complexity)]
|
||||||
Read<'a, EventBus<ServerEvent>>,
|
type SystemData = (Read<'a, EventBus<ServerEvent>>, WriteExpect<'a, RtSim>);
|
||||||
WriteExpect<'a, RtSim>,
|
|
||||||
);
|
|
||||||
|
|
||||||
fn run(&mut self, (server_event_bus, mut rtsim): Self::SystemData) {
|
fn run(&mut self, (_server_event_bus, mut rtsim): Self::SystemData) {
|
||||||
for chunk in std::mem::take(&mut rtsim.chunks.chunks_to_load) {
|
for _chunk in std::mem::take(&mut rtsim.chunks.chunks_to_load) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,23 @@
|
|||||||
mod load_chunks;
|
#![allow(dead_code)] // TODO: Remove this when rtsim is fleshed out
|
||||||
mod unload_chunks;
|
|
||||||
mod tick;
|
|
||||||
mod entity;
|
|
||||||
mod chunks;
|
|
||||||
|
|
||||||
use vek::*;
|
mod chunks;
|
||||||
|
mod entity;
|
||||||
|
mod load_chunks;
|
||||||
|
mod tick;
|
||||||
|
mod unload_chunks;
|
||||||
|
|
||||||
|
use self::{chunks::Chunks, entity::Entity};
|
||||||
use common::{
|
use common::{
|
||||||
|
comp,
|
||||||
|
rtsim::{RtSimController, RtSimEntity, RtSimId},
|
||||||
state::State,
|
state::State,
|
||||||
terrain::TerrainChunk,
|
terrain::TerrainChunk,
|
||||||
rtsim::{RtSimEntity, RtSimId, RtSimController},
|
|
||||||
vol::RectRasterableVol,
|
vol::RectRasterableVol,
|
||||||
comp,
|
|
||||||
};
|
};
|
||||||
use specs::{DispatcherBuilder, WorldExt};
|
|
||||||
use specs_idvs::IdvStorage;
|
|
||||||
use slab::Slab;
|
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use self::{
|
use slab::Slab;
|
||||||
entity::Entity,
|
use specs::{DispatcherBuilder, WorldExt};
|
||||||
chunks::Chunks,
|
use vek::*;
|
||||||
};
|
|
||||||
|
|
||||||
pub struct RtSim {
|
pub struct RtSim {
|
||||||
tick: u64,
|
tick: u64,
|
||||||
@ -88,12 +86,14 @@ pub fn init(state: &mut State, world: &world::World) {
|
|||||||
let mut rtsim = RtSim::new(world.sim().get_size());
|
let mut rtsim = RtSim::new(world.sim().get_size());
|
||||||
|
|
||||||
for _ in 0..2500 {
|
for _ in 0..2500 {
|
||||||
let pos = rtsim.chunks.size().map2(
|
let pos = rtsim
|
||||||
TerrainChunk::RECT_SIZE,
|
.chunks
|
||||||
|sz, chunk_sz| thread_rng().gen_range(0, sz * chunk_sz) as i32,
|
.size()
|
||||||
);
|
.map2(TerrainChunk::RECT_SIZE, |sz, chunk_sz| {
|
||||||
|
thread_rng().gen_range(0, sz * chunk_sz) as i32
|
||||||
|
});
|
||||||
|
|
||||||
let id = rtsim.entities.insert(Entity {
|
rtsim.entities.insert(Entity {
|
||||||
is_loaded: false,
|
is_loaded: false,
|
||||||
pos: Vec3::from(pos.map(|e| e as f32)),
|
pos: Vec3::from(pos.map(|e| e as f32)),
|
||||||
seed: thread_rng().gen(),
|
seed: thread_rng().gen(),
|
||||||
@ -101,8 +101,6 @@ pub fn init(state: &mut State, world: &world::World) {
|
|||||||
last_tick: 0,
|
last_tick: 0,
|
||||||
brain: Default::default(),
|
brain: Default::default(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// tracing::info!("Spawned rtsim NPC {} at {:?}", id, pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.ecs_mut().insert(rtsim);
|
state.ecs_mut().insert(rtsim);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![allow(dead_code)] // TODO: Remove this when rtsim is fleshed out
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use common::{
|
use common::{
|
||||||
comp,
|
comp,
|
||||||
@ -12,6 +14,7 @@ const ENTITY_TICK_PERIOD: u64 = 30;
|
|||||||
|
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
Read<'a, DeltaTime>,
|
Read<'a, DeltaTime>,
|
||||||
Read<'a, EventBus<ServerEvent>>,
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
@ -33,7 +36,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut rtsim,
|
mut rtsim,
|
||||||
terrain,
|
terrain,
|
||||||
world,
|
world,
|
||||||
index,
|
_index,
|
||||||
positions,
|
positions,
|
||||||
rtsim_entities,
|
rtsim_entities,
|
||||||
mut agents,
|
mut agents,
|
||||||
|
@ -4,10 +4,11 @@ use common::{
|
|||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
terrain::TerrainGrid,
|
terrain::TerrainGrid,
|
||||||
};
|
};
|
||||||
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write, WriteExpect};
|
use specs::{Entities, Read, ReadExpect, ReadStorage, System, WriteExpect};
|
||||||
|
|
||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
Read<'a, EventBus<ServerEvent>>,
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
WriteExpect<'a, RtSim>,
|
WriteExpect<'a, RtSim>,
|
||||||
@ -20,17 +21,17 @@ impl<'a> System<'a> for Sys {
|
|||||||
fn run(
|
fn run(
|
||||||
&mut self,
|
&mut self,
|
||||||
(
|
(
|
||||||
server_event_bus,
|
_server_event_bus,
|
||||||
mut rtsim,
|
mut rtsim,
|
||||||
terrain_grid,
|
_terrain_grid,
|
||||||
entities,
|
_entities,
|
||||||
rtsim_entities,
|
_rtsim_entities,
|
||||||
positions,
|
_positions,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let chunks = std::mem::take(&mut rtsim.chunks.chunks_to_unload);
|
let chunks = std::mem::take(&mut rtsim.chunks.chunks_to_unload);
|
||||||
|
|
||||||
for chunk in chunks {
|
for _chunk in chunks {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use common::{
|
|||||||
use criterion::{black_box, criterion_group, criterion_main, Benchmark, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Benchmark, Criterion};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use veloren_voxygen::mesh::Meshable;
|
use veloren_voxygen::{mesh::Meshable, scene::terrain::BlocksOfInterest};
|
||||||
use world::{sim, World};
|
use world::{sim, World};
|
||||||
|
|
||||||
const CENTER: Vec2<i32> = Vec2 { x: 512, y: 512 };
|
const CENTER: Vec2<i32> = Vec2 { x: 512, y: 512 };
|
||||||
@ -133,7 +133,7 @@ pub fn criterion_benchmark(c: &mut Criterion) {
|
|||||||
c.bench(
|
c.bench(
|
||||||
"meshing",
|
"meshing",
|
||||||
Benchmark::new(&format!("Terrain mesh {}, {}", x, y), move |b| {
|
Benchmark::new(&format!("Terrain mesh {}, {}", x, y), move |b| {
|
||||||
b.iter(|| volume.generate_mesh(black_box((range, Vec2::new(8192, 8192)))))
|
b.iter(|| volume.generate_mesh(black_box((range, Vec2::new(8192, 8192), &BlocksOfInterest::default()))))
|
||||||
})
|
})
|
||||||
// Lower sample size to save time
|
// Lower sample size to save time
|
||||||
.sample_size(15),
|
.sample_size(15),
|
||||||
|
@ -489,15 +489,11 @@ impl<'a> Widget for Map<'a> {
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let title =
|
let title = site.name.as_deref().unwrap_or_else(|| match &site.kind {
|
||||||
site.name
|
SiteKind::Town => i18n.get("hud.map.town"),
|
||||||
.as_ref()
|
SiteKind::Dungeon { .. } => i18n.get("hud.map.dungeon"),
|
||||||
.map(|s| s.as_str())
|
SiteKind::Castle => i18n.get("hud.map.castle"),
|
||||||
.unwrap_or_else(|| match &site.kind {
|
});
|
||||||
SiteKind::Town => i18n.get("hud.map.town"),
|
|
||||||
SiteKind::Dungeon { .. } => i18n.get("hud.map.dungeon"),
|
|
||||||
SiteKind::Castle => i18n.get("hud.map.castle"),
|
|
||||||
});
|
|
||||||
let (difficulty, desc) = match &site.kind {
|
let (difficulty, desc) = match &site.kind {
|
||||||
SiteKind::Town => (0, i18n.get("hud.map.town").to_string()),
|
SiteKind::Town => (0, i18n.get("hud.map.town").to_string()),
|
||||||
SiteKind::Dungeon { difficulty } => (
|
SiteKind::Dungeon { difficulty } => (
|
||||||
@ -656,10 +652,9 @@ impl<'a> Widget for Map<'a> {
|
|||||||
Vec2::new(32.0, 37.0) * scale
|
Vec2::new(32.0, 37.0) * scale
|
||||||
};
|
};
|
||||||
// Hide if icon could go off of the edge of the map
|
// Hide if icon could go off of the edge of the map
|
||||||
|
let arrow_mag = arrow_sz.map(|e| e as f32 / 2.0).magnitude();
|
||||||
if !rpos
|
if !rpos
|
||||||
.map2(map_size, |e, sz| {
|
.map2(map_size, |e, sz| e.abs() + arrow_mag > sz as f32 / 2.0)
|
||||||
e.abs() + arrow_sz.map(|e| e as f32 / 2.0).magnitude() > sz as f32 / 2.0
|
|
||||||
})
|
|
||||||
.reduce_or()
|
.reduce_or()
|
||||||
{
|
{
|
||||||
Image::new(self.rot_imgs.indicator_mmap_small.target_north)
|
Image::new(self.rot_imgs.indicator_mmap_small.target_north)
|
||||||
|
@ -2291,7 +2291,7 @@ impl Hud {
|
|||||||
// Reset the map position when it's not showing
|
// Reset the map position when it's not showing
|
||||||
let drag = &global_state.settings.gameplay.map_drag;
|
let drag = &global_state.settings.gameplay.map_drag;
|
||||||
if drag.x != 0.0 || drag.y != 0.0 {
|
if drag.x != 0.0 || drag.y != 0.0 {
|
||||||
events.push(Event::MapDrag(drag - drag))
|
events.push(Event::MapDrag(Vec2::zero()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,16 +586,15 @@ fn draw_col_lights<D>(
|
|||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
) / 4.0;
|
) / 4.0;
|
||||||
let glowiness = (
|
let glowiness = (get_glow(data, light_pos)
|
||||||
get_glow(data, light_pos)
|
+ get_glow(data, light_pos - uv.x)
|
||||||
+ get_glow(data, light_pos - uv.x)
|
+ get_glow(data, light_pos - uv.y)
|
||||||
+ get_glow(data, light_pos - uv.y)
|
+ if direct_u_opacity || direct_v_opacity {
|
||||||
+ if direct_u_opacity || direct_v_opacity {
|
get_glow(data, light_pos - uv.x - uv.y)
|
||||||
get_glow(data, light_pos - uv.x - uv.y)
|
} else {
|
||||||
} else {
|
0.0
|
||||||
0.0
|
})
|
||||||
}
|
/ 4.0;
|
||||||
) / 4.0;
|
|
||||||
let col = get_color(data, pos);
|
let col = get_color(data, pos);
|
||||||
let light = (darkness * 31.5) as u8;
|
let light = (darkness * 31.5) as u8;
|
||||||
let glow = (glowiness * 31.5) as u8;
|
let glow = (glowiness * 31.5) as u8;
|
||||||
|
@ -77,7 +77,7 @@ where
|
|||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let get_glow = |vol: &mut V, pos: Vec3<i32>| 0.0;
|
let get_glow = |_vol: &mut V, _pos: Vec3<i32>| 0.0;
|
||||||
let get_color = |vol: &mut V, pos: Vec3<i32>| {
|
let get_color = |vol: &mut V, pos: Vec3<i32>| {
|
||||||
vol.get(pos)
|
vol.get(pos)
|
||||||
.ok()
|
.ok()
|
||||||
|
@ -250,6 +250,7 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug + 'static>
|
|||||||
Meshable<TerrainPipeline, FluidPipeline> for &'a VolGrid2d<V>
|
Meshable<TerrainPipeline, FluidPipeline> for &'a VolGrid2d<V>
|
||||||
{
|
{
|
||||||
type Pipeline = TerrainPipeline;
|
type Pipeline = TerrainPipeline;
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
type Result = (
|
type Result = (
|
||||||
Aabb<f32>,
|
Aabb<f32>,
|
||||||
ColLightInfo,
|
ColLightInfo,
|
||||||
@ -468,7 +469,12 @@ impl<'a, V: RectRasterableVol<Vox = Block> + ReadVol + Debug + 'static>
|
|||||||
opaque_mesh,
|
opaque_mesh,
|
||||||
fluid_mesh,
|
fluid_mesh,
|
||||||
Mesh::new(),
|
Mesh::new(),
|
||||||
(bounds, (col_lights, col_lights_size), Box::new(light), Box::new(glow)),
|
(
|
||||||
|
bounds,
|
||||||
|
(col_lights, col_lights_size),
|
||||||
|
Box::new(light),
|
||||||
|
Box::new(glow),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,14 @@ impl Vertex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn new(mat: Mat4<f32>, wind_sway: f32, pos: Vec3<i32>, ori_bits: u8, light: f32, glow: f32) -> Self {
|
pub fn new(
|
||||||
|
mat: Mat4<f32>,
|
||||||
|
wind_sway: f32,
|
||||||
|
pos: Vec3<i32>,
|
||||||
|
ori_bits: u8,
|
||||||
|
light: f32,
|
||||||
|
glow: f32,
|
||||||
|
) -> Self {
|
||||||
const EXTRA_NEG_Z: i32 = 32768;
|
const EXTRA_NEG_Z: i32 = 32768;
|
||||||
|
|
||||||
let mat_arr = mat.into_col_arrays();
|
let mat_arr = mat.into_col_arrays();
|
||||||
|
@ -107,23 +107,25 @@ impl Vertex {
|
|||||||
) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType
|
) -> <<ColLightFmt as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType
|
||||||
{
|
{
|
||||||
//[col.r, col.g, col.b, light]
|
//[col.r, col.g, col.b, light]
|
||||||
// It would be nice for this to be cleaner, but we want to squeeze 5 fields into 4.
|
// It would be nice for this to be cleaner, but we want to squeeze 5 fields into
|
||||||
// We can do this because both `light` and `glow` go from 0 to 31, meaning that they
|
// 4. We can do this because both `light` and `glow` go from 0 to 31,
|
||||||
// can both fit into 5 bits. If we steal a bit from red and blue each (not green,
|
// meaning that they can both fit into 5 bits. If we steal a bit from
|
||||||
// human eyes are more sensitive to changes in green) then we get just enough to
|
// red and blue each (not green, human eyes are more sensitive to
|
||||||
// expand the nibbles of the alpha field enough to fit both `light` and `glow`.
|
// changes in green) then we get just enough to expand the nibbles of
|
||||||
|
// the alpha field enough to fit both `light` and `glow`.
|
||||||
//
|
//
|
||||||
// However, we now have a problem. In the shader code with use hardware filtering to
|
// However, we now have a problem. In the shader code with use hardware
|
||||||
// get at the `light` and `glow` attributes (but not colour, that remains constant
|
// filtering to get at the `light` and `glow` attributes (but not
|
||||||
// across a block). How do we resolve this if we're twiddling bits? The answer is to
|
// colour, that remains constant across a block). How do we resolve this
|
||||||
// very carefully manipulate the bit pattern such that the fields we want to filter
|
// if we're twiddling bits? The answer is to very carefully manipulate
|
||||||
// (`light` and `glow`) always sit as the higher bits of the fields. Then, we can do
|
// the bit pattern such that the fields we want to filter (`light` and
|
||||||
|
// `glow`) always sit as the higher bits of the fields. Then, we can do
|
||||||
// some modulation magic to extract them from the filtering unharmed and use
|
// some modulation magic to extract them from the filtering unharmed and use
|
||||||
// unfiltered texture access (i.e: `texelFetch`) to access the colours, plus a little
|
// unfiltered texture access (i.e: `texelFetch`) to access the colours, plus a
|
||||||
// bit-fiddling.
|
// little bit-fiddling.
|
||||||
//
|
//
|
||||||
// TODO: This isn't currently working (no idea why). See `srgb.glsl` for current impl
|
// TODO: This isn't currently working (no idea why). See `srgb.glsl` for current
|
||||||
// that intead does manual bit-twiddling and filtering.
|
// impl that intead does manual bit-twiddling and filtering.
|
||||||
[
|
[
|
||||||
(light.min(31) << 3) | ((col.r & 0b1110) >> 1),
|
(light.min(31) << 3) | ((col.r & 0b1110) >> 1),
|
||||||
(glow.min(31) << 3) | ((col.r & 0b1110) >> 1),
|
(glow.min(31) << 3) | ((col.r & 0b1110) >> 1),
|
||||||
|
@ -33,7 +33,8 @@ use tracing::{error, warn};
|
|||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
/// Represents the format of the pre-processed color target.
|
/// Represents the format of the pre-processed color target.
|
||||||
// TODO: `(gfx::format::R11_G11_B10, gfx::format::Float)` would be better in theory, but it doesn't seem to work
|
// TODO: `(gfx::format::R11_G11_B10, gfx::format::Float)` would be better in
|
||||||
|
// theory, but it doesn't seem to work
|
||||||
pub type TgtColorFmt = gfx::format::Rgba16F;
|
pub type TgtColorFmt = gfx::format::Rgba16F;
|
||||||
/// Represents the format of the pre-processed depth and stencil target.
|
/// Represents the format of the pre-processed depth and stencil target.
|
||||||
pub type TgtDepthStencilFmt = gfx::format::Depth;
|
pub type TgtDepthStencilFmt = gfx::format::Depth;
|
||||||
@ -1001,10 +1002,10 @@ impl Renderer {
|
|||||||
size: [u16; 2],
|
size: [u16; 2],
|
||||||
data: &[<<T as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType],
|
data: &[<<T as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType],
|
||||||
) -> Result<(), RenderError>
|
) -> Result<(), RenderError>
|
||||||
where
|
where
|
||||||
<T as gfx::format::Formatted>::Surface: gfx::format::TextureSurface,
|
<T as gfx::format::Formatted>::Surface: gfx::format::TextureSurface,
|
||||||
<T as gfx::format::Formatted>::Channel: gfx::format::TextureChannel,
|
<T as gfx::format::Formatted>::Channel: gfx::format::TextureChannel,
|
||||||
<<T as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType: Copy,
|
<<T as gfx::format::Formatted>::Surface as gfx::format::SurfaceTyped>::DataType: Copy,
|
||||||
{
|
{
|
||||||
texture.update(&mut self.encoder, offset, size, data)
|
texture.update(&mut self.encoder, offset, size, data)
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,9 @@ use crate::{
|
|||||||
},
|
},
|
||||||
scene::{
|
scene::{
|
||||||
camera::{Camera, CameraMode, Dependents},
|
camera::{Camera, CameraMode, Dependents},
|
||||||
math, LodData, SceneData,
|
math,
|
||||||
terrain::Terrain,
|
terrain::Terrain,
|
||||||
|
LodData, SceneData,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use anim::{
|
use anim::{
|
||||||
@ -3486,7 +3487,8 @@ impl<S: Skeleton> FigureState<S> {
|
|||||||
})
|
})
|
||||||
.unwrap_or((1.0, 0.0));
|
.unwrap_or((1.0, 0.0));
|
||||||
// Fade between light and glow levels
|
// Fade between light and glow levels
|
||||||
// TODO: Making this temporal rather than spatial is a bit dumb but it's a very subtle difference
|
// TODO: Making this temporal rather than spatial is a bit dumb but it's a very
|
||||||
|
// subtle difference
|
||||||
self.last_light = vek::Lerp::lerp(self.last_light, light, 16.0 * dt);
|
self.last_light = vek::Lerp::lerp(self.last_light, light, 16.0 * dt);
|
||||||
self.last_glow = vek::Lerp::lerp(self.last_glow, glow, 16.0 * dt);
|
self.last_glow = vek::Lerp::lerp(self.last_glow, glow, 16.0 * dt);
|
||||||
|
|
||||||
|
@ -540,7 +540,8 @@ impl Scene {
|
|||||||
lights.clear();
|
lights.clear();
|
||||||
|
|
||||||
// Maintain the particles.
|
// Maintain the particles.
|
||||||
self.particle_mgr.maintain(renderer, &scene_data, &self.terrain, lights);
|
self.particle_mgr
|
||||||
|
.maintain(renderer, &scene_data, &self.terrain, lights);
|
||||||
|
|
||||||
// Update light constants
|
// Update light constants
|
||||||
lights.extend(
|
lights.extend(
|
||||||
|
@ -2,8 +2,8 @@ use super::{terrain::BlocksOfInterest, SceneData, Terrain};
|
|||||||
use crate::{
|
use crate::{
|
||||||
mesh::{greedy::GreedyMesh, Meshable},
|
mesh::{greedy::GreedyMesh, Meshable},
|
||||||
render::{
|
render::{
|
||||||
pipelines::particle::ParticleMode, GlobalModel, Instances, LodData, Model,
|
pipelines::particle::ParticleMode, GlobalModel, Instances, Light, LodData, Model,
|
||||||
ParticleInstance, ParticlePipeline, Renderer, Light,
|
ParticleInstance, ParticlePipeline, Renderer,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
@ -73,7 +73,8 @@ impl ParticleMgr {
|
|||||||
ParticleMode::EnergyNature,
|
ParticleMode::EnergyNature,
|
||||||
*pos + Vec3::<f32>::zero()
|
*pos + Vec3::<f32>::zero()
|
||||||
.map(|_| rng.gen_range(-1.0, 1.0))
|
.map(|_| rng.gen_range(-1.0, 1.0))
|
||||||
.normalized() * *radius,
|
.normalized()
|
||||||
|
* *radius,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -87,7 +88,8 @@ impl ParticleMgr {
|
|||||||
ParticleMode::CampfireFire,
|
ParticleMode::CampfireFire,
|
||||||
*pos + Vec3::<f32>::zero()
|
*pos + Vec3::<f32>::zero()
|
||||||
.map(|_| rng.gen_range(-1.0, 1.0))
|
.map(|_| rng.gen_range(-1.0, 1.0))
|
||||||
.normalized() * *radius,
|
.normalized()
|
||||||
|
* *radius,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -121,7 +123,8 @@ impl ParticleMgr {
|
|||||||
ParticleMode::CampfireSmoke,
|
ParticleMode::CampfireSmoke,
|
||||||
*pos + Vec3::<f32>::zero()
|
*pos + Vec3::<f32>::zero()
|
||||||
.map(|_| rng.gen_range(-1.0, 1.0))
|
.map(|_| rng.gen_range(-1.0, 1.0))
|
||||||
.normalized() * *radius,
|
.normalized()
|
||||||
|
* *radius,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -377,11 +380,7 @@ impl ParticleMgr {
|
|||||||
if b.stage_section == StageSection::Cast {
|
if b.stage_section == StageSection::Cast {
|
||||||
if b.static_data.base_hps > 0 {
|
if b.static_data.base_hps > 0 {
|
||||||
// Emit a light when using healing
|
// Emit a light when using healing
|
||||||
lights.push(Light::new(
|
lights.push(Light::new(pos.0 + b.offset, Rgb::new(0.1, 1.0, 0.15), 1.0));
|
||||||
pos.0 + b.offset,
|
|
||||||
Rgb::new(0.1, 1.0, 0.15),
|
|
||||||
1.0,
|
|
||||||
));
|
|
||||||
for i in 0..self.scheduler.heartbeats(Duration::from_millis(1)) {
|
for i in 0..self.scheduler.heartbeats(Duration::from_millis(1)) {
|
||||||
self.particles.push(Particle::new_beam(
|
self.particles.push(Particle::new_beam(
|
||||||
b.static_data.beam_duration,
|
b.static_data.beam_duration,
|
||||||
|
@ -144,7 +144,11 @@ fn mesh_worker<V: BaseVol<Vox = Block> + RectRasterableVol + ReadVol + Debug + '
|
|||||||
span!(_guard, "mesh_worker");
|
span!(_guard, "mesh_worker");
|
||||||
let blocks_of_interest = BlocksOfInterest::from_chunk(&chunk);
|
let blocks_of_interest = BlocksOfInterest::from_chunk(&chunk);
|
||||||
let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info, light_map, glow_map)) =
|
let (opaque_mesh, fluid_mesh, _shadow_mesh, (bounds, col_lights_info, light_map, glow_map)) =
|
||||||
volume.generate_mesh((range, Vec2::new(max_texture_size, max_texture_size), &blocks_of_interest));
|
volume.generate_mesh((
|
||||||
|
range,
|
||||||
|
Vec2::new(max_texture_size, max_texture_size),
|
||||||
|
&blocks_of_interest,
|
||||||
|
));
|
||||||
MeshWorkerResponse {
|
MeshWorkerResponse {
|
||||||
pos,
|
pos,
|
||||||
z_bounds: (bounds.min.z, bounds.max.z),
|
z_bounds: (bounds.min.z, bounds.max.z),
|
||||||
@ -472,14 +476,24 @@ impl<V: RectRasterableVol> Terrain<V> {
|
|||||||
|
|
||||||
/// Find the light level (sunlight) at the given world position.
|
/// Find the light level (sunlight) at the given world position.
|
||||||
pub fn light_at_wpos(&self, wpos: Vec3<i32>) -> f32 {
|
pub fn light_at_wpos(&self, wpos: Vec3<i32>) -> f32 {
|
||||||
let chunk_pos = Vec2::from(wpos).map2(TerrainChunk::RECT_SIZE, |e: i32, sz| e.div_euclid(sz as i32));
|
let chunk_pos = Vec2::from(wpos).map2(TerrainChunk::RECT_SIZE, |e: i32, sz| {
|
||||||
self.chunks.get(&chunk_pos).map(|c| (c.light_map)(wpos)).unwrap_or(1.0)
|
e.div_euclid(sz as i32)
|
||||||
|
});
|
||||||
|
self.chunks
|
||||||
|
.get(&chunk_pos)
|
||||||
|
.map(|c| (c.light_map)(wpos))
|
||||||
|
.unwrap_or(1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the glow level (light from lamps) at the given world position.
|
/// Find the glow level (light from lamps) at the given world position.
|
||||||
pub fn glow_at_wpos(&self, wpos: Vec3<i32>) -> f32 {
|
pub fn glow_at_wpos(&self, wpos: Vec3<i32>) -> f32 {
|
||||||
let chunk_pos = Vec2::from(wpos).map2(TerrainChunk::RECT_SIZE, |e: i32, sz| e.div_euclid(sz as i32));
|
let chunk_pos = Vec2::from(wpos).map2(TerrainChunk::RECT_SIZE, |e: i32, sz| {
|
||||||
self.chunks.get(&chunk_pos).map(|c| (c.glow_map)(wpos)).unwrap_or(0.0)
|
e.div_euclid(sz as i32)
|
||||||
|
});
|
||||||
|
self.chunks
|
||||||
|
.get(&chunk_pos)
|
||||||
|
.map(|c| (c.glow_map)(wpos))
|
||||||
|
.unwrap_or(0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maintain terrain data. To be called once per tick.
|
/// Maintain terrain data. To be called once per tick.
|
||||||
|
@ -6,6 +6,7 @@ use common::{
|
|||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct BlocksOfInterest {
|
pub struct BlocksOfInterest {
|
||||||
pub leaves: Vec<Vec3<i32>>,
|
pub leaves: Vec<Vec3<i32>>,
|
||||||
pub grass: Vec<Vec3<i32>>,
|
pub grass: Vec<Vec3<i32>>,
|
||||||
@ -22,8 +23,6 @@ pub struct BlocksOfInterest {
|
|||||||
pub lights: Vec<(Vec3<i32>, u8)>,
|
pub lights: Vec<(Vec3<i32>, u8)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
use inline_tweak::*;
|
|
||||||
|
|
||||||
impl BlocksOfInterest {
|
impl BlocksOfInterest {
|
||||||
pub fn from_chunk(chunk: &TerrainChunk) -> Self {
|
pub fn from_chunk(chunk: &TerrainChunk) -> Self {
|
||||||
span!(_guard, "from_chunk", "BlocksOfInterest::from_chunk");
|
span!(_guard, "from_chunk", "BlocksOfInterest::from_chunk");
|
||||||
@ -73,8 +72,10 @@ impl BlocksOfInterest {
|
|||||||
// Offset positions to account for block height.
|
// Offset positions to account for block height.
|
||||||
// TODO: Is this a good idea?
|
// TODO: Is this a good idea?
|
||||||
Some(SpriteKind::StreetLamp) => fire_bowls.push(pos + Vec3::unit_z() * 2),
|
Some(SpriteKind::StreetLamp) => fire_bowls.push(pos + Vec3::unit_z() * 2),
|
||||||
Some(SpriteKind::FireBowlGround) => fire_bowls.push(pos + Vec3::unit_z() * 1),
|
Some(SpriteKind::FireBowlGround) => fire_bowls.push(pos + Vec3::unit_z()),
|
||||||
Some(SpriteKind::StreetLampTall) => fire_bowls.push(pos + Vec3::unit_z() * 4),
|
Some(SpriteKind::StreetLampTall) => {
|
||||||
|
fire_bowls.push(pos + Vec3::unit_z() * 4)
|
||||||
|
},
|
||||||
Some(SpriteKind::Beehive) => beehives.push(pos),
|
Some(SpriteKind::Beehive) => beehives.push(pos),
|
||||||
Some(SpriteKind::Reed) => reeds.push(pos),
|
Some(SpriteKind::Reed) => reeds.push(pos),
|
||||||
Some(SpriteKind::PinkFlower) => flowers.push(pos),
|
Some(SpriteKind::PinkFlower) => flowers.push(pos),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{column::ColumnSample, sim::SimChunk, util::RandomField, Canvas, CONFIG};
|
use crate::{column::ColumnSample, sim::SimChunk, Canvas, CONFIG};
|
||||||
use common::terrain::SpriteKind;
|
use common::terrain::SpriteKind;
|
||||||
use noise::NoiseFn;
|
use noise::NoiseFn;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
@ -31,6 +31,7 @@ static MODEL_RAND: RandomPerm = RandomPerm::new(0xDB21C052);
|
|||||||
static UNIT_CHOOSER: UnitChooser = UnitChooser::new(0x700F4EC7);
|
static UNIT_CHOOSER: UnitChooser = UnitChooser::new(0x700F4EC7);
|
||||||
static QUIRKY_RAND: RandomPerm = RandomPerm::new(0xA634460F);
|
static QUIRKY_RAND: RandomPerm = RandomPerm::new(0xA634460F);
|
||||||
|
|
||||||
|
#[allow(clippy::if_same_then_else)]
|
||||||
pub fn apply_trees_to(canvas: &mut Canvas) {
|
pub fn apply_trees_to(canvas: &mut Canvas) {
|
||||||
struct Tree {
|
struct Tree {
|
||||||
pos: Vec3<i32>,
|
pos: Vec3<i32>,
|
||||||
@ -51,15 +52,17 @@ pub fn apply_trees_to(canvas: &mut Canvas) {
|
|||||||
|
|
||||||
let is_quirky = QUIRKY_RAND.chance(seed, 1.0 / 500.0);
|
let is_quirky = QUIRKY_RAND.chance(seed, 1.0 / 500.0);
|
||||||
|
|
||||||
// Ensure that it's valid to place a tree here
|
// Ensure that it's valid to place a *thing* here
|
||||||
if col.alt < col.water_level
|
if col.alt < col.water_level
|
||||||
|| col.spawn_rate < 0.9
|
|| col.spawn_rate < 0.9
|
||||||
|| col.water_dist.map(|d| d < 8.0).unwrap_or(false)
|
|| col.water_dist.map(|d| d < 8.0).unwrap_or(false)
|
||||||
|| col.path.map(|(d, _, _, _)| d < 12.0).unwrap_or(false)
|
|| col.path.map(|(d, _, _, _)| d < 12.0).unwrap_or(false)
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
} else if !is_quirky
|
}
|
||||||
&& ((seed.wrapping_mul(13)) & 0xFF) as f32 / 256.0 > col.tree_density
|
|
||||||
|
// Ensure that it's valid to place a tree here
|
||||||
|
if !is_quirky && ((seed.wrapping_mul(13)) & 0xFF) as f32 / 256.0 > col.tree_density
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -182,10 +182,20 @@ impl World {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let meta = TerrainChunkMeta::new(
|
let meta = TerrainChunkMeta::new(
|
||||||
sim_chunk.sites
|
sim_chunk
|
||||||
|
.sites
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|id| index.sites[**id].get_origin().distance_squared(chunk_center_wpos2d) as f32 <= index.sites[**id].radius().powf(2.0))
|
.filter(|id| {
|
||||||
.min_by_key(|id| index.sites[**id].get_origin().distance_squared(chunk_center_wpos2d))
|
index.sites[**id]
|
||||||
|
.get_origin()
|
||||||
|
.distance_squared(chunk_center_wpos2d) as f32
|
||||||
|
<= index.sites[**id].radius().powf(2.0)
|
||||||
|
})
|
||||||
|
.min_by_key(|id| {
|
||||||
|
index.sites[**id]
|
||||||
|
.get_origin()
|
||||||
|
.distance_squared(chunk_center_wpos2d)
|
||||||
|
})
|
||||||
.map(|id| index.sites[*id].name().to_string()),
|
.map(|id| index.sites[*id].name().to_string()),
|
||||||
sim_chunk.get_biome(),
|
sim_chunk.get_biome(),
|
||||||
sim_chunk.alt,
|
sim_chunk.alt,
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
use crate::sim::WorldSim;
|
use crate::sim::WorldSim;
|
||||||
use common::{
|
use common::path::Path;
|
||||||
astar::Astar,
|
//use hashbrown::hash_map::DefaultHashBuilder;
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
use hashbrown::hash_map::DefaultHashBuilder;
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct SearchCfg {
|
pub struct SearchCfg {
|
||||||
// 0.0 = no discount, 1.0 = free travel
|
// 0.0 = no discount, 1.0 = free travel
|
||||||
path_discount: f32,
|
path_discount: f32,
|
||||||
@ -14,15 +12,19 @@ pub struct SearchCfg {
|
|||||||
gradient_aversion: f32,
|
gradient_aversion: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub struct Searcher<'a> {
|
pub struct Searcher<'a> {
|
||||||
land: &'a WorldSim,
|
land: &'a WorldSim,
|
||||||
pub cfg: SearchCfg,
|
pub cfg: SearchCfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
impl<'a> Searcher<'a> {
|
impl<'a> Searcher<'a> {
|
||||||
/// Attempt to find a path between two chunks on the map.
|
/// Attempt to find a path between two chunks on the map.
|
||||||
pub fn search(self, a: Vec2<i32>, b: Vec2<i32>) -> Option<Path<i32>> {
|
pub fn search(self, _a: Vec2<i32>, _b: Vec2<i32>) -> Option<Path<i32>> {
|
||||||
let heuristic = |pos: &Vec2<i32>| (pos - b).map(|e| e as f32).magnitude();
|
// TODO: implement this function
|
||||||
|
|
||||||
|
//let heuristic = |pos: &Vec2<i32>| (pos - b).map(|e| e as f32).magnitude();
|
||||||
// Astar::new(
|
// Astar::new(
|
||||||
// 100_000,
|
// 100_000,
|
||||||
// a,
|
// a,
|
||||||
|
@ -103,7 +103,7 @@ pub fn sample_pos(
|
|||||||
spline_derivative,
|
spline_derivative,
|
||||||
is_path,
|
is_path,
|
||||||
is_cave,
|
is_cave,
|
||||||
near_site,
|
_near_site,
|
||||||
) = sampler
|
) = sampler
|
||||||
.get(pos)
|
.get(pos)
|
||||||
.map(|sample| {
|
.map(|sample| {
|
||||||
|
@ -3,11 +3,11 @@ use crate::{
|
|||||||
column::ColumnSample,
|
column::ColumnSample,
|
||||||
sim::WorldSim,
|
sim::WorldSim,
|
||||||
site::{
|
site::{
|
||||||
|
namegen::NameGen,
|
||||||
settlement::building::{
|
settlement::building::{
|
||||||
archetype::keep::{Attr, FlagColor, Keep as KeepArchetype, StoneColor},
|
archetype::keep::{Attr, FlagColor, Keep as KeepArchetype, StoneColor},
|
||||||
Archetype, Ori,
|
Archetype, Ori,
|
||||||
},
|
},
|
||||||
namegen::NameGen,
|
|
||||||
},
|
},
|
||||||
IndexRef,
|
IndexRef,
|
||||||
};
|
};
|
||||||
@ -156,9 +156,7 @@ impl Castle {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str { &self.name }
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn contains_point(&self, wpos: Vec2<i32>) -> bool {
|
pub fn contains_point(&self, wpos: Vec2<i32>) -> bool {
|
||||||
let lpos = wpos - self.origin;
|
let lpos = wpos - self.origin;
|
||||||
|
@ -48,8 +48,6 @@ pub struct Colors {
|
|||||||
|
|
||||||
const ALT_OFFSET: i32 = -2;
|
const ALT_OFFSET: i32 = -2;
|
||||||
|
|
||||||
const LEVELS: usize = 5;
|
|
||||||
|
|
||||||
impl Dungeon {
|
impl Dungeon {
|
||||||
#[allow(clippy::let_and_return)] // TODO: Pending review in #587
|
#[allow(clippy::let_and_return)] // TODO: Pending review in #587
|
||||||
pub fn generate(wpos: Vec2<i32>, sim: Option<&WorldSim>, rng: &mut impl Rng) -> Self {
|
pub fn generate(wpos: Vec2<i32>, sim: Option<&WorldSim>, rng: &mut impl Rng) -> Self {
|
||||||
@ -321,7 +319,10 @@ impl Floor {
|
|||||||
enemy_density: Some((0.0002 * difficulty as f32).min(0.001)), // Minions!
|
enemy_density: Some((0.0002 * difficulty as f32).min(0.001)), // Minions!
|
||||||
miniboss: false,
|
miniboss: false,
|
||||||
boss: true,
|
boss: true,
|
||||||
area: Rect::from((new_stair_tile - tile_offset - 4, Extent2::broadcast(width as i32 * 2 + 1))),
|
area: Rect::from((
|
||||||
|
new_stair_tile - tile_offset - 4,
|
||||||
|
Extent2::broadcast(width as i32 * 2 + 1),
|
||||||
|
)),
|
||||||
height: height as i32,
|
height: height as i32,
|
||||||
pillars: Some(2),
|
pillars: Some(2),
|
||||||
difficulty,
|
difficulty,
|
||||||
@ -482,6 +483,8 @@ impl Floor {
|
|||||||
origin: Vec3<i32>,
|
origin: Vec3<i32>,
|
||||||
supplement: &mut ChunkSupplement,
|
supplement: &mut ChunkSupplement,
|
||||||
) {
|
) {
|
||||||
|
/*
|
||||||
|
// Add stair waypoint
|
||||||
let stair_rcenter =
|
let stair_rcenter =
|
||||||
Vec3::from((self.stair_tile + self.tile_offset).map(|e| e * TILE_SIZE + TILE_SIZE / 2));
|
Vec3::from((self.stair_tile + self.tile_offset).map(|e| e * TILE_SIZE + TILE_SIZE / 2));
|
||||||
|
|
||||||
@ -493,13 +496,14 @@ impl Floor {
|
|||||||
.try_normalized()
|
.try_normalized()
|
||||||
.unwrap_or_else(Vec2::unit_y)
|
.unwrap_or_else(Vec2::unit_y)
|
||||||
* (TILE_SIZE as f32 / 2.0 - 4.0);
|
* (TILE_SIZE as f32 / 2.0 - 4.0);
|
||||||
// if !self.final_level {
|
if !self.final_level {
|
||||||
// supplement.add_entity(
|
supplement.add_entity(
|
||||||
// EntityInfo::at((origin + stair_rcenter).map(|e| e as f32)
|
EntityInfo::at((origin + stair_rcenter).map(|e| e as f32)
|
||||||
// + Vec3::from(offs)) .into_waypoint(),
|
+ Vec3::from(offs)) .into_waypoint(),
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
for x in area.min.x..area.max.x {
|
for x in area.min.x..area.max.x {
|
||||||
for y in area.min.y..area.max.y {
|
for y in area.min.y..area.max.y {
|
||||||
@ -601,11 +605,11 @@ impl Floor {
|
|||||||
(room.difficulty as f32).powf(1.5) + 4.0,
|
(room.difficulty as f32).powf(1.5) + 4.0,
|
||||||
).round() as u32);
|
).round() as u32);
|
||||||
let entity = match room.difficulty {
|
let entity = match room.difficulty {
|
||||||
0 => entity.with_name("Outcast")
|
0 => entity
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Outcast)
|
.with_name("Outcast")
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_config(common::loadout_builder::LoadoutConfig::Outcast)
|
||||||
.with_main_tool(
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
comp::Item::new_from_asset_expect(
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
0 => "common.items.weapons.axe.starter_axe",
|
0 => "common.items.weapons.axe.starter_axe",
|
||||||
1 => "common.items.weapons.sword.starter_sword",
|
1 => "common.items.weapons.sword.starter_sword",
|
||||||
@ -614,13 +618,12 @@ impl Floor {
|
|||||||
4 => "common.items.weapons.staff.starter_staff",
|
4 => "common.items.weapons.staff.starter_staff",
|
||||||
_ => "common.items.weapons.bow.starter_bow",
|
_ => "common.items.weapons.bow.starter_bow",
|
||||||
},
|
},
|
||||||
),
|
)),
|
||||||
),
|
1 => entity
|
||||||
1 => entity.with_name("Highwayman")
|
.with_name("Highwayman")
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Highwayman)
|
.with_config(common::loadout_builder::LoadoutConfig::Highwayman)
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
.with_main_tool(
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
comp::Item::new_from_asset_expect(
|
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
0 => "common.items.weapons.axe.worn_iron_axe-0",
|
0 => "common.items.weapons.axe.worn_iron_axe-0",
|
||||||
1 => "common.items.weapons.sword.zweihander_sword_0",
|
1 => "common.items.weapons.sword.zweihander_sword_0",
|
||||||
@ -629,13 +632,12 @@ impl Floor {
|
|||||||
4 => "common.items.weapons.staff.bone_staff",
|
4 => "common.items.weapons.staff.bone_staff",
|
||||||
_ => "common.items.weapons.bow.wood_shortbow-1",
|
_ => "common.items.weapons.bow.wood_shortbow-1",
|
||||||
},
|
},
|
||||||
),
|
)),
|
||||||
),
|
2 => entity
|
||||||
2 => entity.with_name("Bandit")
|
.with_name("Bandit")
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Bandit)
|
.with_config(common::loadout_builder::LoadoutConfig::Bandit)
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
.with_main_tool(
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
comp::Item::new_from_asset_expect(
|
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
0 => "common.items.weapons.axe.bronze_axe-0",
|
0 => "common.items.weapons.axe.bronze_axe-0",
|
||||||
1 => "common.items.weapons.sword.greatsword_2h_simple-0",
|
1 => "common.items.weapons.sword.greatsword_2h_simple-0",
|
||||||
@ -644,13 +646,12 @@ impl Floor {
|
|||||||
4 => "common.items.weapons.staff.bone_staff",
|
4 => "common.items.weapons.staff.bone_staff",
|
||||||
_ => "common.items.weapons.bow.wood_longbow-0",
|
_ => "common.items.weapons.bow.wood_longbow-0",
|
||||||
},
|
},
|
||||||
),
|
)),
|
||||||
),
|
3 => entity
|
||||||
3 => entity.with_name("Cultist Novice")
|
.with_name("Cultist Novice")
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::CultistNovice)
|
.with_config(common::loadout_builder::LoadoutConfig::CultistNovice)
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
.with_main_tool(
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
comp::Item::new_from_asset_expect(
|
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
0 => "common.items.weapons.axe.steel_axe-0",
|
0 => "common.items.weapons.axe.steel_axe-0",
|
||||||
1 => "common.items.weapons.sword.long_2h_orn-0",
|
1 => "common.items.weapons.sword.long_2h_orn-0",
|
||||||
@ -659,13 +660,12 @@ impl Floor {
|
|||||||
4 => "common.items.weapons.staff.amethyst_staff",
|
4 => "common.items.weapons.staff.amethyst_staff",
|
||||||
_ => "common.items.weapons.bow.horn_longbow-0",
|
_ => "common.items.weapons.bow.horn_longbow-0",
|
||||||
},
|
},
|
||||||
),
|
)),
|
||||||
),
|
4 => entity
|
||||||
4 => entity.with_name("Cultist Acolyte")
|
.with_name("Cultist Acolyte")
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::CultistAcolyte)
|
.with_config(common::loadout_builder::LoadoutConfig::CultistAcolyte)
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
.with_main_tool(
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
comp::Item::new_from_asset_expect(
|
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
0 => "common.items.weapons.axe.malachite_axe-0",
|
0 => "common.items.weapons.axe.malachite_axe-0",
|
||||||
1 => "common.items.weapons.sword.cultist_purp_2h-0",
|
1 => "common.items.weapons.sword.cultist_purp_2h-0",
|
||||||
@ -674,20 +674,20 @@ impl Floor {
|
|||||||
4 => "common.items.weapons.staff.cultist_staff",
|
4 => "common.items.weapons.staff.cultist_staff",
|
||||||
_ => "common.items.weapons.bow.horn_longbow-0",
|
_ => "common.items.weapons.bow.horn_longbow-0",
|
||||||
},
|
},
|
||||||
),
|
)),
|
||||||
),
|
|
||||||
5 => match dynamic_rng.gen_range(0, 6) {
|
5 => match dynamic_rng.gen_range(0, 6) {
|
||||||
0 => entity.with_name("Cultist Warlock")
|
0 => entity
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Warlock)
|
.with_name("Cultist Warlock")
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_config(common::loadout_builder::LoadoutConfig::Warlock)
|
||||||
.with_main_tool(
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
comp::Item::new_from_asset_expect("common.items.npc_weapons.staff.cultist_staff"),
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
),
|
"common.items.npc_weapons.staff.cultist_staff",
|
||||||
_ => entity.with_name("Cultist Warlord")
|
)),
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Warlord)
|
_ => entity
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_name("Cultist Warlord")
|
||||||
.with_main_tool(
|
.with_config(common::loadout_builder::LoadoutConfig::Warlord)
|
||||||
comp::Item::new_from_asset_expect(
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
match dynamic_rng.gen_range(0, 5) {
|
match dynamic_rng.gen_range(0, 5) {
|
||||||
0 => "common.items.weapons.axe.malachite_axe-0",
|
0 => "common.items.weapons.axe.malachite_axe-0",
|
||||||
1 => "common.items.weapons.sword.cultist_purp_2h-0",
|
1 => "common.items.weapons.sword.cultist_purp_2h-0",
|
||||||
@ -695,8 +695,7 @@ impl Floor {
|
|||||||
3 => "common.items.weapons.hammer.cultist_purp_2h-0",
|
3 => "common.items.weapons.hammer.cultist_purp_2h-0",
|
||||||
_ => "common.items.weapons.bow.horn_longbow-0",
|
_ => "common.items.weapons.bow.horn_longbow-0",
|
||||||
},
|
},
|
||||||
),
|
)),
|
||||||
),
|
|
||||||
},
|
},
|
||||||
_ => entity.with_name("Humanoid").with_main_tool(
|
_ => entity.with_name("Humanoid").with_main_tool(
|
||||||
comp::Item::new_from_asset_expect(
|
comp::Item::new_from_asset_expect(
|
||||||
@ -723,77 +722,101 @@ impl Floor {
|
|||||||
|
|
||||||
if tile_pos == boss_spawn_tile && tile_wcenter.xy() == wpos2d {
|
if tile_pos == boss_spawn_tile && tile_wcenter.xy() == wpos2d {
|
||||||
let chosen = match room.difficulty {
|
let chosen = match room.difficulty {
|
||||||
0 => Lottery::<String>::load_expect("common.loot_tables.loot_table_weapon_uncommon"),
|
0 => Lottery::<String>::load_expect(
|
||||||
1 => Lottery::<String>::load_expect("common.loot_tables.loot_table_weapon_uncommon"),
|
"common.loot_tables.loot_table_weapon_uncommon",
|
||||||
2 => Lottery::<String>::load_expect("common.loot_tables.loot_table_armor_heavy"),
|
),
|
||||||
3 => Lottery::<String>::load_expect("common.loot_tables.loot_table_weapon_rare"),
|
1 => Lottery::<String>::load_expect(
|
||||||
4 => Lottery::<String>::load_expect("common.loot_tables.loot_table_boss_cultist-leader"),
|
"common.loot_tables.loot_table_weapon_uncommon",
|
||||||
5 => Lottery::<String>::load_expect("common.loot_tables.loot_table_boss_cultist-leader"),
|
),
|
||||||
|
2 => Lottery::<String>::load_expect(
|
||||||
|
"common.loot_tables.loot_table_armor_heavy",
|
||||||
|
),
|
||||||
|
3 => Lottery::<String>::load_expect(
|
||||||
|
"common.loot_tables.loot_table_weapon_rare",
|
||||||
|
),
|
||||||
|
4 => Lottery::<String>::load_expect(
|
||||||
|
"common.loot_tables.loot_table_boss_cultist-leader",
|
||||||
|
),
|
||||||
|
5 => Lottery::<String>::load_expect(
|
||||||
|
"common.loot_tables.loot_table_boss_cultist-leader",
|
||||||
|
),
|
||||||
_ => Lottery::<String>::load_expect(
|
_ => Lottery::<String>::load_expect(
|
||||||
"common.loot_tables.loot_table_armor_misc",
|
"common.loot_tables.loot_table_armor_misc",
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let chosen = chosen.choose();
|
let chosen = chosen.choose();
|
||||||
let entity =
|
let entity = match room.difficulty {
|
||||||
match room.difficulty {
|
0 => vec![
|
||||||
0 =>
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
.with_body(comp::Body::Humanoid(
|
||||||
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
|
comp::humanoid::Body::random(),
|
||||||
.with_name("Outcast Leader".to_string())
|
))
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_name("Outcast Leader".to_string())
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Outcast)
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
.with_scale(2.0)
|
.with_config(
|
||||||
.with_main_tool(
|
common::loadout_builder::LoadoutConfig::Outcast,
|
||||||
comp::Item::new_from_asset_expect(
|
)
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
.with_scale(2.0)
|
||||||
0 => "common.items.weapons.axe.worn_iron_axe-0",
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
1 => "common.items.weapons.sword.zweihander_sword_0",
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
2 => "common.items.weapons.sword.zweihander_sword_0",
|
0 => "common.items.weapons.axe.worn_iron_axe-0",
|
||||||
3 => "common.items.weapons.hammer.worn_iron_hammer-0",
|
1 => {
|
||||||
4 => "common.items.weapons.staff.bone_staff",
|
"common.items.weapons.sword.zweihander_sword_0"
|
||||||
_ => "common.items.weapons.bow.wood_shortbow-1",
|
},
|
||||||
},
|
2 => {
|
||||||
),
|
"common.items.weapons.sword.zweihander_sword_0"
|
||||||
),
|
},
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
3 => {
|
||||||
.with_body(comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random_with(
|
"common.items.weapons.hammer.worn_iron_hammer-0"
|
||||||
dynamic_rng,
|
},
|
||||||
&comp::quadruped_medium::Species::Tarasque,
|
4 => "common.items.weapons.staff.bone_staff",
|
||||||
)))
|
_ => "common.items.weapons.bow.wood_shortbow-1",
|
||||||
.with_name("Tarasque".to_string())
|
},
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
)),
|
||||||
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
.with_body(comp::Body::QuadrupedMedium(
|
||||||
|
comp::quadruped_medium::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::quadruped_medium::Species::Tarasque,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.with_name("Tarasque".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
],
|
],
|
||||||
1 =>
|
1 => vec![
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
.with_body(comp::Body::Theropod(comp::theropod::Body::random_with(
|
.with_body(comp::Body::Theropod(
|
||||||
dynamic_rng,
|
comp::theropod::Body::random_with(
|
||||||
&comp::theropod::Species::Odonto,
|
dynamic_rng,
|
||||||
)))
|
&comp::theropod::Species::Odonto,
|
||||||
.with_name("Odonto".to_string())
|
),
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
))
|
||||||
|
.with_name("Odonto".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
],
|
],
|
||||||
2 =>
|
2 => vec![
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
|
.with_body(comp::Body::Humanoid(
|
||||||
.with_name("Bandit Captain".to_string())
|
comp::humanoid::Body::random()
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
))
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Bandit)
|
.with_name("Bandit Captain".to_string())
|
||||||
.with_scale(2.0)
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
.with_main_tool(
|
.with_config(common::loadout_builder::LoadoutConfig::Bandit)
|
||||||
comp::Item::new_from_asset_expect(
|
.with_scale(2.0)
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
0 => "common.items.weapons.axe.steel_axe-0",
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
1 => "common.items.weapons.sword.long_2h_orn-0",
|
0 => "common.items.weapons.axe.steel_axe-0",
|
||||||
2 => "common.items.weapons.sword.long_2h_orn-0",
|
1 => "common.items.weapons.sword.long_2h_orn-0",
|
||||||
3 => "common.items.weapons.hammer.cobalt_hammer-0",
|
2 => "common.items.weapons.sword.long_2h_orn-0",
|
||||||
4 => "common.items.weapons.staff.amethyst_staff",
|
3 => "common.items.weapons.hammer.cobalt_hammer-0",
|
||||||
_ => "common.items.weapons.bow.horn_longbow-0",
|
4 => "common.items.weapons.staff.amethyst_staff",
|
||||||
},
|
_ => "common.items.weapons.bow.horn_longbow-0",
|
||||||
),
|
},
|
||||||
)
|
),);
|
||||||
; 2],
|
2
|
||||||
3 =>
|
],
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
3 => {
|
||||||
|
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
|
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
|
||||||
.with_name("Cultist Acolyte".to_string())
|
.with_name("Cultist Acolyte".to_string())
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
@ -811,46 +834,57 @@ impl Floor {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
; 2],
|
; 2]
|
||||||
4 =>
|
},
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
4 => vec![
|
||||||
.with_body(comp::Body::Golem(comp::golem::Body::random_with(
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
dynamic_rng,
|
.with_body(comp::Body::Golem(
|
||||||
&comp::golem::Species::StoneGolem,
|
comp::golem::Body::random_with(
|
||||||
)))
|
dynamic_rng,
|
||||||
.with_name("Stonework Defender".to_string())
|
&comp::golem::Species::StoneGolem,
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
),
|
||||||
|
))
|
||||||
|
.with_name("Stonework Defender".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
],
|
],
|
||||||
5 =>
|
5 => vec![
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
.with_body(comp::Body::BipedLarge(comp::biped_large::Body::random_with(
|
.with_body(comp::Body::BipedLarge(
|
||||||
dynamic_rng,
|
comp::biped_large::Body::random_with(
|
||||||
&comp::biped_large::Species::Mindflayer,
|
dynamic_rng,
|
||||||
)))
|
&comp::biped_large::Species::Mindflayer,
|
||||||
.with_name("Mindflayer".to_string())
|
),
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
))
|
||||||
],
|
.with_name("Mindflayer".to_string())
|
||||||
_ =>
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
|
||||||
.with_body(comp::Body::QuadrupedSmall(comp::quadruped_small::Body::random_with(
|
|
||||||
dynamic_rng,
|
|
||||||
&comp::quadruped_small::Species::Sheep,
|
|
||||||
))),
|
|
||||||
],
|
],
|
||||||
|
_ => {
|
||||||
|
vec![EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_body(
|
||||||
|
comp::Body::QuadrupedSmall(
|
||||||
|
comp::quadruped_small::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::quadruped_small::Species::Sheep,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)]
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
for entity in entity {
|
for entity in entity {
|
||||||
supplement.add_entity(entity.with_level(
|
supplement.add_entity(
|
||||||
dynamic_rng
|
entity
|
||||||
.gen_range(
|
.with_level(
|
||||||
(room.difficulty as f32).powf(1.25) + 3.0,
|
dynamic_rng
|
||||||
(room.difficulty as f32).powf(1.5) + 4.0,
|
.gen_range(
|
||||||
)
|
(room.difficulty as f32).powf(1.25) + 3.0,
|
||||||
.round() as u32
|
(room.difficulty as f32).powf(1.5) + 4.0,
|
||||||
* 5,
|
)
|
||||||
)
|
.round()
|
||||||
.with_alignment(comp::Alignment::Enemy),
|
as u32
|
||||||
);
|
* 5,
|
||||||
|
)
|
||||||
|
.with_alignment(comp::Alignment::Enemy),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -868,123 +902,161 @@ impl Floor {
|
|||||||
let miniboss_spawn_tile =
|
let miniboss_spawn_tile =
|
||||||
miniboss_spawn_tile + if miniboss_tile_is_pillar { 1 } else { 0 };
|
miniboss_spawn_tile + if miniboss_tile_is_pillar { 1 } else { 0 };
|
||||||
|
|
||||||
if tile_pos == miniboss_spawn_tile && tile_wcenter.xy() == wpos2d {
|
if tile_pos == miniboss_spawn_tile && tile_wcenter.xy() == wpos2d {
|
||||||
let chosen = match room.difficulty {
|
let chosen = match room.difficulty {
|
||||||
0 => Lottery::<String>::load_expect("common.loot_tables.loot_table_animal_parts"),
|
0 => Lottery::<String>::load_expect(
|
||||||
1 => Lottery::<String>::load_expect("common.loot_tables.loot_table_animal_parts"),
|
"common.loot_tables.loot_table_animal_parts",
|
||||||
2 => Lottery::<String>::load_expect("common.loot_tables.loot_table_animal_parts"),
|
),
|
||||||
3 => Lottery::<String>::load_expect("common.loot_tables.loot_table_weapon_rare"),
|
1 => Lottery::<String>::load_expect(
|
||||||
4 => Lottery::<String>::load_expect("common.loot_tables.loot_table_weapon_rare"),
|
"common.loot_tables.loot_table_animal_parts",
|
||||||
5 => Lottery::<String>::load_expect("common.loot_tables.loot_table_boss_cultist-leader"),
|
),
|
||||||
_ => Lottery::<String>::load_expect(
|
2 => Lottery::<String>::load_expect(
|
||||||
"common.loot_tables.loot_table_armor_misc",
|
"common.loot_tables.loot_table_animal_parts",
|
||||||
),
|
),
|
||||||
};
|
3 => Lottery::<String>::load_expect(
|
||||||
let chosen = chosen.choose();
|
"common.loot_tables.loot_table_weapon_rare",
|
||||||
let entity =
|
),
|
||||||
match room.difficulty {
|
4 => Lottery::<String>::load_expect(
|
||||||
0 =>
|
"common.loot_tables.loot_table_weapon_rare",
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
),
|
||||||
.with_body(comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random_with(
|
5 => Lottery::<String>::load_expect(
|
||||||
dynamic_rng,
|
"common.loot_tables.loot_table_boss_cultist-leader",
|
||||||
&comp::quadruped_medium::Species::Bonerattler,
|
),
|
||||||
)))
|
_ => Lottery::<String>::load_expect(
|
||||||
.with_name("Bonerattler".to_string())
|
"common.loot_tables.loot_table_armor_misc",
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
),
|
||||||
],
|
};
|
||||||
1 =>
|
let chosen = chosen.choose();
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
let entity = match room.difficulty {
|
||||||
.with_body(comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random_with(
|
0 => vec![
|
||||||
dynamic_rng,
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
&comp::quadruped_medium::Species::Bonerattler,
|
.with_body(comp::Body::QuadrupedMedium(
|
||||||
)))
|
comp::quadruped_medium::Body::random_with(
|
||||||
.with_name("Bonerattler".to_string())
|
dynamic_rng,
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
&comp::quadruped_medium::Species::Bonerattler,
|
||||||
; 3],
|
),
|
||||||
2 =>
|
))
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
.with_name("Bonerattler".to_string())
|
||||||
.with_body(comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random_with(
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
dynamic_rng,
|
],
|
||||||
&comp::quadruped_medium::Species::Tarasque,
|
1 => vec![
|
||||||
)))
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
.with_name("Tarasque".to_string())
|
.with_body(comp::Body::QuadrupedMedium(
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
comp::quadruped_medium::Body::random_with(
|
||||||
],
|
dynamic_rng,
|
||||||
3 =>
|
&comp::quadruped_medium::Species::Bonerattler,
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
)
|
||||||
.with_body(comp::Body::Humanoid(comp::humanoid::Body::random()))
|
))
|
||||||
.with_name("Animal Trainer".to_string())
|
.with_name("Bonerattler".to_string())
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
.with_loot_drop(comp::Item::new_from_asset_expect(
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::CultistAcolyte)
|
chosen
|
||||||
.with_scale(2.0)
|
));
|
||||||
.with_main_tool(
|
3
|
||||||
comp::Item::new_from_asset_expect(
|
],
|
||||||
|
2 => vec![
|
||||||
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
.with_body(comp::Body::QuadrupedMedium(
|
||||||
|
comp::quadruped_medium::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::quadruped_medium::Species::Tarasque,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.with_name("Tarasque".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
|
],
|
||||||
|
3 => vec![
|
||||||
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
.with_body(comp::Body::Humanoid(
|
||||||
|
comp::humanoid::Body::random(),
|
||||||
|
))
|
||||||
|
.with_name("Animal Trainer".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen))
|
||||||
|
.with_config(
|
||||||
|
common::loadout_builder::LoadoutConfig::CultistAcolyte,
|
||||||
|
)
|
||||||
|
.with_scale(2.0)
|
||||||
|
.with_main_tool(comp::Item::new_from_asset_expect(
|
||||||
match dynamic_rng.gen_range(0, 6) {
|
match dynamic_rng.gen_range(0, 6) {
|
||||||
0 => "common.items.weapons.axe.malachite_axe-0",
|
0 => "common.items.weapons.axe.malachite_axe-0",
|
||||||
1 => "common.items.weapons.sword.cultist_purp_2h-0",
|
1 => "common.items.weapons.sword.cultist_purp_2h-0",
|
||||||
2 => "common.items.weapons.sword.cultist_purp_2h-0",
|
2 => "common.items.weapons.sword.cultist_purp_2h-0",
|
||||||
3 => "common.items.weapons.hammer.cultist_purp_2h-0",
|
3 => {
|
||||||
|
"common.items.weapons.hammer.cultist_purp_2h-0"
|
||||||
|
},
|
||||||
4 => "common.items.weapons.staff.cultist_staff",
|
4 => "common.items.weapons.staff.cultist_staff",
|
||||||
_ => "common.items.weapons.bow.horn_longbow-0",
|
_ => "common.items.weapons.bow.horn_longbow-0",
|
||||||
},
|
},
|
||||||
|
)),
|
||||||
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
.with_body(comp::Body::QuadrupedMedium(
|
||||||
|
comp::quadruped_medium::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::quadruped_medium::Species::Wolf,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.with_name("Tamed Wolf".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
.with_body(comp::Body::QuadrupedMedium(
|
||||||
|
comp::quadruped_medium::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::quadruped_medium::Species::Wolf,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.with_name("Tamed Wolf".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
|
],
|
||||||
|
4 => vec![
|
||||||
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
.with_body(comp::Body::BipedLarge(
|
||||||
|
comp::biped_large::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::biped_large::Species::Dullahan,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.with_name("Dullahan Guard".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
|
],
|
||||||
|
5 => vec![
|
||||||
|
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
||||||
|
.with_body(comp::Body::Golem(
|
||||||
|
comp::golem::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::golem::Species::StoneGolem,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.with_name("Stonework Defender".to_string())
|
||||||
|
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
||||||
|
],
|
||||||
|
_ => {
|
||||||
|
vec![EntityInfo::at(tile_wcenter.map(|e| e as f32)).with_body(
|
||||||
|
comp::Body::QuadrupedSmall(
|
||||||
|
comp::quadruped_small::Body::random_with(
|
||||||
|
dynamic_rng,
|
||||||
|
&comp::quadruped_small::Species::Sheep,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
)]
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
},
|
||||||
.with_body(comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random_with(
|
};
|
||||||
dynamic_rng,
|
|
||||||
&comp::quadruped_medium::Species::Wolf,
|
|
||||||
)))
|
|
||||||
.with_name("Tamed Wolf".to_string())
|
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
|
||||||
EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
|
||||||
.with_body(comp::Body::QuadrupedMedium(comp::quadruped_medium::Body::random_with(
|
|
||||||
dynamic_rng,
|
|
||||||
&comp::quadruped_medium::Species::Wolf,
|
|
||||||
)))
|
|
||||||
.with_name("Tamed Wolf".to_string())
|
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
|
||||||
],
|
|
||||||
4 =>
|
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
|
||||||
.with_body(comp::Body::BipedLarge(comp::biped_large::Body::random_with(
|
|
||||||
dynamic_rng,
|
|
||||||
&comp::biped_large::Species::Dullahan,
|
|
||||||
)))
|
|
||||||
.with_name("Dullahan Guard".to_string())
|
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
|
||||||
],
|
|
||||||
5 =>
|
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
|
||||||
.with_body(comp::Body::Golem(comp::golem::Body::random_with(
|
|
||||||
dynamic_rng,
|
|
||||||
&comp::golem::Species::StoneGolem,
|
|
||||||
)))
|
|
||||||
.with_name("Stonework Defender".to_string())
|
|
||||||
.with_loot_drop(comp::Item::new_from_asset_expect(chosen)),
|
|
||||||
],
|
|
||||||
_ =>
|
|
||||||
vec![ EntityInfo::at(tile_wcenter.map(|e| e as f32))
|
|
||||||
.with_body(comp::Body::QuadrupedSmall(comp::quadruped_small::Body::random_with(
|
|
||||||
dynamic_rng,
|
|
||||||
&comp::quadruped_small::Species::Sheep,
|
|
||||||
))),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
for entity in entity {
|
for entity in entity {
|
||||||
supplement.add_entity(entity.with_level(
|
supplement.add_entity(
|
||||||
dynamic_rng
|
entity
|
||||||
.gen_range(
|
.with_level(
|
||||||
(room.difficulty as f32).powf(1.25) + 3.0,
|
dynamic_rng
|
||||||
(room.difficulty as f32).powf(1.5) + 4.0,
|
.gen_range(
|
||||||
|
(room.difficulty as f32).powf(1.25) + 3.0,
|
||||||
|
(room.difficulty as f32).powf(1.5) + 4.0,
|
||||||
|
)
|
||||||
|
.round()
|
||||||
|
as u32
|
||||||
|
* 5,
|
||||||
)
|
)
|
||||||
.round() as u32
|
.with_alignment(comp::Alignment::Enemy),
|
||||||
* 5,
|
|
||||||
)
|
|
||||||
.with_alignment(comp::Alignment::Enemy),
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
mod block_mask;
|
mod block_mask;
|
||||||
mod castle;
|
mod castle;
|
||||||
mod dungeon;
|
mod dungeon;
|
||||||
mod namegen;
|
|
||||||
pub mod economy;
|
pub mod economy;
|
||||||
|
mod namegen;
|
||||||
mod settlement;
|
mod settlement;
|
||||||
|
|
||||||
// Reexports
|
// Reexports
|
||||||
|
@ -17,13 +17,14 @@ impl<'a, R: Rng> NameGen<'a, R> {
|
|||||||
|
|
||||||
pub fn generate(self) -> String {
|
pub fn generate(self) -> String {
|
||||||
let cons = vec![
|
let cons = vec![
|
||||||
"d", "f", "ph", "r", "st", "t", "s", "p", "sh", "th", "br", "tr", "m", "k", "st", "w", "y",
|
"d", "f", "ph", "r", "st", "t", "s", "p", "sh", "th", "br", "tr", "m", "k", "st", "w",
|
||||||
"cr", "fr", "dr", "pl", "wr", "sn", "g", "qu", "l",
|
"y", "cr", "fr", "dr", "pl", "wr", "sn", "g", "qu", "l",
|
||||||
];
|
];
|
||||||
let mut start = cons.clone();
|
let mut start = cons.clone();
|
||||||
start.extend(vec![
|
start.extend(vec![
|
||||||
"cr", "thr", "str", "br", "iv", "est", "ost", "ing", "kr", "in", "on", "tr", "tw", "wh",
|
"cr", "thr", "str", "br", "iv", "est", "ost", "ing", "kr", "in", "on", "tr", "tw",
|
||||||
"eld", "ar", "or", "ear", "irr", "mi", "en", "ed", "et", "ow", "fr", "shr", "wr", "gr", "pr",
|
"wh", "eld", "ar", "or", "ear", "irr", "mi", "en", "ed", "et", "ow", "fr", "shr", "wr",
|
||||||
|
"gr", "pr",
|
||||||
]);
|
]);
|
||||||
let mut middle = cons.clone();
|
let mut middle = cons.clone();
|
||||||
middle.extend(vec!["tt"]);
|
middle.extend(vec!["tt"]);
|
||||||
@ -43,14 +44,9 @@ impl<'a, R: Rng> NameGen<'a, R> {
|
|||||||
}
|
}
|
||||||
name += end.choose(self.rng).unwrap();
|
name += end.choose(self.rng).unwrap();
|
||||||
|
|
||||||
name
|
name.chars()
|
||||||
.chars()
|
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, c)| if i == 0 {
|
.map(|(i, c)| if i == 0 { c.to_ascii_uppercase() } else { c })
|
||||||
c.to_ascii_uppercase()
|
|
||||||
} else {
|
|
||||||
c
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ use super::SpawnRules;
|
|||||||
use crate::{
|
use crate::{
|
||||||
column::ColumnSample,
|
column::ColumnSample,
|
||||||
sim::WorldSim,
|
sim::WorldSim,
|
||||||
util::{RandomField, Sampler, StructureGen2d},
|
|
||||||
site::namegen::NameGen,
|
site::namegen::NameGen,
|
||||||
|
util::{RandomField, Sampler, StructureGen2d},
|
||||||
IndexRef,
|
IndexRef,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
@ -188,9 +188,7 @@ impl Settlement {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str { &self.name }
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_origin(&self) -> Vec2<i32> { self.origin }
|
pub fn get_origin(&self) -> Vec2<i32> { self.origin }
|
||||||
|
|
||||||
@ -921,14 +919,16 @@ impl Settlement {
|
|||||||
.do_if(is_dummy, |e| e.with_name("Training Dummy"))
|
.do_if(is_dummy, |e| e.with_name("Training Dummy"))
|
||||||
.do_if(is_human && dynamic_rng.gen(), |entity| {
|
.do_if(is_human && dynamic_rng.gen(), |entity| {
|
||||||
match dynamic_rng.gen_range(0, 5) {
|
match dynamic_rng.gen_range(0, 5) {
|
||||||
0 => entity.with_main_tool(Item::new_from_asset_expect(
|
0 => entity
|
||||||
"common.items.weapons.sword.greatsword_2h_simple-0",
|
.with_main_tool(Item::new_from_asset_expect(
|
||||||
))
|
"common.items.weapons.sword.greatsword_2h_simple-0",
|
||||||
.with_name("Guard")
|
))
|
||||||
.with_level(dynamic_rng.gen_range(10, 15))
|
.with_name("Guard")
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Guard),
|
.with_level(dynamic_rng.gen_range(10, 15))
|
||||||
_ => entity.with_main_tool(Item::new_from_asset_expect(
|
.with_config(common::loadout_builder::LoadoutConfig::Guard),
|
||||||
match dynamic_rng.gen_range(0, 7) {
|
_ => entity
|
||||||
|
.with_main_tool(Item::new_from_asset_expect(
|
||||||
|
match dynamic_rng.gen_range(0, 7) {
|
||||||
0 => "common.items.npc_weapons.tool.broom",
|
0 => "common.items.npc_weapons.tool.broom",
|
||||||
1 => "common.items.npc_weapons.tool.hoe",
|
1 => "common.items.npc_weapons.tool.hoe",
|
||||||
2 => "common.items.npc_weapons.tool.pickaxe",
|
2 => "common.items.npc_weapons.tool.pickaxe",
|
||||||
@ -938,9 +938,9 @@ impl Settlement {
|
|||||||
_ => "common.items.npc_weapons.tool.shovel-1",
|
_ => "common.items.npc_weapons.tool.shovel-1",
|
||||||
//_ => "common.items.npc_weapons.bow.starter_bow", TODO: Re-Add this when we have a better way of distributing npc_weapons here
|
//_ => "common.items.npc_weapons.bow.starter_bow", TODO: Re-Add this when we have a better way of distributing npc_weapons here
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.with_config(common::loadout_builder::LoadoutConfig::Villager)
|
.with_config(common::loadout_builder::LoadoutConfig::Villager),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
supplement.add_entity(entity);
|
supplement.add_entity(entity);
|
||||||
|
Loading…
Reference in New Issue
Block a user