mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Airship progress: now possessable, and physics kind of works (desyncs from the visuals by a shift + scale, and rotation isn't done at all yet, but the contours are correct).
This commit is contained in:
parent
1d0600851b
commit
6d35e7c6d0
@ -1,16 +1,17 @@
|
|||||||
({
|
({
|
||||||
DefaultAirship: (
|
DefaultAirship: (
|
||||||
bone0: (
|
bone0: (
|
||||||
offset: (-20.0, -35.0, 1.0),
|
//offset: (-20.0, -35.0, 1.0),
|
||||||
|
offset: (3.0, 7.0, 1.0),
|
||||||
central: ("object.Human_Airship"),
|
central: ("object.Human_Airship"),
|
||||||
),
|
),
|
||||||
bone1: (
|
bone1: (
|
||||||
offset: (0.0, 0.0, 0.0),
|
offset: (0.0, 40.0, -8.0),
|
||||||
central: ("propeller-l"),
|
central: ("object.propeller-l"),
|
||||||
),
|
),
|
||||||
bone2: (
|
bone2: (
|
||||||
offset: (0.0, 0.0, 0.0),
|
offset: (0.0, 0.0, -4.0),
|
||||||
central: ("propeller-r"),
|
central: ("object.propeller-r"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
BIN
assets/server/voxel/Human_Airship.vox
(Stored with Git LFS)
BIN
assets/server/voxel/Human_Airship.vox
(Stored with Git LFS)
Binary file not shown.
BIN
assets/voxygen/voxel/object/Human_Airship.vox
(Stored with Git LFS)
BIN
assets/voxygen/voxel/object/Human_Airship.vox
(Stored with Git LFS)
Binary file not shown.
1
assets/voxygen/voxel/object/Human_Airship.vox
Symbolic link
1
assets/voxygen/voxel/object/Human_Airship.vox
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../server/voxel/Human_Airship.vox
|
@ -1,6 +1,4 @@
|
|||||||
use crate::{
|
use crate::make_case_elim;
|
||||||
make_case_elim
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
make_case_elim!(
|
make_case_elim!(
|
||||||
@ -17,22 +15,29 @@ impl From<Body> for super::Body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Body {
|
impl Body {
|
||||||
pub fn manifest_id(&self) -> &'static str {
|
pub fn manifest_entry(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Body::DefaultAirship => "server.manifests.ship_manifest",
|
Body::DefaultAirship => "object.Human_Airship",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Duplicate of some of the things defined in `voxygen::scene::figure::load` to avoid having to
|
/// Duplicate of some of the things defined in `voxygen::scene::figure::load` to
|
||||||
/// refactor all of that to `common` for using voxels as collider geometry
|
/// avoid having to refactor all of that to `common` for using voxels as
|
||||||
|
/// collider geometry
|
||||||
pub mod figuredata {
|
pub mod figuredata {
|
||||||
use crate::{
|
use crate::{
|
||||||
assets::{self, AssetExt, AssetHandle, DotVoxAsset, Ron},
|
assets::{self, AssetExt, AssetHandle, DotVoxAsset, Ron},
|
||||||
volumes::dyna::Dyna,
|
figure::cell::Cell,
|
||||||
|
terrain::{
|
||||||
|
block::{Block, BlockKind},
|
||||||
|
sprite::SpriteKind,
|
||||||
|
},
|
||||||
|
volumes::dyna::{ColumnAccess, Dyna},
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct VoxSimple(pub String);
|
pub struct VoxSimple(pub String);
|
||||||
@ -57,13 +62,43 @@ pub mod figuredata {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ShipSpec {
|
pub struct ShipSpec {
|
||||||
pub central: AssetHandle<Ron<ShipCentralSpec>>,
|
pub central: AssetHandle<Ron<ShipCentralSpec>>,
|
||||||
|
pub voxes: HashMap<String, Dyna<Block, (), ColumnAccess>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for ShipSpec {
|
impl assets::Compound for ShipSpec {
|
||||||
fn load<S: assets::source::Source>(_: &assets::AssetCache<S>, _: &str) -> Result<Self, assets::Error> {
|
fn load<S: assets::source::Source>(
|
||||||
|
cache: &assets::AssetCache<S>,
|
||||||
|
_: &str,
|
||||||
|
) -> Result<Self, assets::Error> {
|
||||||
|
let manifest: AssetHandle<Ron<ShipCentralSpec>> = AssetExt::load("server.manifests.ship_manifest")?;
|
||||||
|
let mut voxes = HashMap::new();
|
||||||
|
for (_, spec) in (manifest.read().0).0.iter() {
|
||||||
|
for bone in [&spec.bone0, &spec.bone1, &spec.bone2].iter() {
|
||||||
|
// TODO: avoid the requirement for symlinks in "voxygen.voxel.object.", and load
|
||||||
|
// the models from "server.voxel." instead
|
||||||
|
let vox =
|
||||||
|
cache.load::<DotVoxAsset>(&["voxygen.voxel.", &bone.central.0].concat())?;
|
||||||
|
let dyna = Dyna::<Cell, (), ColumnAccess>::from_vox(&vox.read().0, false);
|
||||||
|
voxes.insert(bone.central.0.clone(), dyna.map_into(|cell| {
|
||||||
|
if let Some(rgb) = cell.get_color() {
|
||||||
|
Block::new(BlockKind::Misc, rgb)
|
||||||
|
} else {
|
||||||
|
Block::air(SpriteKind::Empty)
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(ShipSpec {
|
Ok(ShipSpec {
|
||||||
central: AssetExt::load("server.manifests.ship_manifest")?
|
central: manifest,
|
||||||
|
voxes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
// TODO: load this from the ECS as a resource, and maybe make it more general than ships
|
||||||
|
// (although figuring out how to keep the figure bones in sync with the terrain offsets seems
|
||||||
|
// like a hard problem if they're not the same manifest)
|
||||||
|
pub static ref VOXEL_COLLIDER_MANIFEST: ShipSpec = AssetExt::load_expect_cloned("server.manifests.ship_manifest");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ pub enum Collider {
|
|||||||
impl Collider {
|
impl Collider {
|
||||||
pub fn get_radius(&self) -> f32 {
|
pub fn get_radius(&self) -> f32 {
|
||||||
match self {
|
match self {
|
||||||
Collider::Voxel { .. } => 0.0,
|
Collider::Voxel { .. } => 1.0,
|
||||||
Collider::Box { radius, .. } => *radius,
|
Collider::Box { radius, .. } => *radius,
|
||||||
Collider::Point => 0.0,
|
Collider::Point => 0.0,
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ impl Collider {
|
|||||||
|
|
||||||
pub fn get_z_limits(&self, modifier: f32) -> (f32, f32) {
|
pub fn get_z_limits(&self, modifier: f32) -> (f32, f32) {
|
||||||
match self {
|
match self {
|
||||||
Collider::Voxel { .. } => (0.0, 0.0),
|
Collider::Voxel { .. } => (0.0, 1.0),
|
||||||
Collider::Box { z_min, z_max, .. } => (*z_min * modifier, *z_max * modifier),
|
Collider::Box { z_min, z_max, .. } => (*z_min * modifier, *z_max * modifier),
|
||||||
Collider::Point => (0.0, 0.0),
|
Collider::Point => (0.0, 0.0),
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,16 @@ impl<V, M, A: Access> Dyna<V, M, A> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn map_into<W, F: FnMut(V) -> W>(self, f: F) -> Dyna<W, M, A> {
|
||||||
|
let Dyna { vox, meta, sz, _phantom } = self;
|
||||||
|
Dyna {
|
||||||
|
vox: vox.into_iter().map(f).collect(),
|
||||||
|
meta,
|
||||||
|
sz,
|
||||||
|
_phantom,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V, M, A: Access> BaseVol for Dyna<V, M, A> {
|
impl<V, M, A: Access> BaseVol for Dyna<V, M, A> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
BeamSegment, CharacterState, Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos,
|
BeamSegment, CharacterState, Collider, Gravity, Mass, Mounting, Ori, PhysicsState, Pos,
|
||||||
PreviousPhysCache, Projectile, Scale, Shockwave, Sticky, Vel,
|
PreviousPhysCache, Projectile, Scale, Shockwave, Sticky, Vel, body::ship::figuredata::VOXEL_COLLIDER_MANIFEST,
|
||||||
},
|
},
|
||||||
consts::{FRIC_GROUND, GRAVITY},
|
consts::{FRIC_GROUND, GRAVITY},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
@ -15,8 +15,9 @@ use common_ecs::{Job, Origin, ParMode, Phase, PhysicsMetrics, System};
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use rayon::iter::ParallelIterator;
|
use rayon::iter::ParallelIterator;
|
||||||
use specs::{
|
use specs::{
|
||||||
shred::{World, ResourceId},
|
shred::{ResourceId, World},
|
||||||
Entities, Entity, Join, ParJoin, Read, ReadExpect, ReadStorage, WriteExpect, WriteStorage, SystemData,
|
Entities, Entity, Join, ParJoin, Read, ReadExpect, ReadStorage, SystemData, WriteExpect,
|
||||||
|
WriteStorage,
|
||||||
};
|
};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use vek::*;
|
use vek::*;
|
||||||
@ -114,7 +115,9 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
let _ = self.w.physics_states
|
let _ = self
|
||||||
|
.w
|
||||||
|
.physics_states
|
||||||
.entry(entity)
|
.entry(entity)
|
||||||
.map(|e| e.or_insert_with(Default::default));
|
.map(|e| e.or_insert_with(Default::default));
|
||||||
}
|
}
|
||||||
@ -137,7 +140,10 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
.map(|(e, _, _, _, _, _, _)| e)
|
.map(|(e, _, _, _, _, _, _)| e)
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
{
|
{
|
||||||
let _ = self.w.previous_phys_cache.insert(entity, PreviousPhysCache {
|
let _ = self
|
||||||
|
.w
|
||||||
|
.previous_phys_cache
|
||||||
|
.insert(entity, PreviousPhysCache {
|
||||||
velocity_dt: Vec3::zero(),
|
velocity_dt: Vec3::zero(),
|
||||||
center: Vec3::zero(),
|
center: Vec3::zero(),
|
||||||
collision_boundary: 0.0,
|
collision_boundary: 0.0,
|
||||||
@ -180,10 +186,14 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
}
|
}
|
||||||
drop(guard);
|
drop(guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_pushback(&mut self, job: &mut Job<Sys>) {
|
fn apply_pushback(&mut self, job: &mut Job<Sys>) {
|
||||||
span!(guard, "Apply pushback");
|
span!(guard, "Apply pushback");
|
||||||
job.cpu_stats.measure(ParMode::Rayon);
|
job.cpu_stats.measure(ParMode::Rayon);
|
||||||
let PhysicsSystemData { r: ref psdr, w: ref mut psdw } = self;
|
let PhysicsSystemData {
|
||||||
|
r: ref psdr,
|
||||||
|
w: ref mut psdw,
|
||||||
|
} = self;
|
||||||
let (positions, previous_phys_cache) = (&psdw.positions, &psdw.previous_phys_cache);
|
let (positions, previous_phys_cache) = (&psdw.positions, &psdw.previous_phys_cache);
|
||||||
let metrics = (
|
let metrics = (
|
||||||
&psdr.entities,
|
&psdr.entities,
|
||||||
@ -310,8 +320,13 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
metrics.entity_entity_collisions += 1;
|
metrics.entity_entity_collisions += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't apply repulsive force to projectiles
|
// Don't apply repulsive force to projectiles or if we're colliding
|
||||||
if diff.magnitude_squared() > 0.0 && !is_projectile {
|
// with a terrain-like entity, or if we are a terrain-like entity
|
||||||
|
if diff.magnitude_squared() > 0.0
|
||||||
|
&& !is_projectile
|
||||||
|
&& !matches!(collider_other, Some(Collider::Voxel { .. }))
|
||||||
|
&& !matches!(collider, Some(Collider::Voxel { .. }))
|
||||||
|
{
|
||||||
let force =
|
let force =
|
||||||
400.0 * (collision_dist - diff.magnitude()) * mass_other
|
400.0 * (collision_dist - diff.magnitude()) * mass_other
|
||||||
/ (mass + mass_other);
|
/ (mass + mass_other);
|
||||||
@ -335,18 +350,21 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
entity_entity_collisions: old.entity_entity_collisions
|
entity_entity_collisions: old.entity_entity_collisions
|
||||||
+ new.entity_entity_collisions,
|
+ new.entity_entity_collisions,
|
||||||
});
|
});
|
||||||
psdw.physics_metrics.entity_entity_collision_checks = metrics.entity_entity_collision_checks;
|
psdw.physics_metrics.entity_entity_collision_checks =
|
||||||
|
metrics.entity_entity_collision_checks;
|
||||||
psdw.physics_metrics.entity_entity_collisions = metrics.entity_entity_collisions;
|
psdw.physics_metrics.entity_entity_collisions = metrics.entity_entity_collisions;
|
||||||
drop(guard);
|
drop(guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_movement_and_terrain(&mut self, job: &mut Job<Sys>) {
|
fn handle_movement_and_terrain(&mut self, job: &mut Job<Sys>) {
|
||||||
let PhysicsSystemData { r: ref psdr, w: ref mut psdw } = self;
|
let PhysicsSystemData {
|
||||||
|
r: ref psdr,
|
||||||
|
w: ref mut psdw,
|
||||||
|
} = self;
|
||||||
// Apply movement inputs
|
// Apply movement inputs
|
||||||
span!(guard, "Apply movement and terrain collision");
|
span!(guard, "Apply movement and terrain collision");
|
||||||
let (positions, previous_phys_cache) = (&psdw.positions, &psdw.previous_phys_cache);
|
let (positions, previous_phys_cache) = (&psdw.positions, &psdw.previous_phys_cache);
|
||||||
let (pos_writes, land_on_grounds) =
|
let (pos_writes, land_on_grounds) = (
|
||||||
(
|
|
||||||
&psdr.entities,
|
&psdr.entities,
|
||||||
psdr.scales.maybe(),
|
psdr.scales.maybe(),
|
||||||
psdr.stickies.maybe(),
|
psdr.stickies.maybe(),
|
||||||
@ -405,7 +423,8 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
});
|
});
|
||||||
let in_loaded_chunk = psdr.terrain
|
let in_loaded_chunk = psdr
|
||||||
|
.terrain
|
||||||
.get_key(psdr.terrain.pos_key(pos.0.map(|e| e.floor() as i32)))
|
.get_key(psdr.terrain.pos_key(pos.0.map(|e| e.floor() as i32)))
|
||||||
.is_some();
|
.is_some();
|
||||||
let downward_force =
|
let downward_force =
|
||||||
@ -474,7 +493,8 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
Collider::Point => {
|
Collider::Point => {
|
||||||
let (dist, block) = psdr.terrain
|
let (dist, block) = psdr
|
||||||
|
.terrain
|
||||||
.ray(pos.0, pos.0 + pos_delta)
|
.ray(pos.0, pos.0 + pos_delta)
|
||||||
.until(|block: &Block| block.is_filled())
|
.until(|block: &Block| block.is_filled())
|
||||||
.ignore_error()
|
.ignore_error()
|
||||||
@ -511,7 +531,8 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
physics_state.in_liquid = psdr.terrain
|
physics_state.in_liquid = psdr
|
||||||
|
.terrain
|
||||||
.get(pos.0.map(|e| e.floor() as i32))
|
.get(pos.0.map(|e| e.floor() as i32))
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|vox| vox.is_liquid().then_some(1.0));
|
.and_then(|vox| vox.is_liquid().then_some(1.0));
|
||||||
@ -546,7 +567,7 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
let collision_boundary = previous_cache.collision_boundary
|
/*let collision_boundary = previous_cache.collision_boundary
|
||||||
+ previous_cache_other.collision_boundary;
|
+ previous_cache_other.collision_boundary;
|
||||||
if previous_cache
|
if previous_cache
|
||||||
.center
|
.center
|
||||||
@ -555,7 +576,7 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
|| entity == entity_other
|
|| entity == entity_other
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if let Collider::Voxel { id } = collider_other {
|
if let Collider::Voxel { id } = collider_other {
|
||||||
// use bounding cylinder regardless of our collider
|
// use bounding cylinder regardless of our collider
|
||||||
@ -563,19 +584,21 @@ impl<'a> PhysicsSystemData<'a> {
|
|||||||
let radius = collider.get_radius() * scale;
|
let radius = collider.get_radius() * scale;
|
||||||
let (z_min, z_max) = collider.get_z_limits(scale);
|
let (z_min, z_max) = collider.get_z_limits(scale);
|
||||||
|
|
||||||
|
pos.0 -= pos_other.0;
|
||||||
let cylinder = (radius, z_min, z_max);
|
let cylinder = (radius, z_min, z_max);
|
||||||
// TODO: load .vox into a Dyna, and use it (appropriately rotated)
|
if let Some(dyna) = VOXEL_COLLIDER_MANIFEST.voxes.get(id) {
|
||||||
// as the terrain
|
cylinder_voxel_collision(
|
||||||
/*cylinder_voxel_collision(
|
|
||||||
cylinder,
|
cylinder,
|
||||||
&*psdr.terrain,
|
&*dyna,
|
||||||
entity,
|
entity,
|
||||||
&mut pos,
|
&mut pos,
|
||||||
pos_delta,
|
pos_delta,
|
||||||
vel,
|
vel,
|
||||||
&mut physics_state,
|
&mut physics_state,
|
||||||
&mut land_on_grounds,
|
&mut land_on_grounds,
|
||||||
);*/
|
);
|
||||||
|
}
|
||||||
|
pos.0 += pos_other.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pos != old_pos {
|
if pos != old_pos {
|
||||||
@ -620,10 +643,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||||
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
#[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
|
||||||
fn run(
|
fn run(job: &mut Job<Self>, mut psd: Self::SystemData) {
|
||||||
job: &mut Job<Self>,
|
|
||||||
mut psd: Self::SystemData,
|
|
||||||
) {
|
|
||||||
psd.reset();
|
psd.reset();
|
||||||
|
|
||||||
// Apply pushback
|
// Apply pushback
|
||||||
@ -642,7 +662,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
psd.maintain_pushback_cache();
|
psd.maintain_pushback_cache();
|
||||||
psd.apply_pushback(job);
|
psd.apply_pushback(job);
|
||||||
|
|
||||||
|
|
||||||
psd.handle_movement_and_terrain(job);
|
psd.handle_movement_and_terrain(job);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -966,11 +966,12 @@ fn handle_spawn_airship(
|
|||||||
_action: &ChatCommand,
|
_action: &ChatCommand,
|
||||||
) {
|
) {
|
||||||
match server.state.read_component_copied::<comp::Pos>(target) {
|
match server.state.read_component_copied::<comp::Pos>(target) {
|
||||||
Some(pos) => {
|
Some(mut pos) => {
|
||||||
|
pos.0.z += 50.0;
|
||||||
server
|
server
|
||||||
.state
|
.state
|
||||||
.create_ship(pos, comp::ship::Body::DefaultAirship)
|
.create_ship(pos, comp::ship::Body::DefaultAirship, 1)
|
||||||
.with(comp::Scale(50.0))
|
.with(comp::Scale(11.0))
|
||||||
.with(LightEmitter {
|
.with(LightEmitter {
|
||||||
col: Rgb::new(1.0, 0.65, 0.2),
|
col: Rgb::new(1.0, 0.65, 0.2),
|
||||||
strength: 2.0,
|
strength: 2.0,
|
||||||
|
@ -41,7 +41,7 @@ pub trait StateExt {
|
|||||||
) -> EcsEntityBuilder;
|
) -> EcsEntityBuilder;
|
||||||
/// Build a static object entity
|
/// Build a static object entity
|
||||||
fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder;
|
fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder;
|
||||||
fn create_ship(&mut self, pos: comp::Pos, object: comp::ship::Body) -> EcsEntityBuilder;
|
fn create_ship(&mut self, pos: comp::Pos, object: comp::ship::Body, level: u16) -> EcsEntityBuilder;
|
||||||
/// Build a projectile
|
/// Build a projectile
|
||||||
fn create_projectile(
|
fn create_projectile(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -203,16 +203,24 @@ impl StateExt for State {
|
|||||||
.with(comp::Gravity(1.0))
|
.with(comp::Gravity(1.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_ship(&mut self, pos: comp::Pos, object: comp::ship::Body) -> EcsEntityBuilder {
|
fn create_ship(&mut self, pos: comp::Pos, ship: comp::ship::Body, level: u16) -> EcsEntityBuilder {
|
||||||
self.ecs_mut()
|
self.ecs_mut()
|
||||||
.create_entity_synced()
|
.create_entity_synced()
|
||||||
.with(pos)
|
.with(pos)
|
||||||
.with(comp::Vel(Vec3::zero()))
|
.with(comp::Vel(Vec3::zero()))
|
||||||
.with(comp::Ori::default())
|
.with(comp::Ori::default())
|
||||||
.with(comp::Mass(50.0))
|
.with(comp::Mass(50.0))
|
||||||
.with(comp::Collider::Voxel { id: object.manifest_id().to_string() })
|
.with(comp::Collider::Voxel { id: ship.manifest_entry().to_string() })
|
||||||
.with(comp::Body::Ship(object))
|
.with(comp::Body::Ship(ship))
|
||||||
.with(comp::Gravity(1.0))
|
.with(comp::Gravity(1.0))
|
||||||
|
.with(comp::Controller::default())
|
||||||
|
.with(comp::inventory::Inventory::new_empty())
|
||||||
|
.with(comp::CharacterState::default())
|
||||||
|
.with(comp::Energy::new(ship.into(), level))
|
||||||
|
.with(comp::Health::new(ship.into(), level))
|
||||||
|
.with(comp::Stats::new("Airship".to_string()))
|
||||||
|
.with(comp::Buffs::default())
|
||||||
|
.with(comp::Combo::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_projectile(
|
fn create_projectile(
|
||||||
|
@ -4120,7 +4120,7 @@ impl FigureMgr {
|
|||||||
.join()
|
.join()
|
||||||
// Don't render dead entities
|
// Don't render dead entities
|
||||||
.filter(|(_, _, _, _, health, _, _)| health.map_or(true, |h| !h.is_dead))
|
.filter(|(_, _, _, _, health, _, _)| health.map_or(true, |h| !h.is_dead))
|
||||||
.for_each(|(entity, pos, _, body, _, inventory, _)| {
|
.for_each(|(entity, pos, _, body, _, inventory, scale)| {
|
||||||
if let Some((locals, bone_consts, model, _)) = self.get_model_for_render(
|
if let Some((locals, bone_consts, model, _)) = self.get_model_for_render(
|
||||||
tick,
|
tick,
|
||||||
camera,
|
camera,
|
||||||
@ -4130,7 +4130,7 @@ impl FigureMgr {
|
|||||||
inventory,
|
inventory,
|
||||||
false,
|
false,
|
||||||
pos.0,
|
pos.0,
|
||||||
figure_lod_render_distance,
|
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
||||||
|state| state.can_shadow_sun(),
|
|state| state.can_shadow_sun(),
|
||||||
) {
|
) {
|
||||||
renderer.render_figure_shadow_directed(
|
renderer.render_figure_shadow_directed(
|
||||||
@ -4162,7 +4162,7 @@ impl FigureMgr {
|
|||||||
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
let character_state_storage = state.read_storage::<common::comp::CharacterState>();
|
||||||
let character_state = character_state_storage.get(player_entity);
|
let character_state = character_state_storage.get(player_entity);
|
||||||
|
|
||||||
for (entity, pos, _, body, _, inventory, _) in (
|
for (entity, pos, _, body, _, inventory, scale) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
ecs.read_storage::<Ori>().maybe(),
|
ecs.read_storage::<Ori>().maybe(),
|
||||||
@ -4187,7 +4187,7 @@ impl FigureMgr {
|
|||||||
inventory,
|
inventory,
|
||||||
false,
|
false,
|
||||||
pos.0,
|
pos.0,
|
||||||
figure_lod_render_distance,
|
figure_lod_render_distance * scale.map_or(1.0, |s| s.0),
|
||||||
|state| state.visible(),
|
|state| state.visible(),
|
||||||
) {
|
) {
|
||||||
renderer.render_figure(model, &col_lights, global, locals, bone_consts, lod);
|
renderer.render_figure(model, &col_lights, global, locals, bone_consts, lod);
|
||||||
|
Loading…
Reference in New Issue
Block a user