mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added bombs, throwable items, more block kinds, weaker explosions
This commit is contained in:
parent
1c7c04141a
commit
2f6a618d5a
@ -38,6 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- New quadruped_low body for reptile-likes
|
- New quadruped_low body for reptile-likes
|
||||||
- Added new animals
|
- Added new animals
|
||||||
- Better pathfinding
|
- Better pathfinding
|
||||||
|
- Bombs
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Switch to a new network backend that will allow several improvements in the future
|
- Switch to a new network backend that will allow several improvements in the future
|
||||||
- Connection screen fails after 4 minutes if it can't connect to the server instead of 80 minutes
|
- Connection screen fails after 4 minutes if it can't connect to the server instead of 80 minutes
|
||||||
- Rebuilt quadruped_medium animation and assets
|
- Rebuilt quadruped_medium animation and assets
|
||||||
|
- Disabled destruction of most blocks by explosions
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
7
assets/common/items/bomb.ron
Normal file
7
assets/common/items/bomb.ron
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Item(
|
||||||
|
name: "Bomb",
|
||||||
|
description: "Boom!\n\n<Right-Click to use>",
|
||||||
|
kind: Throwable(
|
||||||
|
kind: Bomb,
|
||||||
|
),
|
||||||
|
)
|
@ -200,7 +200,7 @@
|
|||||||
Tool(Staff(Sceptre)): VoxTrans(
|
Tool(Staff(Sceptre)): VoxTrans(
|
||||||
"voxel.weapon.staff.wood-nature",
|
"voxel.weapon.staff.wood-nature",
|
||||||
(1.0, -1.0, 0.0), (-310., 90.0, 0.0), 1.2,
|
(1.0, -1.0, 0.0), (-310., 90.0, 0.0), 1.2,
|
||||||
),
|
),
|
||||||
// Shields
|
// Shields
|
||||||
Tool(Shield(BasicShield)): VoxTrans(
|
Tool(Shield(BasicShield)): VoxTrans(
|
||||||
"voxel.weapon.shield.wood-0",
|
"voxel.weapon.shield.wood-0",
|
||||||
@ -219,11 +219,11 @@
|
|||||||
Lantern(Red0): Png(
|
Lantern(Red0): Png(
|
||||||
"element.icons.lantern_red-0",
|
"element.icons.lantern_red-0",
|
||||||
),
|
),
|
||||||
// Farming Equipment
|
// Farming Equipment
|
||||||
Tool(Farming(Broom)): VoxTrans(
|
Tool(Farming(Broom)): VoxTrans(
|
||||||
"voxel.weapon.tool.broom-0",
|
"voxel.weapon.tool.broom-0",
|
||||||
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
|
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
|
||||||
),
|
),
|
||||||
Tool(Farming(Hoe0)): VoxTrans(
|
Tool(Farming(Hoe0)): VoxTrans(
|
||||||
"voxel.weapon.tool.hoe_green",
|
"voxel.weapon.tool.hoe_green",
|
||||||
(0.0, 0.0, 0.0), (130.0, 35.0, 180.0), 1.0,
|
(0.0, 0.0, 0.0), (130.0, 35.0, 180.0), 1.0,
|
||||||
@ -231,7 +231,7 @@
|
|||||||
Tool(Farming(Hoe1)): VoxTrans(
|
Tool(Farming(Hoe1)): VoxTrans(
|
||||||
"voxel.weapon.tool.hoe_blue",
|
"voxel.weapon.tool.hoe_blue",
|
||||||
(0.0, 0.0, 0.0), (130.0, 35.0, 180.0), 1.0,
|
(0.0, 0.0, 0.0), (130.0, 35.0, 180.0), 1.0,
|
||||||
),
|
),
|
||||||
Tool(Farming(Pitchfork)): VoxTrans(
|
Tool(Farming(Pitchfork)): VoxTrans(
|
||||||
"voxel.weapon.tool.pitchfork-0",
|
"voxel.weapon.tool.pitchfork-0",
|
||||||
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
|
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
|
||||||
@ -255,7 +255,7 @@
|
|||||||
Tool(Farming(Shovel0)): VoxTrans(
|
Tool(Farming(Shovel0)): VoxTrans(
|
||||||
"voxel.weapon.tool.shovel_green",
|
"voxel.weapon.tool.shovel_green",
|
||||||
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2,
|
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2,
|
||||||
),
|
),
|
||||||
Tool(Farming(Shovel1)): VoxTrans(
|
Tool(Farming(Shovel1)): VoxTrans(
|
||||||
"voxel.weapon.tool.shovel_gold",
|
"voxel.weapon.tool.shovel_gold",
|
||||||
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2,
|
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2,
|
||||||
@ -264,7 +264,7 @@
|
|||||||
// Other
|
// Other
|
||||||
Utility(Collar): Png(
|
Utility(Collar): Png(
|
||||||
"element.icons.collar",
|
"element.icons.collar",
|
||||||
),
|
),
|
||||||
// Armor
|
// Armor
|
||||||
// Starter Parts
|
// Starter Parts
|
||||||
Armor(Foot(Sandal0)): VoxTrans(
|
Armor(Foot(Sandal0)): VoxTrans(
|
||||||
@ -311,7 +311,7 @@
|
|||||||
Armor(Pants(CultistBlue)): VoxTrans(
|
Armor(Pants(CultistBlue)): VoxTrans(
|
||||||
"voxel.armor.pants.cultist",
|
"voxel.armor.pants.cultist",
|
||||||
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
|
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
|
||||||
),
|
),
|
||||||
Armor(Hand(CultistBlue)): VoxTrans(
|
Armor(Hand(CultistBlue)): VoxTrans(
|
||||||
"voxel.armor.hand.cultist_right",
|
"voxel.armor.hand.cultist_right",
|
||||||
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
|
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
|
||||||
@ -680,7 +680,7 @@
|
|||||||
Armor(Shoulder(LeafyShoulder)): VoxTrans(
|
Armor(Shoulder(LeafyShoulder)): VoxTrans(
|
||||||
"voxel.armor.shoulder.twigsleaves_shoulder_right",
|
"voxel.armor.shoulder.twigsleaves_shoulder_right",
|
||||||
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
|
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
|
||||||
),
|
),
|
||||||
//TwigsFlowers Set
|
//TwigsFlowers Set
|
||||||
Armor(Chest(Twigsflowers)): VoxTrans(
|
Armor(Chest(Twigsflowers)): VoxTrans(
|
||||||
"voxel.armor.chest.twigsflowers_chest",
|
"voxel.armor.chest.twigsflowers_chest",
|
||||||
@ -710,7 +710,7 @@
|
|||||||
Armor(Pants(Hunting)): VoxTrans(
|
Armor(Pants(Hunting)): VoxTrans(
|
||||||
"voxel.armor.pants.grayscale",
|
"voxel.armor.pants.grayscale",
|
||||||
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
|
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
|
||||||
),
|
),
|
||||||
// Backs
|
// Backs
|
||||||
Armor(Back(Short0)): VoxTrans(
|
Armor(Back(Short0)): VoxTrans(
|
||||||
"voxel.armor.back.short-0",
|
"voxel.armor.back.short-0",
|
||||||
@ -722,15 +722,15 @@
|
|||||||
),
|
),
|
||||||
// Rings
|
// Rings
|
||||||
Armor(Ring(Ring0)): Png(
|
Armor(Ring(Ring0)): Png(
|
||||||
"element.icons.ring-0",
|
"element.icons.ring-0",
|
||||||
),
|
),
|
||||||
// Necks
|
// Necks
|
||||||
Armor(Neck(Neck0)): Png(
|
Armor(Neck(Neck0)): Png(
|
||||||
"element.icons.neck-0",
|
"element.icons.neck-0",
|
||||||
),
|
),
|
||||||
// Tabards
|
// Tabards
|
||||||
Armor(Tabard(Admin)): Png(
|
Armor(Tabard(Admin)): Png(
|
||||||
"element.icons.tabard_admin",
|
"element.icons.tabard_admin",
|
||||||
),
|
),
|
||||||
// Heads
|
// Heads
|
||||||
Armor(Head(Leather0)): VoxTrans(
|
Armor(Head(Leather0)): VoxTrans(
|
||||||
@ -746,7 +746,7 @@
|
|||||||
VoxTrans(
|
VoxTrans(
|
||||||
"element.icons.item_apple",
|
"element.icons.item_apple",
|
||||||
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 1.0,
|
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 1.0,
|
||||||
),
|
),
|
||||||
Consumable(Coconut): Png(
|
Consumable(Coconut): Png(
|
||||||
"element.icons.item_coconut",
|
"element.icons.item_coconut",
|
||||||
),
|
),
|
||||||
@ -761,7 +761,7 @@
|
|||||||
Consumable(Cheese): VoxTrans(
|
Consumable(Cheese): VoxTrans(
|
||||||
"element.icons.item_cheese",
|
"element.icons.item_cheese",
|
||||||
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 0.9,
|
(0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 0.9,
|
||||||
),
|
),
|
||||||
Consumable(Potion): VoxTrans(
|
Consumable(Potion): VoxTrans(
|
||||||
"voxel.object.potion_red",
|
"voxel.object.potion_red",
|
||||||
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 1.0,
|
(0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 1.0,
|
||||||
@ -777,6 +777,11 @@
|
|||||||
Consumable(VeloriteFrag): VoxTrans(
|
Consumable(VeloriteFrag): VoxTrans(
|
||||||
"voxel.sprite.velorite.velorite_1",
|
"voxel.sprite.velorite.velorite_1",
|
||||||
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
|
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
|
||||||
|
),
|
||||||
|
// Throwables
|
||||||
|
Throwable(Bomb): VoxTrans(
|
||||||
|
"voxel.object.bomb",
|
||||||
|
(0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8,
|
||||||
),
|
),
|
||||||
// Ingredients
|
// Ingredients
|
||||||
Ingredient(Flower): VoxTrans(
|
Ingredient(Flower): VoxTrans(
|
||||||
@ -791,5 +796,5 @@
|
|||||||
Tool(Debug(Boost)): VoxTrans(
|
Tool(Debug(Boost)): VoxTrans(
|
||||||
"voxel.weapon.tool.broom_belzeshrub_purple",
|
"voxel.weapon.tool.broom_belzeshrub_purple",
|
||||||
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
|
(0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
@ -28,6 +28,11 @@ pub enum Consumable {
|
|||||||
PotionExp,
|
PotionExp,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
|
pub enum Throwable {
|
||||||
|
Bomb,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum Utility {
|
pub enum Utility {
|
||||||
Collar,
|
Collar,
|
||||||
@ -86,6 +91,11 @@ pub enum ItemKind {
|
|||||||
#[serde(default = "default_amount")]
|
#[serde(default = "default_amount")]
|
||||||
amount: u32,
|
amount: u32,
|
||||||
},
|
},
|
||||||
|
Throwable {
|
||||||
|
kind: Throwable,
|
||||||
|
#[serde(default = "default_amount")]
|
||||||
|
amount: u32,
|
||||||
|
},
|
||||||
Utility {
|
Utility {
|
||||||
kind: Utility,
|
kind: Utility,
|
||||||
#[serde(default = "default_amount")]
|
#[serde(default = "default_amount")]
|
||||||
@ -129,15 +139,10 @@ impl Item {
|
|||||||
pub fn set_amount(&mut self, give_amount: u32) -> Result<(), assets::Error> {
|
pub fn set_amount(&mut self, give_amount: u32) -> Result<(), assets::Error> {
|
||||||
use ItemKind::*;
|
use ItemKind::*;
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Consumable { ref mut amount, .. } => {
|
Consumable { ref mut amount, .. }
|
||||||
*amount = give_amount;
|
| Throwable { ref mut amount, .. }
|
||||||
Ok(())
|
| Utility { ref mut amount, .. }
|
||||||
},
|
| Ingredient { ref mut amount, .. } => {
|
||||||
Utility { ref mut amount, .. } => {
|
|
||||||
*amount = give_amount;
|
|
||||||
Ok(())
|
|
||||||
},
|
|
||||||
Ingredient { ref mut amount, .. } => {
|
|
||||||
*amount = give_amount;
|
*amount = give_amount;
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|
@ -102,6 +102,37 @@ impl Inventory {
|
|||||||
// It didn't work
|
// It didn't work
|
||||||
self.add_to_first_empty(item)
|
self.add_to_first_empty(item)
|
||||||
},
|
},
|
||||||
|
ItemKind::Throwable {
|
||||||
|
kind: item_kind,
|
||||||
|
amount: new_amount,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
for slot in &mut self.slots {
|
||||||
|
if slot
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.name() == item.name())
|
||||||
|
.unwrap_or(false)
|
||||||
|
&& slot
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.description() == item.description())
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
if let Some(Item {
|
||||||
|
kind: ItemKind::Throwable { kind, amount, .. },
|
||||||
|
..
|
||||||
|
}) = slot
|
||||||
|
{
|
||||||
|
if item_kind == *kind {
|
||||||
|
*amount += new_amount;
|
||||||
|
self.recount_items();
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// It didn't work
|
||||||
|
self.add_to_first_empty(item)
|
||||||
|
},
|
||||||
ItemKind::Ingredient {
|
ItemKind::Ingredient {
|
||||||
kind: item_kind,
|
kind: item_kind,
|
||||||
amount: new_amount,
|
amount: new_amount,
|
||||||
@ -277,6 +308,19 @@ impl Inventory {
|
|||||||
Some(return_item)
|
Some(return_item)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
ItemKind::Throwable { kind, amount } => {
|
||||||
|
if *amount <= 1 {
|
||||||
|
self.remove(cell)
|
||||||
|
} else {
|
||||||
|
*amount -= 1;
|
||||||
|
return_item.kind = ItemKind::Throwable {
|
||||||
|
kind: *kind,
|
||||||
|
amount: 1,
|
||||||
|
};
|
||||||
|
self.recount_items();
|
||||||
|
Some(return_item)
|
||||||
|
}
|
||||||
|
},
|
||||||
ItemKind::Ingredient { kind, amount } => {
|
ItemKind::Ingredient { kind, amount } => {
|
||||||
if *amount <= 1 {
|
if *amount <= 1 {
|
||||||
self.remove(cell)
|
self.remove(cell)
|
||||||
|
16
common/src/comp/misc.rs
Normal file
16
common/src/comp/misc.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use crate::sync::Uid;
|
||||||
|
use specs::Component;
|
||||||
|
use specs_idvs::IDVStorage;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum Object {
|
||||||
|
Bomb {
|
||||||
|
timeout: Duration,
|
||||||
|
owner: Option<Uid>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Object {
|
||||||
|
type Storage = IDVStorage<Self>;
|
||||||
|
}
|
@ -10,6 +10,7 @@ mod inputs;
|
|||||||
mod inventory;
|
mod inventory;
|
||||||
mod last;
|
mod last;
|
||||||
mod location;
|
mod location;
|
||||||
|
mod misc;
|
||||||
mod phys;
|
mod phys;
|
||||||
mod player;
|
mod player;
|
||||||
pub mod projectile;
|
pub mod projectile;
|
||||||
@ -40,6 +41,7 @@ pub use inventory::{
|
|||||||
};
|
};
|
||||||
pub use last::Last;
|
pub use last::Last;
|
||||||
pub use location::{Waypoint, WaypointArea};
|
pub use location::{Waypoint, WaypointArea};
|
||||||
|
pub use misc::Object;
|
||||||
pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
|
pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel};
|
||||||
pub use player::Player;
|
pub use player::Player;
|
||||||
pub use projectile::Projectile;
|
pub use projectile::Projectile;
|
||||||
|
@ -122,6 +122,7 @@ impl State {
|
|||||||
ecs.register::<comp::Sticky>();
|
ecs.register::<comp::Sticky>();
|
||||||
ecs.register::<comp::Gravity>();
|
ecs.register::<comp::Gravity>();
|
||||||
ecs.register::<comp::CharacterState>();
|
ecs.register::<comp::CharacterState>();
|
||||||
|
ecs.register::<comp::Object>();
|
||||||
|
|
||||||
// Register components send from clients -> server
|
// Register components send from clients -> server
|
||||||
ecs.register::<comp::Controller>();
|
ecs.register::<comp::Controller>();
|
||||||
|
@ -9,6 +9,9 @@ pub enum BlockKind {
|
|||||||
Air,
|
Air,
|
||||||
Normal,
|
Normal,
|
||||||
Dense,
|
Dense,
|
||||||
|
Rock,
|
||||||
|
Grass,
|
||||||
|
Leaves,
|
||||||
Water,
|
Water,
|
||||||
LargeCactus,
|
LargeCactus,
|
||||||
BarrelCactus,
|
BarrelCactus,
|
||||||
@ -32,7 +35,6 @@ pub enum BlockKind {
|
|||||||
Velorite,
|
Velorite,
|
||||||
VeloriteFrag,
|
VeloriteFrag,
|
||||||
Chest,
|
Chest,
|
||||||
Leaves,
|
|
||||||
Pumpkin,
|
Pumpkin,
|
||||||
Welwitch,
|
Welwitch,
|
||||||
LingonBerry,
|
LingonBerry,
|
||||||
@ -325,6 +327,13 @@ impl BlockKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_explodable(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
BlockKind::Leaves | BlockKind::Grass | BlockKind::Rock => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Integrate this into `is_solid` by returning an `Option<f32>`
|
// TODO: Integrate this into `is_solid` by returning an `Option<f32>`
|
||||||
pub fn get_height(&self) -> f32 {
|
pub fn get_height(&self) -> f32 {
|
||||||
// Beware: the height *must* be <= `MAX_HEIGHT` or the collision system will not
|
// Beware: the height *must* be <= `MAX_HEIGHT` or the collision system will not
|
||||||
|
@ -292,11 +292,19 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, power: f32, owner: Opti
|
|||||||
)
|
)
|
||||||
.normalized();
|
.normalized();
|
||||||
|
|
||||||
let _ = ecs
|
let terrain = ecs.read_resource::<TerrainGrid>();
|
||||||
.read_resource::<TerrainGrid>()
|
let _ = terrain
|
||||||
.ray(pos, pos + dir * power)
|
.ray(pos, pos + dir * power)
|
||||||
.until(|_| rand::random::<f32>() < 0.05)
|
.until(|_| rand::random::<f32>() < 0.05)
|
||||||
.for_each(|pos| block_change.set(pos, Block::empty()))
|
.for_each(|pos| {
|
||||||
|
if terrain
|
||||||
|
.get(pos)
|
||||||
|
.map(|block| block.is_explodable())
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
block_change.set(pos, Block::empty());
|
||||||
|
}
|
||||||
|
})
|
||||||
.cast();
|
.cast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,13 @@ use common::{
|
|||||||
slot::{self, Slot},
|
slot::{self, Slot},
|
||||||
Pos, MAX_PICKUP_RANGE_SQR,
|
Pos, MAX_PICKUP_RANGE_SQR,
|
||||||
},
|
},
|
||||||
sync::WorldSyncExt,
|
sync::{Uid, WorldSyncExt},
|
||||||
terrain::block::Block,
|
terrain::block::Block,
|
||||||
vol::{ReadVol, Vox},
|
vol::{ReadVol, Vox},
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use specs::{join::Join, world::WorldExt, Builder, Entity as EcsEntity, WriteStorage};
|
use specs::{join::Join, world::WorldExt, Builder, Entity as EcsEntity, WriteStorage};
|
||||||
|
use std::time::Duration;
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
use vek::Vec3;
|
use vek::Vec3;
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ pub fn snuff_lantern(storage: &mut WriteStorage<comp::LightEmitter>, entity: Ecs
|
|||||||
pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::InventoryManip) {
|
pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::InventoryManip) {
|
||||||
let state = server.state_mut();
|
let state = server.state_mut();
|
||||||
let mut dropped_items = Vec::new();
|
let mut dropped_items = Vec::new();
|
||||||
|
let mut thrown_items = Vec::new();
|
||||||
|
|
||||||
match manip {
|
match manip {
|
||||||
comp::InventoryManip::Pickup(uid) => {
|
comp::InventoryManip::Pickup(uid) => {
|
||||||
@ -157,6 +159,29 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
|||||||
maybe_effect = Some(*effect);
|
maybe_effect = Some(*effect);
|
||||||
Some(comp::InventoryUpdateEvent::Consumed(*kind))
|
Some(comp::InventoryUpdateEvent::Consumed(*kind))
|
||||||
},
|
},
|
||||||
|
ItemKind::Throwable { .. } => {
|
||||||
|
if let Some(pos) =
|
||||||
|
state.ecs().read_storage::<comp::Pos>().get(entity)
|
||||||
|
{
|
||||||
|
thrown_items.push((
|
||||||
|
*pos,
|
||||||
|
state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<comp::Vel>()
|
||||||
|
.get(entity)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
state
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<comp::Ori>()
|
||||||
|
.get(entity)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
item,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Some(comp::InventoryUpdateEvent::Used)
|
||||||
|
},
|
||||||
ItemKind::Utility {
|
ItemKind::Utility {
|
||||||
kind: comp::item::Utility::Collar,
|
kind: comp::item::Utility::Collar,
|
||||||
..
|
..
|
||||||
@ -318,6 +343,37 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
|||||||
.with(comp::Vel(vel))
|
.with(comp::Vel(vel))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drop items
|
||||||
|
for (pos, vel, ori, item) in thrown_items {
|
||||||
|
let vel = vel.0
|
||||||
|
+ *ori.0 * 20.0
|
||||||
|
+ Vec3::unit_z() * 15.0
|
||||||
|
+ Vec3::<f32>::zero().map(|_| rand::thread_rng().gen::<f32>() - 0.5) * 4.0;
|
||||||
|
|
||||||
|
let uid = state.read_component_cloned::<Uid>(entity);
|
||||||
|
|
||||||
|
let mut entity = state
|
||||||
|
.create_object(Default::default(), comp::object::Body::Bomb)
|
||||||
|
.with(comp::Pos(pos.0 + Vec3::unit_z() * 0.25))
|
||||||
|
.with(comp::Vel(vel));
|
||||||
|
|
||||||
|
#[allow(clippy::single-match)]
|
||||||
|
match item.kind {
|
||||||
|
item::ItemKind::Throwable {
|
||||||
|
kind: item::Throwable::Bomb,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
entity = entity.with(comp::Object::Bomb {
|
||||||
|
timeout: Duration::from_secs_f32(1.0),
|
||||||
|
owner: uid,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn within_pickup_range(player_position: Option<&Pos>, item_position: Option<&Pos>) -> bool {
|
fn within_pickup_range(player_position: Option<&Pos>, item_position: Option<&Pos>) -> bool {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod entity_sync;
|
pub mod entity_sync;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
pub mod object;
|
||||||
pub mod persistence;
|
pub mod persistence;
|
||||||
pub mod sentinel;
|
pub mod sentinel;
|
||||||
pub mod subscription;
|
pub mod subscription;
|
||||||
@ -32,11 +33,13 @@ pub type PersistenceScheduler = SysScheduler<persistence::Sys>;
|
|||||||
const TERRAIN_SYS: &str = "server_terrain_sys";
|
const TERRAIN_SYS: &str = "server_terrain_sys";
|
||||||
const WAYPOINT_SYS: &str = "waypoint_sys";
|
const WAYPOINT_SYS: &str = "waypoint_sys";
|
||||||
const PERSISTENCE_SYS: &str = "persistence_sys";
|
const PERSISTENCE_SYS: &str = "persistence_sys";
|
||||||
|
const OBJECT_SYS: &str = "object_sys";
|
||||||
|
|
||||||
pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) {
|
pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||||
dispatch_builder.add(terrain::Sys, TERRAIN_SYS, &[]);
|
dispatch_builder.add(terrain::Sys, TERRAIN_SYS, &[]);
|
||||||
dispatch_builder.add(waypoint::Sys, WAYPOINT_SYS, &[]);
|
dispatch_builder.add(waypoint::Sys, WAYPOINT_SYS, &[]);
|
||||||
dispatch_builder.add(persistence::Sys, PERSISTENCE_SYS, &[]);
|
dispatch_builder.add(persistence::Sys, PERSISTENCE_SYS, &[]);
|
||||||
|
dispatch_builder.add(object::Sys, OBJECT_SYS, &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_sync_systems(ecs: &mut specs::World) {
|
pub fn run_sync_systems(ecs: &mut specs::World) {
|
||||||
|
51
server/src/sys/object.rs
Normal file
51
server/src/sys/object.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use common::{
|
||||||
|
comp::{HealthSource, Object, PhysicsState, Pos},
|
||||||
|
event::{EventBus, ServerEvent},
|
||||||
|
state::DeltaTime,
|
||||||
|
};
|
||||||
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// This system is responsible for handling projectile effect triggers
|
||||||
|
pub struct Sys;
|
||||||
|
impl<'a> System<'a> for Sys {
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
type SystemData = (
|
||||||
|
Entities<'a>,
|
||||||
|
Read<'a, DeltaTime>,
|
||||||
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
|
ReadStorage<'a, Pos>,
|
||||||
|
ReadStorage<'a, PhysicsState>,
|
||||||
|
WriteStorage<'a, Object>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&mut self,
|
||||||
|
(entities, dt, server_bus, positions, physics_states, mut objects): Self::SystemData,
|
||||||
|
) {
|
||||||
|
let mut server_emitter = server_bus.emitter();
|
||||||
|
|
||||||
|
// Objects
|
||||||
|
for (entity, pos, _physics, object) in
|
||||||
|
(&entities, &positions, &physics_states, &mut objects).join()
|
||||||
|
{
|
||||||
|
match object {
|
||||||
|
Object::Bomb { owner, timeout } => {
|
||||||
|
if let Some(t) = timeout.checked_sub(Duration::from_secs_f32(dt.0)) {
|
||||||
|
*timeout = t;
|
||||||
|
} else {
|
||||||
|
server_emitter.emit(ServerEvent::Destroy {
|
||||||
|
entity,
|
||||||
|
cause: HealthSource::Suicide,
|
||||||
|
});
|
||||||
|
server_emitter.emit(ServerEvent::Explosion {
|
||||||
|
pos: pos.0,
|
||||||
|
power: 4.0,
|
||||||
|
owner: *owner,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ use common::{
|
|||||||
comp::item::{
|
comp::item::{
|
||||||
armor::Armor,
|
armor::Armor,
|
||||||
tool::{Tool, ToolKind},
|
tool::{Tool, ToolKind},
|
||||||
Consumable, Ingredient, Item, ItemKind, Lantern, LanternKind, Utility,
|
Consumable, Ingredient, Item, ItemKind, Lantern, LanternKind, Throwable, Utility,
|
||||||
},
|
},
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
};
|
};
|
||||||
@ -24,6 +24,7 @@ pub enum ItemKey {
|
|||||||
Armor(Armor),
|
Armor(Armor),
|
||||||
Utility(Utility),
|
Utility(Utility),
|
||||||
Consumable(Consumable),
|
Consumable(Consumable),
|
||||||
|
Throwable(Throwable),
|
||||||
Ingredient(Ingredient),
|
Ingredient(Ingredient),
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
@ -35,6 +36,7 @@ impl From<&Item> for ItemKey {
|
|||||||
ItemKind::Armor { kind, .. } => ItemKey::Armor(*kind),
|
ItemKind::Armor { kind, .. } => ItemKey::Armor(*kind),
|
||||||
ItemKind::Utility { kind, .. } => ItemKey::Utility(*kind),
|
ItemKind::Utility { kind, .. } => ItemKey::Utility(*kind),
|
||||||
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(*kind),
|
ItemKind::Consumable { kind, .. } => ItemKey::Consumable(*kind),
|
||||||
|
ItemKind::Throwable { kind, .. } => ItemKey::Throwable(*kind),
|
||||||
ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(*kind),
|
ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(*kind),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ impl SlotKey<Inventory, ItemImgs> for InventorySlot {
|
|||||||
ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None,
|
ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None,
|
||||||
ItemKind::Utility { amount, .. }
|
ItemKind::Utility { amount, .. }
|
||||||
| ItemKind::Consumable { amount, .. }
|
| ItemKind::Consumable { amount, .. }
|
||||||
|
| ItemKind::Throwable { amount, .. }
|
||||||
| ItemKind::Ingredient { amount, .. } => Some(amount),
|
| ItemKind::Ingredient { amount, .. } => Some(amount),
|
||||||
})
|
})
|
||||||
.filter(|amount| *amount > 1)
|
.filter(|amount| *amount > 1)
|
||||||
@ -139,6 +140,7 @@ impl<'a> SlotKey<HotbarSource<'a>, HotbarImageSource<'a>> for HotbarSlot {
|
|||||||
ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None,
|
ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None,
|
||||||
ItemKind::Utility { amount, .. }
|
ItemKind::Utility { amount, .. }
|
||||||
| ItemKind::Consumable { amount, .. }
|
| ItemKind::Consumable { amount, .. }
|
||||||
|
| ItemKind::Throwable { amount, .. }
|
||||||
| ItemKind::Ingredient { amount, .. } => Some(amount),
|
| ItemKind::Ingredient { amount, .. } => Some(amount),
|
||||||
})
|
})
|
||||||
.filter(|amount| *amount > 1)
|
.filter(|amount| *amount > 1)
|
||||||
|
@ -254,22 +254,19 @@ impl<'a> BlockGen<'a> {
|
|||||||
.map(|e| (e * 255.0) as u8);
|
.map(|e| (e * 255.0) as u8);
|
||||||
|
|
||||||
// Underground
|
// Underground
|
||||||
if (wposf.z as f32) > alt - 32.0 * chaos {
|
Some(Block::new(BlockKind::Normal, col))
|
||||||
Some(Block::new(BlockKind::Normal, col))
|
|
||||||
} else {
|
|
||||||
Some(Block::new(BlockKind::Dense, col))
|
|
||||||
}
|
|
||||||
} else if (wposf.z as f32) < height {
|
} else if (wposf.z as f32) < height {
|
||||||
let col = Lerp::lerp(
|
let grass_factor = (wposf.z as f32 - (height - grass_depth))
|
||||||
sub_surface_color,
|
.div(grass_depth)
|
||||||
surface_color,
|
.powf(0.5);
|
||||||
(wposf.z as f32 - (height - grass_depth))
|
let col = Lerp::lerp(sub_surface_color, surface_color, grass_factor);
|
||||||
.div(grass_depth)
|
|
||||||
.powf(0.5),
|
|
||||||
);
|
|
||||||
// Surface
|
// Surface
|
||||||
Some(Block::new(
|
Some(Block::new(
|
||||||
BlockKind::Normal,
|
if grass_factor > 0.7 {
|
||||||
|
BlockKind::Grass
|
||||||
|
} else {
|
||||||
|
BlockKind::Normal
|
||||||
|
},
|
||||||
col.map(|e| (e * 255.0) as u8),
|
col.map(|e| (e * 255.0) as u8),
|
||||||
))
|
))
|
||||||
} else if (wposf.z as f32) < height + 0.9
|
} else if (wposf.z as f32) < height + 0.9
|
||||||
@ -349,7 +346,7 @@ impl<'a> BlockGen<'a> {
|
|||||||
let field2 = RandomField::new(world.seed + 2);
|
let field2 = RandomField::new(world.seed + 2);
|
||||||
|
|
||||||
Some(Block::new(
|
Some(Block::new(
|
||||||
BlockKind::Normal,
|
BlockKind::Rock,
|
||||||
stone_col
|
stone_col
|
||||||
- Rgb::new(
|
- Rgb::new(
|
||||||
field0.get(wpos) as u8 % 16,
|
field0.get(wpos) as u8 % 16,
|
||||||
@ -596,7 +593,7 @@ pub fn block_from_structure(
|
|||||||
StructureBlock::Water => Some(Block::new(BlockKind::Water, Rgb::new(100, 150, 255))),
|
StructureBlock::Water => Some(Block::new(BlockKind::Water, Rgb::new(100, 150, 255))),
|
||||||
StructureBlock::GreenSludge => Some(Block::new(BlockKind::Water, Rgb::new(30, 126, 23))),
|
StructureBlock::GreenSludge => Some(Block::new(BlockKind::Water, Rgb::new(30, 126, 23))),
|
||||||
StructureBlock::Acacia => Some(Block::new(
|
StructureBlock::Acacia => Some(Block::new(
|
||||||
BlockKind::Normal,
|
BlockKind::Leaves,
|
||||||
Lerp::lerp(
|
Lerp::lerp(
|
||||||
Rgb::new(15.0, 126.0, 50.0),
|
Rgb::new(15.0, 126.0, 50.0),
|
||||||
Rgb::new(30.0, 180.0, 10.0),
|
Rgb::new(30.0, 180.0, 10.0),
|
||||||
@ -629,7 +626,7 @@ pub fn block_from_structure(
|
|||||||
.map(|e| e as u8),
|
.map(|e| e as u8),
|
||||||
)),
|
)),
|
||||||
StructureBlock::Mangrove => Some(Block::new(
|
StructureBlock::Mangrove => Some(Block::new(
|
||||||
BlockKind::Normal,
|
BlockKind::Leaves,
|
||||||
Lerp::lerp(Rgb::new(32.0, 56.0, 22.0), Rgb::new(57.0, 69.0, 27.0), lerp)
|
Lerp::lerp(Rgb::new(32.0, 56.0, 22.0), Rgb::new(57.0, 69.0, 27.0), lerp)
|
||||||
.map(|e| e as u8),
|
.map(|e| e as u8),
|
||||||
)),
|
)),
|
||||||
|
Loading…
Reference in New Issue
Block a user