From 40ff4923dc0fdaa95087640f6e18739ee00d5e9b Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 5 Jul 2020 00:55:13 +0100 Subject: [PATCH 1/5] Added bombs, throwable items, more block kinds, weaker explosions --- CHANGELOG.md | 2 + assets/common/items/bomb.ron | 7 +++ assets/voxygen/item_image_manifest.ron | 35 ++++++++------ common/src/comp/inventory/item/mod.rs | 23 ++++++---- common/src/comp/inventory/mod.rs | 44 ++++++++++++++++++ common/src/comp/misc.rs | 16 +++++++ common/src/comp/mod.rs | 2 + common/src/state.rs | 1 + common/src/terrain/block.rs | 11 ++++- server/src/events/entity_manipulation.rs | 14 ++++-- server/src/events/inventory_manip.rs | 58 +++++++++++++++++++++++- server/src/sys/mod.rs | 3 ++ server/src/sys/object.rs | 51 +++++++++++++++++++++ voxygen/src/hud/item_imgs.rs | 4 +- voxygen/src/hud/slots.rs | 2 + world/src/block/mod.rs | 29 ++++++------ 16 files changed, 256 insertions(+), 46 deletions(-) create mode 100644 assets/common/items/bomb.ron create mode 100644 common/src/comp/misc.rs create mode 100644 server/src/sys/object.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c20a476054..1d78c775b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 - Added new animals - Better pathfinding +- Bombs ### 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 - Connection screen fails after 4 minutes if it can't connect to the server instead of 80 minutes - Rebuilt quadruped_medium animation and assets +- Disabled destruction of most blocks by explosions ### Removed diff --git a/assets/common/items/bomb.ron b/assets/common/items/bomb.ron new file mode 100644 index 0000000000..bfe33b06b9 --- /dev/null +++ b/assets/common/items/bomb.ron @@ -0,0 +1,7 @@ +Item( + name: "Bomb", + description: "Boom!\n\n", + kind: Throwable( + kind: Bomb, + ), +) diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index ddd80ea625..6363740403 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -200,7 +200,7 @@ Tool(Staff(Sceptre)): VoxTrans( "voxel.weapon.staff.wood-nature", (1.0, -1.0, 0.0), (-310., 90.0, 0.0), 1.2, - ), + ), // Shields Tool(Shield(BasicShield)): VoxTrans( "voxel.weapon.shield.wood-0", @@ -219,11 +219,11 @@ Lantern(Red0): Png( "element.icons.lantern_red-0", ), - // Farming Equipment + // Farming Equipment Tool(Farming(Broom)): VoxTrans( "voxel.weapon.tool.broom-0", (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1, - ), + ), Tool(Farming(Hoe0)): VoxTrans( "voxel.weapon.tool.hoe_green", (0.0, 0.0, 0.0), (130.0, 35.0, 180.0), 1.0, @@ -231,7 +231,7 @@ Tool(Farming(Hoe1)): VoxTrans( "voxel.weapon.tool.hoe_blue", (0.0, 0.0, 0.0), (130.0, 35.0, 180.0), 1.0, - ), + ), Tool(Farming(Pitchfork)): VoxTrans( "voxel.weapon.tool.pitchfork-0", (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1, @@ -255,7 +255,7 @@ Tool(Farming(Shovel0)): VoxTrans( "voxel.weapon.tool.shovel_green", (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2, - ), + ), Tool(Farming(Shovel1)): VoxTrans( "voxel.weapon.tool.shovel_gold", (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2, @@ -264,7 +264,7 @@ // Other Utility(Collar): Png( "element.icons.collar", - ), + ), // Armor // Starter Parts Armor(Foot(Sandal0)): VoxTrans( @@ -311,7 +311,7 @@ Armor(Pants(CultistBlue)): VoxTrans( "voxel.armor.pants.cultist", (0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2, - ), + ), Armor(Hand(CultistBlue)): VoxTrans( "voxel.armor.hand.cultist_right", (0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0, @@ -680,7 +680,7 @@ Armor(Shoulder(LeafyShoulder)): VoxTrans( "voxel.armor.shoulder.twigsleaves_shoulder_right", (0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2, - ), + ), //TwigsFlowers Set Armor(Chest(Twigsflowers)): VoxTrans( "voxel.armor.chest.twigsflowers_chest", @@ -710,7 +710,7 @@ Armor(Pants(Hunting)): VoxTrans( "voxel.armor.pants.grayscale", (0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2, - ), + ), // Backs Armor(Back(Short0)): VoxTrans( "voxel.armor.back.short-0", @@ -722,15 +722,15 @@ ), // Rings Armor(Ring(Ring0)): Png( - "element.icons.ring-0", + "element.icons.ring-0", ), // Necks Armor(Neck(Neck0)): Png( - "element.icons.neck-0", + "element.icons.neck-0", ), // Tabards Armor(Tabard(Admin)): Png( - "element.icons.tabard_admin", + "element.icons.tabard_admin", ), // Heads Armor(Head(Leather0)): VoxTrans( @@ -746,7 +746,7 @@ VoxTrans( "element.icons.item_apple", (0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 1.0, - ), + ), Consumable(Coconut): Png( "element.icons.item_coconut", ), @@ -761,7 +761,7 @@ Consumable(Cheese): VoxTrans( "element.icons.item_cheese", (0.0, 0.0, 0.0), (-90.0, 90.0, 0.0), 0.9, - ), + ), Consumable(Potion): VoxTrans( "voxel.object.potion_red", (0.0, 0.0, 0.0), (-50.0, 30.0, 20.0), 1.0, @@ -777,6 +777,11 @@ Consumable(VeloriteFrag): VoxTrans( "voxel.sprite.velorite.velorite_1", (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 Ingredient(Flower): VoxTrans( @@ -791,5 +796,5 @@ Tool(Debug(Boost)): VoxTrans( "voxel.weapon.tool.broom_belzeshrub_purple", (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.1, - ), + ), }) diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index 4e1ea47338..fd90138a0c 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -28,6 +28,11 @@ pub enum Consumable { PotionExp, } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Throwable { + Bomb, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Utility { Collar, @@ -86,6 +91,11 @@ pub enum ItemKind { #[serde(default = "default_amount")] amount: u32, }, + Throwable { + kind: Throwable, + #[serde(default = "default_amount")] + amount: u32, + }, Utility { kind: Utility, #[serde(default = "default_amount")] @@ -129,15 +139,10 @@ impl Item { pub fn set_amount(&mut self, give_amount: u32) -> Result<(), assets::Error> { use ItemKind::*; match self.kind { - Consumable { ref mut amount, .. } => { - *amount = give_amount; - Ok(()) - }, - Utility { ref mut amount, .. } => { - *amount = give_amount; - Ok(()) - }, - Ingredient { ref mut amount, .. } => { + Consumable { ref mut amount, .. } + | Throwable { ref mut amount, .. } + | Utility { ref mut amount, .. } + | Ingredient { ref mut amount, .. } => { *amount = give_amount; Ok(()) }, diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 4ff88d819b..0bbfa14d1e 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -102,6 +102,37 @@ impl Inventory { // It didn't work 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 { kind: item_kind, amount: new_amount, @@ -277,6 +308,19 @@ impl Inventory { 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 } => { if *amount <= 1 { self.remove(cell) diff --git a/common/src/comp/misc.rs b/common/src/comp/misc.rs new file mode 100644 index 0000000000..22951df4b8 --- /dev/null +++ b/common/src/comp/misc.rs @@ -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, + }, +} + +impl Component for Object { + type Storage = IDVStorage; +} diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index 809cfcd17d..3efd7e9381 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -10,6 +10,7 @@ mod inputs; mod inventory; mod last; mod location; +mod misc; mod phys; mod player; pub mod projectile; @@ -40,6 +41,7 @@ pub use inventory::{ }; pub use last::Last; pub use location::{Waypoint, WaypointArea}; +pub use misc::Object; pub use phys::{Collider, ForceUpdate, Gravity, Mass, Ori, PhysicsState, Pos, Scale, Sticky, Vel}; pub use player::Player; pub use projectile::Projectile; diff --git a/common/src/state.rs b/common/src/state.rs index ce8834a179..99792738ef 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -122,6 +122,7 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); + ecs.register::(); // Register components send from clients -> server ecs.register::(); diff --git a/common/src/terrain/block.rs b/common/src/terrain/block.rs index 2b8b96a174..c80a7e3bf4 100644 --- a/common/src/terrain/block.rs +++ b/common/src/terrain/block.rs @@ -9,6 +9,9 @@ pub enum BlockKind { Air, Normal, Dense, + Rock, + Grass, + Leaves, Water, LargeCactus, BarrelCactus, @@ -32,7 +35,6 @@ pub enum BlockKind { Velorite, VeloriteFrag, Chest, - Leaves, Pumpkin, Welwitch, 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` pub fn get_height(&self) -> f32 { // Beware: the height *must* be <= `MAX_HEIGHT` or the collision system will not diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 1bb3934325..0e77c1f000 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -292,11 +292,19 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti ) .normalized(); - let _ = ecs - .read_resource::() + let terrain = ecs.read_resource::(); + let _ = terrain .ray(pos, pos + dir * power) .until(|_| rand::random::() < 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(); } } diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 236573bbe8..86cbf38ffb 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -5,12 +5,13 @@ use common::{ slot::{self, Slot}, Pos, MAX_PICKUP_RANGE_SQR, }, - sync::WorldSyncExt, + sync::{Uid, WorldSyncExt}, terrain::block::Block, vol::{ReadVol, Vox}, }; use rand::Rng; use specs::{join::Join, world::WorldExt, Builder, Entity as EcsEntity, WriteStorage}; +use std::time::Duration; use tracing::{debug, error}; use vek::Vec3; @@ -33,6 +34,7 @@ pub fn snuff_lantern(storage: &mut WriteStorage, entity: Ecs pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::InventoryManip) { let state = server.state_mut(); let mut dropped_items = Vec::new(); + let mut thrown_items = Vec::new(); match manip { comp::InventoryManip::Pickup(uid) => { @@ -157,6 +159,29 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv maybe_effect = Some(*effect); Some(comp::InventoryUpdateEvent::Consumed(*kind)) }, + ItemKind::Throwable { .. } => { + if let Some(pos) = + state.ecs().read_storage::().get(entity) + { + thrown_items.push(( + *pos, + state + .ecs() + .read_storage::() + .get(entity) + .copied() + .unwrap_or_default(), + state + .ecs() + .read_storage::() + .get(entity) + .copied() + .unwrap_or_default(), + item, + )); + } + Some(comp::InventoryUpdateEvent::Used) + }, ItemKind::Utility { 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)) .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::::zero().map(|_| rand::thread_rng().gen::() - 0.5) * 4.0; + + let uid = state.read_component_cloned::(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 { diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 41a7227bb2..252c05591a 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -1,5 +1,6 @@ pub mod entity_sync; pub mod message; +pub mod object; pub mod persistence; pub mod sentinel; pub mod subscription; @@ -32,11 +33,13 @@ pub type PersistenceScheduler = SysScheduler; const TERRAIN_SYS: &str = "server_terrain_sys"; const WAYPOINT_SYS: &str = "waypoint_sys"; const PERSISTENCE_SYS: &str = "persistence_sys"; +const OBJECT_SYS: &str = "object_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(terrain::Sys, TERRAIN_SYS, &[]); dispatch_builder.add(waypoint::Sys, WAYPOINT_SYS, &[]); dispatch_builder.add(persistence::Sys, PERSISTENCE_SYS, &[]); + dispatch_builder.add(object::Sys, OBJECT_SYS, &[]); } pub fn run_sync_systems(ecs: &mut specs::World) { diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs new file mode 100644 index 0000000000..36ed8371eb --- /dev/null +++ b/server/src/sys/object.rs @@ -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>, + 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, + }); + } + }, + } + } + } +} diff --git a/voxygen/src/hud/item_imgs.rs b/voxygen/src/hud/item_imgs.rs index e6383e0c81..8661e911fe 100644 --- a/voxygen/src/hud/item_imgs.rs +++ b/voxygen/src/hud/item_imgs.rs @@ -4,7 +4,7 @@ use common::{ comp::item::{ armor::Armor, tool::{Tool, ToolKind}, - Consumable, Ingredient, Item, ItemKind, Lantern, LanternKind, Utility, + Consumable, Ingredient, Item, ItemKind, Lantern, LanternKind, Throwable, Utility, }, figure::Segment, }; @@ -24,6 +24,7 @@ pub enum ItemKey { Armor(Armor), Utility(Utility), Consumable(Consumable), + Throwable(Throwable), Ingredient(Ingredient), Empty, } @@ -35,6 +36,7 @@ impl From<&Item> for ItemKey { ItemKind::Armor { kind, .. } => ItemKey::Armor(*kind), ItemKind::Utility { kind, .. } => ItemKey::Utility(*kind), ItemKind::Consumable { kind, .. } => ItemKey::Consumable(*kind), + ItemKind::Throwable { kind, .. } => ItemKey::Throwable(*kind), ItemKind::Ingredient { kind, .. } => ItemKey::Ingredient(*kind), } } diff --git a/voxygen/src/hud/slots.rs b/voxygen/src/hud/slots.rs index 19f17ceea4..b8279eaf3f 100644 --- a/voxygen/src/hud/slots.rs +++ b/voxygen/src/hud/slots.rs @@ -42,6 +42,7 @@ impl SlotKey for InventorySlot { ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None, ItemKind::Utility { amount, .. } | ItemKind::Consumable { amount, .. } + | ItemKind::Throwable { amount, .. } | ItemKind::Ingredient { amount, .. } => Some(amount), }) .filter(|amount| *amount > 1) @@ -139,6 +140,7 @@ impl<'a> SlotKey, HotbarImageSource<'a>> for HotbarSlot { ItemKind::Tool { .. } | ItemKind::Lantern(_) | ItemKind::Armor { .. } => None, ItemKind::Utility { amount, .. } | ItemKind::Consumable { amount, .. } + | ItemKind::Throwable { amount, .. } | ItemKind::Ingredient { amount, .. } => Some(amount), }) .filter(|amount| *amount > 1) diff --git a/world/src/block/mod.rs b/world/src/block/mod.rs index f00f615297..5f1479f48e 100644 --- a/world/src/block/mod.rs +++ b/world/src/block/mod.rs @@ -254,22 +254,19 @@ impl<'a> BlockGen<'a> { .map(|e| (e * 255.0) as u8); // Underground - if (wposf.z as f32) > alt - 32.0 * chaos { - Some(Block::new(BlockKind::Normal, col)) - } else { - Some(Block::new(BlockKind::Dense, col)) - } + Some(Block::new(BlockKind::Normal, col)) } else if (wposf.z as f32) < height { - let col = Lerp::lerp( - sub_surface_color, - surface_color, - (wposf.z as f32 - (height - grass_depth)) - .div(grass_depth) - .powf(0.5), - ); + let grass_factor = (wposf.z as f32 - (height - grass_depth)) + .div(grass_depth) + .powf(0.5); + let col = Lerp::lerp(sub_surface_color, surface_color, grass_factor); // Surface Some(Block::new( - BlockKind::Normal, + if grass_factor > 0.7 { + BlockKind::Grass + } else { + BlockKind::Normal + }, col.map(|e| (e * 255.0) as u8), )) } else if (wposf.z as f32) < height + 0.9 @@ -349,7 +346,7 @@ impl<'a> BlockGen<'a> { let field2 = RandomField::new(world.seed + 2); Some(Block::new( - BlockKind::Normal, + BlockKind::Rock, stone_col - Rgb::new( 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::GreenSludge => Some(Block::new(BlockKind::Water, Rgb::new(30, 126, 23))), StructureBlock::Acacia => Some(Block::new( - BlockKind::Normal, + BlockKind::Leaves, Lerp::lerp( Rgb::new(15.0, 126.0, 50.0), Rgb::new(30.0, 180.0, 10.0), @@ -629,7 +626,7 @@ pub fn block_from_structure( .map(|e| e as u8), )), 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) .map(|e| e as u8), )), From d5e0a7d3518a15b7603a4991a602715cd34f2c04 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 5 Jul 2020 01:08:52 +0100 Subject: [PATCH 2/5] Added bombs to loot table --- assets/common/items/bomb_pile.ron | 8 ++++++++ assets/common/loot_table.ron | 8 +++++++- server/src/events/inventory_manip.rs | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 assets/common/items/bomb_pile.ron diff --git a/assets/common/items/bomb_pile.ron b/assets/common/items/bomb_pile.ron new file mode 100644 index 0000000000..84577dced8 --- /dev/null +++ b/assets/common/items/bomb_pile.ron @@ -0,0 +1,8 @@ +Item( + name: "Bomb", + description: "Boom!\n\n", + kind: Throwable( + kind: Bomb, + amount: 10, + ), +) diff --git a/assets/common/loot_table.ron b/assets/common/loot_table.ron index 089f042417..17891fbf7b 100644 --- a/assets/common/loot_table.ron +++ b/assets/common/loot_table.ron @@ -1,10 +1,16 @@ [ // All loot rates go here + // food + (3, "common.items.cheese"), + (3, "common.items.apple"), + (3, "common.items.mushroom"), // miscellaneous (0.4, "common.items.velorite"), (0.6, "common.items.veloritefrag"), (1.5, "common.items.potion_minor"), - (1, "common.items.collar"), + (0.5, "common.items.collar"), + (0.5, "common.items.bomb_pile"), + (1, "common.items.bomb"), // swords (0.1, "common.items.weapons.sword.starter_sword"), (0.1, "common.items.weapons.sword.wood_sword"), diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 86cbf38ffb..d0d857c89e 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -358,7 +358,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .with(comp::Pos(pos.0 + Vec3::unit_z() * 0.25)) .with(comp::Vel(vel)); - #[allow(clippy::single-match)] + #[allow(clippy::single_match)] match item.kind { item::ItemKind::Throwable { kind: item::Throwable::Bomb, From a0b3c4e9a48647465b3559179905ed3ea1c4a25d Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 5 Jul 2020 11:13:16 +0100 Subject: [PATCH 3/5] Made fluids block explosions --- server/src/events/entity_manipulation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 0e77c1f000..f67770cc87 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -295,7 +295,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti let terrain = ecs.read_resource::(); let _ = terrain .ray(pos, pos + dir * power) - .until(|_| rand::random::() < 0.05) + .until(|block| block.is_fluid() || rand::random::() < 0.05) .for_each(|pos| { if terrain .get(pos) From 4da106aec140d0f073a5a8e7b800f188241e971e Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 5 Jul 2020 13:39:28 +0100 Subject: [PATCH 4/5] Added training dummies --- CHANGELOG.md | 1 + assets/common/items/training_dummy.ron | 7 +++++ assets/voxygen/item_image_manifest.ron | 6 +++- common/src/comp/body/object.rs | 4 +++ common/src/comp/inventory/item/mod.rs | 1 + common/src/event.rs | 2 +- common/src/generation.rs | 11 +++++-- common/src/ray.rs | 16 ++++++---- common/src/sys/combat.rs | 4 +-- common/src/sys/stats.rs | 15 ++++++--- common/src/vol.rs | 2 +- server/src/events/entity_creation.rs | 9 ++++-- server/src/events/entity_manipulation.rs | 14 +++------ server/src/events/inventory_manip.rs | 39 +++++++++++++----------- server/src/state_ext.rs | 2 +- server/src/sys/mod.rs | 6 ++-- server/src/sys/object.rs | 2 +- server/src/sys/terrain.rs | 6 +++- voxygen/src/hud/mod.rs | 2 +- voxygen/src/hud/overhead.rs | 36 ++++++++++++---------- world/src/site/settlement/mod.rs | 15 +++++++-- 21 files changed, 128 insertions(+), 72 deletions(-) create mode 100644 assets/common/items/training_dummy.ron diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d78c775b6..59e3321783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new animals - Better pathfinding - Bombs +- Training dummies ### Changed diff --git a/assets/common/items/training_dummy.ron b/assets/common/items/training_dummy.ron new file mode 100644 index 0000000000..9e9a4bd22a --- /dev/null +++ b/assets/common/items/training_dummy.ron @@ -0,0 +1,7 @@ +Item( + name: "Training Dummy", + description: "His name is William. Fire at will.\n\n", + kind: Throwable( + kind: TrainingDummy, + ), +) diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 6363740403..68c68ffc4f 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -778,11 +778,15 @@ "voxel.sprite.velorite.velorite_1", (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, ), - // Throwables + // Throwables Throwable(Bomb): VoxTrans( "voxel.object.bomb", (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, ), + Throwable(TrainingDummy): VoxTrans( + "voxel.object.training_dummy", + (0.0, -1.0, 0.0), (-50.0, 40.0, 20.0), 0.8, + ), // Ingredients Ingredient(Flower): VoxTrans( "voxel.sprite.flowers.flower_red_2", diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index f98f1bdb92..865c4992e5 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -123,6 +123,10 @@ pub const ALL_OBJECTS: [Body; 54] = [ Body::TrainingDummy, ]; +impl From for super::Body { + fn from(body: Body) -> Self { super::Body::Object(body) } +} + impl Body { pub fn to_string(&self) -> &str { match self { diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index fd90138a0c..72218b795b 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -31,6 +31,7 @@ pub enum Consumable { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Throwable { Bomb, + TrainingDummy, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/common/src/event.rs b/common/src/event.rs index 47a6e34df8..7bcb6683db 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -70,7 +70,7 @@ pub enum ServerEvent { stats: comp::Stats, loadout: comp::Loadout, body: comp::Body, - agent: comp::Agent, + agent: Option, alignment: comp::Alignment, scale: comp::Scale, drop_item: Option, diff --git a/common/src/generation.rs b/common/src/generation.rs index 3edd331c24..cb285faf1d 100644 --- a/common/src/generation.rs +++ b/common/src/generation.rs @@ -12,6 +12,7 @@ pub struct EntityInfo { pub pos: Vec3, pub is_waypoint: bool, // Edge case, overrides everything else pub is_giant: bool, + pub has_agency: bool, pub alignment: Alignment, pub body: Body, pub name: Option, @@ -28,6 +29,7 @@ impl EntityInfo { pos, is_waypoint: false, is_giant: false, + has_agency: true, alignment: Alignment::Wild, body: Body::Humanoid(humanoid::Body::random()), name: None, @@ -66,8 +68,13 @@ impl EntityInfo { self } - pub fn with_name(mut self, name: String) -> Self { - self.name = Some(name); + pub fn with_name(mut self, name: impl Into) -> Self { + self.name = Some(name.into()); + self + } + + pub fn with_agency(mut self, agency: bool) -> Self { + self.has_agency = agency; self } diff --git a/common/src/ray.rs b/common/src/ray.rs index 86b0e51a18..f0e412975e 100644 --- a/common/src/ray.rs +++ b/common/src/ray.rs @@ -2,9 +2,9 @@ use crate::vol::{ReadVol, Vox}; use vek::*; pub trait RayUntil = FnMut(&V) -> bool; -pub trait RayForEach = FnMut(Vec3); +pub trait RayForEach = FnMut(&V, Vec3); -pub struct Ray<'a, V: ReadVol, F: RayUntil, G: RayForEach> { +pub struct Ray<'a, V: ReadVol, F: RayUntil, G: RayForEach> { vol: &'a V, from: Vec3, to: Vec3, @@ -14,7 +14,7 @@ pub struct Ray<'a, V: ReadVol, F: RayUntil, G: RayForEach> { ignore_error: bool, } -impl<'a, V: ReadVol, F: RayUntil, G: RayForEach> Ray<'a, V, F, G> { +impl<'a, V: ReadVol, F: RayUntil, G: RayForEach> Ray<'a, V, F, G> { pub fn new(vol: &'a V, from: Vec3, to: Vec3, until: F) -> Self { Self { vol, @@ -29,7 +29,7 @@ impl<'a, V: ReadVol, F: RayUntil, G: RayForEach> Ray<'a, V, F, G> { pub fn until(self, f: F) -> Ray<'a, V, F, G> { Ray { until: f, ..self } } - pub fn for_each(self, f: H) -> Ray<'a, V, F, H> { + pub fn for_each>(self, f: H) -> Ray<'a, V, F, H> { Ray { for_each: Some(f), vol: self.vol, @@ -69,12 +69,16 @@ impl<'a, V: ReadVol, F: RayUntil, G: RayForEach> Ray<'a, V, F, G> { break; } + let vox = self.vol.get(ipos); + // for_each if let Some(g) = &mut self.for_each { - g(ipos); + if let Ok(vox) = vox { + g(vox, ipos); + } } - match self.vol.get(ipos).map(|vox| (vox, (self.until)(vox))) { + match vox.map(|vox| (vox, (self.until)(vox))) { Ok((vox, true)) => return (dist, Ok(Some(vox))), Err(err) if !self.ignore_error => return (dist, Err(err)), _ => {}, diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index ee7ac80143..910c87e5f5 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -85,7 +85,7 @@ impl<'a> System<'a> for Sys { &orientations, scales.maybe(), agents.maybe(), - &character_states, + character_states.maybe(), &stats, &bodies, ) @@ -129,7 +129,7 @@ impl<'a> System<'a> for Sys { } // Block - if character_b.is_block() + if character_b.map(|c_b| c_b.is_block()).unwrap_or(false) && ori_b.0.angle_between(pos.0 - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0 { healthchange *= 1.0 - BLOCK_EFFICIENCY diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index af95d1cc98..28045e8313 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -33,13 +33,10 @@ impl<'a> System<'a> for Sys { } stats.set_event_emission(true); - // Mutates all stats every tick causing the server to resend this component for - // every entity every tick - for (entity, character_state, mut stats, mut energy) in ( + // Update stats + for (entity, mut stats) in ( &entities, - &character_states, &mut stats.restrict_mut(), - &mut energies.restrict_mut(), ) .join() { @@ -74,7 +71,15 @@ impl<'a> System<'a> for Sys { stat.health .set_to(stat.health.maximum(), HealthSource::LevelUp); } + } + // Update energies + for (character_state, mut energy) in ( + &character_states, + &mut energies.restrict_mut(), + ) + .join() + { match character_state { // Accelerate recharging energy. CharacterState::Idle { .. } diff --git a/common/src/vol.rs b/common/src/vol.rs index 2fc3fb54cc..210779c8d6 100644 --- a/common/src/vol.rs +++ b/common/src/vol.rs @@ -102,7 +102,7 @@ pub trait ReadVol: BaseVol { &'a self, from: Vec3, to: Vec3, - ) -> Ray<'a, Self, fn(&Self::Vox) -> bool, fn(Vec3)> + ) -> Ray<'a, Self, fn(&Self::Vox) -> bool, fn(&Self::Vox, Vec3)> where Self: Sized, { diff --git a/server/src/events/entity_creation.rs b/server/src/events/entity_creation.rs index b695c20779..fb8606e37a 100644 --- a/server/src/events/entity_creation.rs +++ b/server/src/events/entity_creation.rs @@ -31,7 +31,7 @@ pub fn handle_create_npc( stats: Stats, loadout: Loadout, body: Body, - agent: Agent, + agent: impl Into>, alignment: Alignment, scale: Scale, drop_item: Option, @@ -39,10 +39,15 @@ pub fn handle_create_npc( let entity = server .state .create_npc(pos, stats, loadout, body) - .with(agent) .with(scale) .with(alignment); + let entity = if let Some(agent) = agent.into() { + entity.with(agent) + } else { + entity + }; + let entity = if let Some(drop_item) = drop_item { entity.with(ItemDrop(drop_item)) } else { diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index f67770cc87..423b707753 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -211,7 +211,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti for (pos_b, ori_b, character_b, stats_b) in ( &ecs.read_storage::(), &ecs.read_storage::(), - &ecs.read_storage::(), + ecs.read_storage::().maybe(), &mut ecs.write_storage::(), ) .join() @@ -231,7 +231,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti } // Block - if character_b.is_block() + if character_b.map(|c_b| c_b.is_block()).unwrap_or(false) && ori_b.0.angle_between(pos - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0 { dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as u32 @@ -261,7 +261,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti .read_resource::() .ray(pos, pos + dir * color_range) .until(|_| rand::random::() < 0.05) - .for_each(|pos| touched_blocks.push(pos)) + .for_each(|_: &Block, pos| touched_blocks.push(pos)) .cast(); } @@ -296,12 +296,8 @@ pub fn handle_explosion(server: &Server, pos: Vec3, power: f32, owner: Opti let _ = terrain .ray(pos, pos + dir * power) .until(|block| block.is_fluid() || rand::random::() < 0.05) - .for_each(|pos| { - if terrain - .get(pos) - .map(|block| block.is_explodable()) - .unwrap_or(false) - { + .for_each(|block: &Block, pos| { + if block.is_explodable() { block_change.set(pos, Block::empty()); } }) diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index d0d857c89e..4254e196f4 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -159,7 +159,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv maybe_effect = Some(*effect); Some(comp::InventoryUpdateEvent::Consumed(*kind)) }, - ItemKind::Throwable { .. } => { + ItemKind::Throwable { kind, .. } => { if let Some(pos) = state.ecs().read_storage::().get(entity) { @@ -177,7 +177,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .get(entity) .copied() .unwrap_or_default(), - item, + kind.clone(), )); } Some(comp::InventoryUpdateEvent::Used) @@ -344,8 +344,8 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .build(); } - // Drop items - for (pos, vel, ori, item) in thrown_items { + // Throw items + for (pos, vel, ori, kind) in thrown_items { let vel = vel.0 + *ori.0 * 20.0 + Vec3::unit_z() * 15.0 @@ -353,26 +353,31 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv let uid = state.read_component_cloned::(entity); - let mut entity = state - .create_object(Default::default(), comp::object::Body::Bomb) + let mut new_entity = state + .create_object(Default::default(), match kind { + item::Throwable::Bomb => comp::object::Body::Bomb, + item::Throwable::TrainingDummy => comp::object::Body::TrainingDummy, + }) .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 { + match kind { + item::Throwable::Bomb => { + new_entity = new_entity.with(comp::Object::Bomb { timeout: Duration::from_secs_f32(1.0), owner: uid, - }) + }); }, - _ => {}, - } + item::Throwable::TrainingDummy => { + new_entity = new_entity + .with(comp::Stats::new( + "Training Dummy".to_string(), + comp::object::Body::TrainingDummy.into(), + )); + }, + }; - entity.build(); + new_entity.build(); } } diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index ad9ca3f5e1..20a7baac5d 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -128,7 +128,7 @@ impl StateExt for State { .with(comp::Vel(Vec3::zero())) .with(comp::Ori::default()) .with(comp::Body::Object(object)) - .with(comp::Mass(100.0)) + .with(comp::Mass(5.0)) .with(comp::Collider::Box { radius: 0.4, z_min: 0.0, diff --git a/server/src/sys/mod.rs b/server/src/sys/mod.rs index 252c05591a..5afef7795c 100644 --- a/server/src/sys/mod.rs +++ b/server/src/sys/mod.rs @@ -31,9 +31,9 @@ pub type PersistenceScheduler = SysScheduler; //const SUBSCRIPTION_SYS: &str = "server_subscription_sys"; //const TERRAIN_SYNC_SYS: &str = "server_terrain_sync_sys"; const TERRAIN_SYS: &str = "server_terrain_sys"; -const WAYPOINT_SYS: &str = "waypoint_sys"; -const PERSISTENCE_SYS: &str = "persistence_sys"; -const OBJECT_SYS: &str = "object_sys"; +const WAYPOINT_SYS: &str = "server_waypoint_sys"; +const PERSISTENCE_SYS: &str = "server_persistence_sys"; +const OBJECT_SYS: &str = "server_object_sys"; pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) { dispatch_builder.add(terrain::Sys, TERRAIN_SYS, &[]); diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index 36ed8371eb..3becae6218 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -6,7 +6,7 @@ use common::{ use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; use std::time::Duration; -/// This system is responsible for handling projectile effect triggers +/// This system is responsible for handling misc object behaviours pub struct Sys; impl<'a> System<'a> for Sys { #[allow(clippy::type_complexity)] diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index cdb3fd387d..54d01b0596 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -346,8 +346,12 @@ impl<'a> System<'a> for Sys { stats, loadout, body, + agent: if entity.has_agency { + Some(comp::Agent::new(entity.pos, can_speak)) + } else { + None + }, alignment, - agent: comp::Agent::new(entity.pos, can_speak), scale: comp::Scale(scale), drop_item: entity.loot_drop, }) diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 602ba98fa5..da04cedf2f 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -970,7 +970,7 @@ impl Hud { &pos, interpolated.maybe(), &stats, - &energy, + energy.maybe(), players.maybe(), scales.maybe(), &bodies, diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs index 32204fb527..da74395dd2 100644 --- a/voxygen/src/hud/overhead.rs +++ b/voxygen/src/hud/overhead.rs @@ -54,7 +54,7 @@ pub struct Overhead<'a> { name: &'a str, bubble: Option<&'a SpeechBubble>, stats: &'a Stats, - energy: &'a Energy, + energy: Option<&'a Energy>, own_level: u32, settings: &'a GameplaySettings, pulse: f32, @@ -71,7 +71,7 @@ impl<'a> Overhead<'a> { name: &'a str, bubble: Option<&'a SpeechBubble>, stats: &'a Stats, - energy: &'a Energy, + energy: Option<&'a Energy>, own_level: u32, settings: &'a GameplaySettings, pulse: f32, @@ -297,7 +297,6 @@ impl<'a> Widget for Overhead<'a> { let hp_percentage = self.stats.health.current() as f64 / self.stats.health.maximum() as f64 * 100.0; - let energy_percentage = self.energy.current() as f64 / self.energy.maximum() as f64 * 100.0; let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 1.0; //Animation timer let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani); @@ -325,20 +324,25 @@ impl<'a> Widget for Overhead<'a> { })) .parent(id) .set(state.ids.health_bar, ui); + // % Mana Filling - Rectangle::fill_with( - [ - 72.0 * (self.energy.current() as f64 / self.energy.maximum() as f64) * BARSIZE, - MANA_BAR_HEIGHT, - ], - MANA_COLOR, - ) - .x_y( - ((3.5 + (energy_percentage / 100.0 * 36.5)) - 36.45) * BARSIZE, - MANA_BAR_Y, //-32.0, - ) - .parent(id) - .set(state.ids.mana_bar, ui); + if let Some(energy) = self.energy { + let energy_factor = energy.current() as f64 / energy.maximum() as f64; + + Rectangle::fill_with( + [ + 72.0 * energy_factor * BARSIZE, + MANA_BAR_HEIGHT, + ], + MANA_COLOR, + ) + .x_y( + ((3.5 + (energy_factor * 36.5)) - 36.45) * BARSIZE, + MANA_BAR_Y, //-32.0, + ) + .parent(id) + .set(state.ids.mana_bar, ui); + } // Foreground Image::new(self.imgs.enemy_health) diff --git a/world/src/site/settlement/mod.rs b/world/src/site/settlement/mod.rs index be659d840f..546f81215b 100644 --- a/world/src/site/settlement/mod.rs +++ b/world/src/site/settlement/mod.rs @@ -10,7 +10,7 @@ use crate::{ use common::{ assets, astar::Astar, - comp::{self, bird_medium, humanoid, quadruped_small}, + comp::{self, bird_medium, humanoid, quadruped_small, object}, generation::{ChunkSupplement, EntityInfo}, path::Path, spiral::Spiral2d, @@ -789,8 +789,13 @@ impl Settlement { && RandomField::new(self.seed).chance(Vec3::from(wpos2d), 1.0 / (50.0 * 50.0)) { let is_human: bool; + let is_dummy = RandomField::new(self.seed + 1).chance(Vec3::from(wpos2d), 1.0 / 15.0); let entity = EntityInfo::at(entity_wpos) .with_body(match rng.gen_range(0, 4) { + _ if is_dummy => { + is_human = false; + object::Body::TrainingDummy.into() + }, 0 => { let species = match rng.gen_range(0, 3) { 0 => quadruped_small::Species::Pig, @@ -819,7 +824,10 @@ impl Settlement { comp::Body::Humanoid(humanoid::Body::random()) }, }) - .with_alignment(if is_human { + .with_agency(!is_dummy) + .with_alignment(if is_dummy { + comp::Alignment::Wild + } else if is_human { comp::Alignment::Npc } else { comp::Alignment::Tame @@ -838,7 +846,8 @@ impl Settlement { }, )) }) - .with_automatic_name(); + .do_if(is_dummy, |e| e.with_name("Training Dummy")) + .do_if(!is_dummy, |e| e.with_automatic_name()); supplement.add_entity(entity); } From afcf72d7e9045380caa4827409348a78fe60076e Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sun, 5 Jul 2020 15:06:01 +0100 Subject: [PATCH 5/5] Removed bomb timeout --- CHANGELOG.md | 2 +- common/src/comp/misc.rs | 6 +----- common/src/comp/phys.rs | 9 +++++++++ common/src/sys/phys.rs | 6 +----- common/src/sys/stats.rs | 14 +++----------- server/src/events/inventory_manip.rs | 17 ++++++----------- server/src/sys/object.rs | 11 ++++------- voxygen/src/hud/overhead.rs | 5 +---- world/src/site/settlement/mod.rs | 5 +++-- 9 files changed, 29 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59e3321783..de98e44886 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added new animals - Better pathfinding - Bombs -- Training dummies +- Training dummy items ### Changed diff --git a/common/src/comp/misc.rs b/common/src/comp/misc.rs index 22951df4b8..5135ec67d7 100644 --- a/common/src/comp/misc.rs +++ b/common/src/comp/misc.rs @@ -1,14 +1,10 @@ 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, - }, + Bomb { owner: Option }, } impl Component for Object { diff --git a/common/src/comp/phys.rs b/common/src/comp/phys.rs index 01fe96dc46..61ceaaaf90 100644 --- a/common/src/comp/phys.rs +++ b/common/src/comp/phys.rs @@ -78,6 +78,15 @@ pub struct PhysicsState { pub in_fluid: bool, } +impl PhysicsState { + pub fn on_surface(&self) -> Option> { + self.on_ground + .then_some(-Vec3::unit_z()) + .or_else(|| self.on_ceiling.then_some(Vec3::unit_z())) + .or(self.on_wall) + } +} + impl Component for PhysicsState { type Storage = FlaggedStorage>; } diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index b5a1236d6e..d57ef92df1 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -96,11 +96,7 @@ impl<'a> System<'a> for Sys { { let mut physics_state = physics_states.get(entity).cloned().unwrap_or_default(); - if sticky.is_some() - && (physics_state.on_ground - || physics_state.on_ceiling - || physics_state.on_wall.is_some()) - { + if sticky.is_some() && physics_state.on_surface().is_some() { vel.0 = Vec3::zero(); continue; } diff --git a/common/src/sys/stats.rs b/common/src/sys/stats.rs index 28045e8313..2335c64fce 100644 --- a/common/src/sys/stats.rs +++ b/common/src/sys/stats.rs @@ -34,12 +34,7 @@ impl<'a> System<'a> for Sys { stats.set_event_emission(true); // Update stats - for (entity, mut stats) in ( - &entities, - &mut stats.restrict_mut(), - ) - .join() - { + for (entity, mut stats) in (&entities, &mut stats.restrict_mut()).join() { let (set_dead, level_up) = { let stat = stats.get_unchecked(); ( @@ -74,11 +69,8 @@ impl<'a> System<'a> for Sys { } // Update energies - for (character_state, mut energy) in ( - &character_states, - &mut energies.restrict_mut(), - ) - .join() + for (character_state, mut energy) in + (&character_states, &mut energies.restrict_mut()).join() { match character_state { // Accelerate recharging energy. diff --git a/server/src/events/inventory_manip.rs b/server/src/events/inventory_manip.rs index 4254e196f4..0d6c37839d 100644 --- a/server/src/events/inventory_manip.rs +++ b/server/src/events/inventory_manip.rs @@ -11,7 +11,6 @@ use common::{ }; use rand::Rng; use specs::{join::Join, world::WorldExt, Builder, Entity as EcsEntity, WriteStorage}; -use std::time::Duration; use tracing::{debug, error}; use vek::Vec3; @@ -177,7 +176,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv .get(entity) .copied() .unwrap_or_default(), - kind.clone(), + *kind, )); } Some(comp::InventoryUpdateEvent::Used) @@ -363,17 +362,13 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv match kind { item::Throwable::Bomb => { - new_entity = new_entity.with(comp::Object::Bomb { - timeout: Duration::from_secs_f32(1.0), - owner: uid, - }); + new_entity = new_entity.with(comp::Object::Bomb { owner: uid }); }, item::Throwable::TrainingDummy => { - new_entity = new_entity - .with(comp::Stats::new( - "Training Dummy".to_string(), - comp::object::Body::TrainingDummy.into(), - )); + new_entity = new_entity.with(comp::Stats::new( + "Training Dummy".to_string(), + comp::object::Body::TrainingDummy.into(), + )); }, }; diff --git a/server/src/sys/object.rs b/server/src/sys/object.rs index 3becae6218..be986f8e6e 100644 --- a/server/src/sys/object.rs +++ b/server/src/sys/object.rs @@ -4,7 +4,6 @@ use common::{ state::DeltaTime, }; use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage}; -use std::time::Duration; /// This system is responsible for handling misc object behaviours pub struct Sys; @@ -21,19 +20,17 @@ impl<'a> System<'a> for Sys { fn run( &mut self, - (entities, dt, server_bus, positions, physics_states, mut objects): Self::SystemData, + (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 + 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 { + Object::Bomb { owner } => { + if physics.on_surface().is_some() { server_emitter.emit(ServerEvent::Destroy { entity, cause: HealthSource::Suicide, diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs index da74395dd2..ad551d7281 100644 --- a/voxygen/src/hud/overhead.rs +++ b/voxygen/src/hud/overhead.rs @@ -330,10 +330,7 @@ impl<'a> Widget for Overhead<'a> { let energy_factor = energy.current() as f64 / energy.maximum() as f64; Rectangle::fill_with( - [ - 72.0 * energy_factor * BARSIZE, - MANA_BAR_HEIGHT, - ], + [72.0 * energy_factor * BARSIZE, MANA_BAR_HEIGHT], MANA_COLOR, ) .x_y( diff --git a/world/src/site/settlement/mod.rs b/world/src/site/settlement/mod.rs index 546f81215b..7571df7aab 100644 --- a/world/src/site/settlement/mod.rs +++ b/world/src/site/settlement/mod.rs @@ -10,7 +10,7 @@ use crate::{ use common::{ assets, astar::Astar, - comp::{self, bird_medium, humanoid, quadruped_small, object}, + comp::{self, bird_medium, humanoid, object, quadruped_small}, generation::{ChunkSupplement, EntityInfo}, path::Path, spiral::Spiral2d, @@ -789,7 +789,8 @@ impl Settlement { && RandomField::new(self.seed).chance(Vec3::from(wpos2d), 1.0 / (50.0 * 50.0)) { let is_human: bool; - let is_dummy = RandomField::new(self.seed + 1).chance(Vec3::from(wpos2d), 1.0 / 15.0); + let is_dummy = + RandomField::new(self.seed + 1).chance(Vec3::from(wpos2d), 1.0 / 15.0); let entity = EntityInfo::at(entity_wpos) .with_body(match rng.gen_range(0, 4) { _ if is_dummy => {