Merge branch 'combat' of https://gitlab.com/veloren/veloren into combat

This commit is contained in:
jshipsey 2020-03-22 11:55:35 -04:00
commit 5a04e37f67
49 changed files with 246 additions and 116 deletions

BIN
.DS_Store vendored

Binary file not shown.

@ -2,7 +2,7 @@ Item(
name: "Blue Linen Skirt",
description: "WIP",
kind: Armor(
kind: Belt(ClothBlue0),
kind: Pants(ClothBlue0),
stats: 20,
),
)

@ -2,7 +2,7 @@ Item(
name: "Green Linen Skirt",
description: "WIP",
kind: Armor(
kind: Belt(ClothGreen0),
kind: Pants(ClothGreen0),
stats: 20,
),
)

@ -2,7 +2,7 @@ Item(
name: "Purple Linen Skirt",
description: "WIP",
kind: Armor(
kind: Belt(ClothPurple0),
kind: Pants(ClothPurple0),
stats: 20,
),
)

@ -2,7 +2,7 @@ Item(
name: "Blue Linen Coat",
description: "WIP",
kind: Armor(
kind: Belt(ClothBlue0),
kind: Shoulder(ClothBlue0),
stats: 20,
),
)

@ -2,7 +2,7 @@ Item(
name: "Green Linen Coat",
description: "WIP",
kind: Armor(
kind: Belt(ClothGreen0),
kind: Shoulder(ClothGreen0),
stats: 20,
),
)
)

@ -2,7 +2,7 @@ Item(
name: "Purple Linen Coat",
description: "WIP",
kind: Armor(
kind: Belt(ClothPurple0),
kind: Shoulder(ClothPurple0),
stats: 20,
),
)
)

@ -192,7 +192,7 @@ Enjoy your stay in the World of Veloren."#,
// Inventory
"hud.bag.inventory": "'s Inventory",
"hud.bag.inventory": "'s Inventory",
"hud.bag.stats": "'s Stats",
"hud.bag.exp": "Exp",
// Settings

@ -74,11 +74,11 @@
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(Assassin)): VoxTrans(
"voxel.armor.hand.assa_left",
"voxel.armor.hand.assa_right",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(Assassin)): VoxTrans(
"voxel.armor.shoulder.assa_left",
"voxel.armor.shoulder.assa_right",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
// Starting Armor - Plate
@ -99,15 +99,15 @@
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(Plate0)): VoxTrans(
"voxel.armor.hand.plate_left-0",
"voxel.armor.hand.plate_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(Plate0)): VoxTrans(
"voxel.armor.shoulder.plate_left-0",
"voxel.armor.shoulder.plate_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//Leather0 Armor
Armor(Chest(Leather0)): VoxTrans(
Armor(Chest(Leather0)): VoxTrans(
"voxel.armor.chest.leather-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
@ -124,15 +124,98 @@
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(Leather0)): VoxTrans(
"voxel.armor.hand.leather_left-0",
"voxel.armor.hand.leather_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(Leather1)): VoxTrans(
"voxel.armor.shoulder.leather_left-1",
"voxel.armor.shoulder.leather_right-1",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder(Leather0)): VoxTrans(
"voxel.armor.shoulder.leather_left-0",
"voxel.armor.shoulder.leather_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//Linen Cloth
Armor(Chest(ClothBlue0)): VoxTrans(
"voxel.armor.chest.cloth_blue-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Pants(ClothBlue0)): VoxTrans(
"voxel.armor.pants.cloth_blue-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Belt(ClothBlue0)): VoxTrans(
"voxel.armor.belt.cloth_blue-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.8,
),
Armor(Foot(ClothBlue0)): VoxTrans(
"voxel.armor.foot.cloth_blue-0",
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(ClothBlue0)): VoxTrans(
"voxel.armor.hand.cloth_blue_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(ClothBlue0)): VoxTrans(
"voxel.armor.shoulder.cloth_blue_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//////////////
Armor(Chest(ClothGreen0)): VoxTrans(
"voxel.armor.chest.cloth_green-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Pants(ClothGreen0)): VoxTrans(
"voxel.armor.pants.cloth_green-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Belt(ClothGreen0)): VoxTrans(
"voxel.armor.belt.cloth_green-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.8,
),
Armor(Foot(ClothGreen0)): VoxTrans(
"voxel.armor.foot.cloth_green-0",
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(ClothGreen0)): VoxTrans(
"voxel.armor.hand.cloth_green_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(Leather1)): VoxTrans(
"voxel.armor.shoulder.cloth_green_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder(ClothGreen0)): VoxTrans(
"voxel.armor.shoulder.cloth_green_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//////
Armor(Chest(ClothPurple0)): VoxTrans(
"voxel.armor.chest.cloth_purple-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Pants(ClothPurple0)): VoxTrans(
"voxel.armor.pants.cloth_purple-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Belt(ClothPurple0)): VoxTrans(
"voxel.armor.belt.cloth_purple-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.8,
),
Armor(Foot(ClothPurple0)): VoxTrans(
"voxel.armor.foot.cloth_purple-0",
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(ClothPurple0)): VoxTrans(
"voxel.armor.hand.cloth_purple_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(ClothPurple0)): VoxTrans(
"voxel.armor.shoulder.cloth_purple_right-1",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder(ClothPurple0)): VoxTrans(
"voxel.armor.shoulder.cloth_purple_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
// Consumables

@ -36,16 +36,16 @@
color: None
),
ClothPurple0:(
vox_spec: ("armor.belt.cloth_purple_0", (-5.0, -3.5, 2.0)),
vox_spec: ("armor.belt.cloth_purple-0", (-5.0, -3.5, 2.0)),
color: None
),
ClothBlue0:(
vox_spec: ("armor.belt.cloth_blue_0", (-5.0, -3.5, 2.0)),
vox_spec: ("armor.belt.cloth_blue-0", (-5.0, -3.5, 2.0)),
color: None
),
ClothGreen0:(
vox_spec: ("armor.belt.cloth_purple_0", (-5.0, -3.5, 2.0)),
vox_spec: ("armor.belt.cloth_green-0", (-5.0, -3.5, 2.0)),
color: None
),
})

@ -44,16 +44,16 @@
color: None
),
ClothPurple0:(
vox_spec: ("armor.chest.cloth_purple-0", (-7.0, -3.5, 2.0)),
vox_spec: ("armor.chest.cloth_purple-0", (-7.0, -3.5, 1.0)),
color: None
),
ClothBlue0:(
vox_spec: ("armor.chest.cloth_blue-0", (-7.0, -3.5, 2.0)),
vox_spec: ("armor.chest.cloth_blue-0", (-7.0, -3.5, 1.0)),
color: None
),
ClothGreen0:(
vox_spec: ("armor.chest.cloth_green-0", (-7.0, -3.5, 2.0)),
vox_spec: ("armor.chest.cloth_green-0", (-7.0, -3.5, 1.0)),
color: None
),
})

@ -28,15 +28,15 @@
color: None
),
ClothPurple0:(
vox_spec: ("armor.foot.cloth_purple_0", (-2.5, -3.5, -9.0)),
vox_spec: ("armor.foot.cloth_purple-0", (-2.5, -3.5, -9.0)),
color: None
),
ClothBlue0:(
vox_spec: ("armor.foot.cloth_purple_0", (-2.5, -3.5, -9.0)),
vox_spec: ("armor.foot.cloth_blue-0", (-2.5, -3.5, -9.0)),
color: None
),
ClothGreen0:(
vox_spec: ("armor.foot.cloth_purple_0", (-2.5, -3.5, -9.0)),
vox_spec: ("armor.foot.cloth_green-0", (-2.5, -3.5, -9.0)),
color: None
),
})

@ -51,7 +51,7 @@
),
ClothPurple0: (
left: (
vox_spec: ("armor.hand.cloth_purple_left-0", (-1.5, -1.5, -7.0)),
vox_spec: ("armor.hand.cloth_purple_right-0", (-1.5, -1.5, -7.0)),
color: None
),
right: (
@ -61,7 +61,7 @@
),
ClothBlue0: (
left: (
vox_spec: ("armor.hand.cloth_blue_left-0", (-1.5, -1.5, -7.0)),
vox_spec: ("armor.hand.cloth_blue_right-0", (-1.5, -1.5, -7.0)),
color: None
),
right: (
@ -71,7 +71,7 @@
),
ClothGreen0: (
left: (
vox_spec: ("armor.hand.cloth_green_left-0", (-1.5, -1.5, -7.0)),
vox_spec: ("armor.hand.cloth_green_right-0", (-1.5, -1.5, -7.0)),
color: None
),
right: (

@ -40,15 +40,15 @@
color: None
),
ClothPurple0:(
vox_spec: ("armor.pants.cloth_purple_0", (-5.0, -3.5, 2.0)),
vox_spec: ("armor.pants.cloth_purple-0", (-5.0, -3.5, 0.0)),
color: None
),
ClothBlue0:(
vox_spec: ("armor.pants.cloth_blue_0", (-5.0, -3.5, 2.0)),
vox_spec: ("armor.pants.cloth_blue-0", (-5.0, -3.5, 0.0)),
color: None
),
ClothGreen0:(
vox_spec: ("armor.pants.cloth_purple_0", (-5.0, -3.5, 2.0)),
vox_spec: ("armor.pants.cloth_green-0", (-5.0, -3.5, 0.0)),
color: None
),
})

@ -82,7 +82,7 @@
),
ClothPurple0: (
left: (
vox_spec: ("armor.shoulder.cloth_purple_left-0", (-3.2, -3.5, 1.0)),
vox_spec: ("armor.shoulder.cloth_purple_right-0", (-3.2, -3.5, 1.0)),
color: None
),
right: (

@ -393,7 +393,7 @@ impl Client {
{
if last_character_states
.get(entity)
.map(|l| !client_character_state.equals(&l.0))
.map(|l| !client_character_state.same_variant(&l.0))
.unwrap_or(true)
{
let _ = last_character_states
@ -692,8 +692,7 @@ impl Client {
self.state
.ecs()
.read_resource::<EventBus<SfxEventItem>>()
.emitter()
.emit(SfxEventItem::at_player_position(SfxEvent::Inventory(event)));
.emit_now(SfxEventItem::at_player_position(SfxEvent::Inventory(event)));
},
ServerMsg::TerrainChunkUpdate { key, chunk } => {
if let Ok(chunk) = chunk {

@ -3,7 +3,7 @@ use crate::{
states::*,
sys::character_behavior::JoinData,
};
use specs::{Component, FlaggedStorage, HashMapStorage};
use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
use std::time::Duration;
@ -13,6 +13,8 @@ pub enum CharacterAbility {
buildup_duration: Duration,
recover_duration: Duration,
base_damage: u32,
range: f32,
max_angle: f32,
},
BasicRanged {
recover_duration: Duration,
@ -66,10 +68,6 @@ impl CharacterAbility {
}
}
impl Component for CharacterAbility {
type Storage = IDVStorage<Self>;
}
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct ItemConfig {
pub item: Item,
@ -99,11 +97,15 @@ impl From<&CharacterAbility> for CharacterState {
buildup_duration,
recover_duration,
base_damage,
range,
max_angle,
} => CharacterState::BasicMelee(basic_melee::Data {
exhausted: false,
buildup_duration: *buildup_duration,
recover_duration: *recover_duration,
base_damage: *base_damage,
range: *range,
max_angle: *max_angle,
}),
CharacterAbility::BasicRanged {
recover_duration,
@ -133,7 +135,7 @@ impl From<&CharacterAbility> for CharacterState {
}),
CharacterAbility::BasicBlock => CharacterState::BasicBlock,
CharacterAbility::Roll => CharacterState::Roll(roll::Data {
remaining_duration: Duration::from_millis(600),
remaining_duration: Duration::from_millis(300),
}),
CharacterAbility::TimedCombo {
buildup_duration,

@ -111,7 +111,7 @@ impl CharacterState {
}
/// Compares for shallow equality (does not check internal struct equality)
pub fn equals(&self, other: &Self) -> bool {
pub fn same_variant(&self, other: &Self) -> bool {
// Check if state is the same without looking at the inner data
std::mem::discriminant(self) == std::mem::discriminant(other)
}

@ -10,7 +10,7 @@ use crate::{
use rand::seq::SliceRandom;
use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
use std::{fs::File, io::BufReader, time::Duration, vec::Vec};
use std::{fs::File, io::BufReader, time::Duration};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum SwordKind {
@ -68,28 +68,24 @@ impl ToolData {
use ToolKind::*;
match self.kind {
Sword(_) => vec![
// BasicMelee {
// buildup_duration: Duration::from_millis(100),
// recover_duration: Duration::from_millis(500),
// base_damage: 6,
// },
CharacterAbility::TripleStrike { base_damage: 7 },
DashMelee {
buildup_duration: Duration::from_millis(500),
recover_duration: Duration::from_millis(500),
base_damage: 20,
},
],
Sword(_) => vec![TripleStrike { base_damage: 7 }, DashMelee {
buildup_duration: Duration::from_millis(500),
recover_duration: Duration::from_millis(500),
base_damage: 20,
}],
Axe(_) => vec![BasicMelee {
buildup_duration: Duration::from_millis(700),
recover_duration: Duration::from_millis(100),
base_damage: 8,
range: 3.5,
max_angle: 30.0,
}],
Hammer(_) => vec![BasicMelee {
buildup_duration: Duration::from_millis(700),
recover_duration: Duration::from_millis(300),
base_damage: 10,
range: 3.5,
max_angle: 60.0,
}],
Bow(_) => vec![BasicRanged {
projectile: Projectile {
@ -113,12 +109,16 @@ impl ToolData {
buildup_duration: Duration::from_millis(100),
recover_duration: Duration::from_millis(400),
base_damage: 5,
range: 3.5,
max_angle: 60.0,
}],
Staff(_) => vec![
BasicMelee {
buildup_duration: Duration::from_millis(400),
buildup_duration: Duration::from_millis(0),
recover_duration: Duration::from_millis(300),
base_damage: 7,
base_damage: 3,
range: 10.0,
max_angle: 45.0,
},
BasicRanged {
projectile: Projectile {
@ -321,8 +321,28 @@ impl Item {
"common.items.armor.shoulder.plate_0",
"common.items.armor.shoulder.leather_1",
"common.items.armor.shoulder.leather_0",
"common.items.armor.hand.leather_0",
"common.items.armor.hand.plate_0",
"common.items.weapons.wood_sword",
"common.items.weapons.short_sword_0",
"common.items.armor.belt.cloth_blue_0",
"common.items.armor.chest.cloth_blue_0",
"common.items.armor.foot.cloth_blue_0",
"common.items.armor.pants.cloth_blue_0",
"common.items.armor.shoulder.cloth_blue_0",
"common.items.armor.hand.cloth_blue_0",
"common.items.armor.belt.cloth_green_0",
"common.items.armor.chest.cloth_green_0",
"common.items.armor.foot.cloth_green_0",
"common.items.armor.pants.cloth_green_0",
"common.items.armor.shoulder.cloth_green_0",
"common.items.armor.hand.cloth_green_0",
"common.items.armor.belt.cloth_purple_0",
"common.items.armor.chest.cloth_purple_0",
"common.items.armor.foot.cloth_purple_0",
"common.items.armor.pants.cloth_purple_0",
"common.items.armor.shoulder.cloth_purple_0",
"common.items.armor.hand.cloth_purple_0",
]
.choose(&mut rand::thread_rng())
.unwrap(), // Can't fail

@ -144,7 +144,7 @@ impl<E> EventBus<E> {
}
}
pub fn emit(&self, event: E) { self.queue.lock().push_front(event); }
pub fn emit_now(&self, event: E) { self.queue.lock().push_back(event); }
pub fn recv_all(&self) -> impl ExactSizeIterator<Item = E> {
std::mem::replace(self.queue.lock().deref_mut(), VecDeque::new()).into_iter()
@ -157,7 +157,7 @@ pub struct Emitter<'a, E> {
}
impl<'a, E> Emitter<'a, E> {
pub fn emit(&mut self, event: E) { self.events.push_front(event); }
pub fn emit(&mut self, event: E) { self.events.push_back(event); }
pub fn append(&mut self, other: &mut VecDeque<E>) { self.events.append(other) }
}

@ -21,9 +21,7 @@ sum_type! {
Mass(comp::Mass),
Gravity(comp::Gravity),
Sticky(comp::Sticky),
CharacterAbility(comp::CharacterAbility),
Loadout(comp::Loadout),
Attacking(comp::Attacking),
CharacterState(comp::CharacterState),
Pos(comp::Pos),
Vel(comp::Vel),
@ -48,9 +46,7 @@ sum_type! {
Mass(PhantomData<comp::Mass>),
Gravity(PhantomData<comp::Gravity>),
Sticky(PhantomData<comp::Sticky>),
CharacterAbility(PhantomData<comp::CharacterAbility>),
Loadout(PhantomData<comp::Loadout>),
Attacking(PhantomData<comp::Attacking>),
CharacterState(PhantomData<comp::CharacterState>),
Pos(PhantomData<comp::Pos>),
Vel(PhantomData<comp::Vel>),
@ -75,9 +71,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::CharacterAbility(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Loadout(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Pos(comp) => sync::handle_insert(comp, entity, world),
EcsCompPacket::Vel(comp) => sync::handle_insert(comp, entity, world),
@ -100,9 +94,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::CharacterAbility(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Loadout(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Pos(comp) => sync::handle_modify(comp, entity, world),
EcsCompPacket::Vel(comp) => sync::handle_modify(comp, entity, world),
@ -127,11 +119,7 @@ impl sync::CompPacket for EcsCompPacket {
EcsCompPhantom::Mass(_) => sync::handle_remove::<comp::Mass>(entity, world),
EcsCompPhantom::Gravity(_) => sync::handle_remove::<comp::Gravity>(entity, world),
EcsCompPhantom::Sticky(_) => sync::handle_remove::<comp::Sticky>(entity, world),
EcsCompPhantom::CharacterAbility(_) => {
sync::handle_remove::<comp::CharacterAbility>(entity, world)
},
EcsCompPhantom::Loadout(_) => sync::handle_remove::<comp::Loadout>(entity, world),
EcsCompPhantom::Attacking(_) => sync::handle_remove::<comp::Attacking>(entity, world),
EcsCompPhantom::CharacterState(_) => {
sync::handle_remove::<comp::CharacterState>(entity, world)
},

@ -107,7 +107,6 @@ impl State {
ecs.register_sync_marker();
// Register server -> all clients synced components.
ecs.register::<comp::Loadout>();
ecs.register::<comp::Projectile>();
ecs.register::<comp::Body>();
ecs.register::<comp::Player>();
ecs.register::<comp::Stats>();
@ -121,7 +120,6 @@ impl State {
ecs.register::<comp::Mass>();
ecs.register::<comp::Sticky>();
ecs.register::<comp::Gravity>();
ecs.register::<comp::Attacking>();
// Register components send from clients -> server
ecs.register::<comp::Controller>();
@ -150,6 +148,7 @@ impl State {
ecs.register::<comp::Admin>();
ecs.register::<comp::Waypoint>();
ecs.register::<comp::Projectile>();
ecs.register::<comp::Attacking>();
// Register synced resources used by the ECS.
ecs.insert(TimeOfDay(0.0));

@ -5,7 +5,7 @@ use crate::{
};
use std::time::Duration;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Data {
/// How long until state should deal damage
pub buildup_duration: Duration,
@ -13,6 +13,10 @@ pub struct Data {
pub recover_duration: Duration,
/// Base damage
pub base_damage: u32,
/// Max range
pub range: f32,
/// Max angle (45.0 will give you a 90.0 angle window)
pub max_angle: f32,
/// Whether the attack can deal more damage
pub exhausted: bool,
}
@ -32,13 +36,15 @@ impl CharacterBehavior for Data {
.unwrap_or_default(),
recover_duration: self.recover_duration,
base_damage: self.base_damage,
range: self.range,
max_angle: self.max_angle,
exhausted: false,
});
} else if !self.exhausted {
// Hit attempt
data.updater.insert(data.entity, Attacking {
base_damage: self.base_damage,
max_angle: 75_f32.to_radians(),
max_angle: self.max_angle.to_radians(),
applied: false,
hit_count: 0,
});
@ -47,6 +53,8 @@ impl CharacterBehavior for Data {
buildup_duration: self.buildup_duration,
recover_duration: self.recover_duration,
base_damage: self.base_damage,
range: self.range,
max_angle: self.max_angle,
exhausted: true,
});
} else if self.recover_duration != Duration::default() {
@ -58,6 +66,8 @@ impl CharacterBehavior for Data {
.checked_sub(Duration::from_secs_f32(data.dt.0))
.unwrap_or_default(),
base_damage: self.base_damage,
range: self.range,
max_angle: self.max_angle,
exhausted: true,
});
} else {

@ -22,7 +22,7 @@ impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData) -> StateUpdate {
let mut update = StateUpdate::from(data);
if let Err(_) = update.energy.try_change_by(-5, EnergySource::Climb) {
if let Err(_) = update.energy.try_change_by(-8, EnergySource::Climb) {
update.character = CharacterState::Idle {};
}

@ -27,6 +27,7 @@ impl CharacterBehavior for Data {
if self.initialize {
update.vel.0 = data.inputs.look_dir * 20.0;
update.ori.0 = data.vel.0.normalized();
}
if self.buildup_duration != Duration::default() && data.physics.touch_entity.is_none() {

@ -129,6 +129,9 @@ impl<'a> System<'a> for Sys {
mountings,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
let mut local_emitter = local_bus.emitter();
let mut join_iter = (
&entities,
&uids,
@ -191,8 +194,8 @@ impl<'a> System<'a> for Sys {
*tuple.5 = state_update.ori;
*tuple.6 = state_update.energy;
*tuple.7 = state_update.loadout;
local_bus.emitter().append(&mut state_update.local_events);
server_bus.emitter().append(&mut state_update.server_events);
local_emitter.append(&mut state_update.local_events);
server_emitter.append(&mut state_update.server_events);
}
}
}

@ -1,7 +1,7 @@
use crate::{
comp::{
Attacking, Body, CharacterState, Controller, HealthChange, HealthSource, Ori, Pos, Scale,
Stats,
Agent, Attacking, Body, CharacterState, Controller, HealthChange, HealthSource, Ori, Pos,
Scale, Stats,
},
event::{EventBus, ServerEvent},
sync::Uid,
@ -25,6 +25,7 @@ impl<'a> System<'a> for Sys {
ReadStorage<'a, Pos>,
ReadStorage<'a, Ori>,
ReadStorage<'a, Scale>,
ReadStorage<'a, Agent>,
ReadStorage<'a, Controller>,
ReadStorage<'a, Body>,
ReadStorage<'a, Stats>,
@ -41,6 +42,7 @@ impl<'a> System<'a> for Sys {
positions,
orientations,
scales,
agents,
controllers,
bodies,
stats,
@ -48,13 +50,15 @@ impl<'a> System<'a> for Sys {
character_states,
): Self::SystemData,
) {
let mut server_emitter = server_bus.emitter();
// Attacks
for (entity, uid, pos, ori, scale_maybe, _, _attacker_stats, attack) in (
for (entity, uid, pos, ori, scale_maybe, agent_maybe, _, _attacker_stats, attack) in (
&entities,
&uids,
&positions,
&orientations,
scales.maybe(),
agents.maybe(),
&controllers,
&stats,
&mut attacking_storage,
@ -81,7 +85,7 @@ impl<'a> System<'a> for Sys {
{
// 2D versions
let pos2 = Vec2::from(pos.0);
let pos_b2: Vec2<f32> = Vec2::from(pos_b.0);
let pos_b2 = Vec2::<f32>::from(pos_b.0);
let ori2 = Vec2::from(ori.0);
// Scales
@ -99,6 +103,15 @@ impl<'a> System<'a> for Sys {
// Weapon gives base damage
let mut dmg = attack.base_damage;
// NPCs do less damage:
if agent_maybe.is_some() {
dmg = (dmg / 2).max(1);
}
if rand::random() {
dmg += 1;
}
// Block
if character_b.is_block()
&& ori_b.0.angle_between(pos.0 - pos_b.0) < BLOCK_ANGLE.to_radians() / 2.0
@ -106,7 +119,7 @@ impl<'a> System<'a> for Sys {
dmg = (dmg as f32 * (1.0 - BLOCK_EFFICIENCY)) as u32
}
server_bus.emitter().emit(ServerEvent::Damage {
server_emitter.emit(ServerEvent::Damage {
uid: *uid_b,
change: HealthChange {
amount: -(dmg as i32),

@ -836,7 +836,7 @@ fn handle_explosion(server: &mut Server, entity: EcsEntity, args: String, action
.state
.ecs()
.read_resource::<EventBus<ServerEvent>>()
.emit(ServerEvent::Explosion { pos: pos.0, radius }),
.emit_now(ServerEvent::Explosion { pos: pos.0, radius }),
None => server.notify_client(
entity,
ServerMsg::private(String::from("You have no position!")),

@ -45,7 +45,7 @@ impl<'a> System<'a> for Sys {
&mut self,
(
entities,
server_emitter,
server_event_bus,
time,
terrain,
mut timer,
@ -68,6 +68,8 @@ impl<'a> System<'a> for Sys {
let time = time.0;
let mut server_emitter = server_event_bus.emitter();
let mut new_chat_msgs = Vec::new();
// Player list to send new players.

@ -38,7 +38,7 @@ impl<'a> System<'a> for Sys {
fn run(
&mut self,
(
server_emitter,
server_event_bus,
tick,
mut timer,
mut chunk_generator,
@ -51,6 +51,8 @@ impl<'a> System<'a> for Sys {
) {
timer.start();
let mut server_emitter = server_event_bus.emitter();
// Fetch any generated `TerrainChunk`s and insert them into the terrain.
// Also, send the chunk data to anybody that is close by.
'insert_terrain_chunks: while let Some((key, res)) = chunk_generator.recv_new_chunk() {
@ -196,16 +198,19 @@ impl<'a> System<'a> for Sys {
item,
primary_ability: ability_drain.next(),
secondary_ability: ability_drain.next(),
block_ability: Some(comp::CharacterAbility::BasicBlock),
block_ability: None,
dodge_ability: Some(comp::CharacterAbility::Roll),
})
} else {
Some(ItemConfig {
// We need the empty item so npcs can attack
item: Item::empty(),
primary_ability: Some(CharacterAbility::BasicMelee {
buildup_duration: Duration::from_millis(50),
recover_duration: Duration::from_millis(50),
base_damage: 1,
buildup_duration: Duration::from_millis(0),
recover_duration: Duration::from_millis(300),
base_damage: 2,
range: 3.5,
max_angle: 60.0,
}),
secondary_ability: None,
block_ability: None,
@ -299,6 +304,8 @@ impl<'a> System<'a> for Sys {
buildup_duration: Duration::from_millis(800),
recover_duration: Duration::from_millis(200),
base_damage: 13,
range: 3.5,
max_angle: 60.0,
}),
secondary_ability: None,
block_ability: None,

@ -47,6 +47,9 @@ impl MovementEventMapper {
const SFX_DIST_LIMIT_SQR: f32 = 20000.0;
let ecs = state.ecs();
let sfx_event_bus = ecs.read_resource::<EventBus<SfxEventItem>>();
let mut sfx_emitter = sfx_event_bus.emitter();
let player_position = ecs
.read_storage::<Pos>()
.get(player_entity)
@ -86,13 +89,11 @@ impl MovementEventMapper {
// Check for SFX config entry for this movement
if Self::should_emit(state, triggers.get_key_value(&mapped_event)) {
ecs.read_resource::<EventBus<SfxEventItem>>()
.emitter()
.emit(SfxEventItem::new(
mapped_event,
Some(pos.0),
Some(Self::get_volume_for_body_type(body)),
));
sfx_emitter.emit(SfxEventItem::new(
mapped_event,
Some(pos.0),
Some(Self::get_volume_for_body_type(body)),
));
// Set the new previous entity state
state.event = mapped_event;

@ -53,8 +53,7 @@ impl ProgressionEventMapper {
if sfx_trigger_item.is_some() {
ecs.read_resource::<EventBus<SfxEventItem>>()
.emitter()
.emit(SfxEventItem::at_player_position(mapped_event));
.emit_now(SfxEventItem::at_player_position(mapped_event));
}
}

@ -683,7 +683,7 @@ impl CharSelectionUi {
Mode::Create {
name,
body,
loadout,
loadout: _,
tool,
} => {
let mut to_select = false;

@ -21,7 +21,6 @@ use common::{
ItemKind, Loadout,
},
figure::{DynaUnionizer, MatSegment, Material, Segment},
vol::SizedVol,
};
use dot_vox::DotVoxData;
use hashbrown::HashMap;

@ -418,7 +418,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -660,7 +660,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -740,7 +740,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -820,7 +820,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -894,7 +894,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -968,7 +968,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -1042,7 +1042,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -1116,7 +1116,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -1190,7 +1190,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
@ -1264,7 +1264,7 @@ impl FigureMgr {
_ => continue,
};
if !character.equals(&last_character.0) {
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}

@ -35,6 +35,10 @@ const LIGHT_DIST_RADIUS: f32 = 64.0; // The distance beyond which lights may not
const SHADOW_DIST_RADIUS: f32 = 8.0;
const SHADOW_MAX_DIST: f32 = 96.0; // The distance beyond which shadows may not be visible
/// Above this speed is considered running
/// Used for first person camera effects
const RUNNING_THRESHOLD: f32 = 0.7;
struct Skybox {
model: Model<SkyboxPipeline>,
locals: Consts<SkyboxLocals>,
@ -191,7 +195,7 @@ impl Scene {
let is_running = ecs
.read_storage::<comp::Vel>()
.get(scene_data.player_entity)
.map(|v| v.0.magnitude_squared() > 0.5);
.map(|v| v.0.magnitude_squared() > RUNNING_THRESHOLD.powi(2));
let on_ground = ecs
.read_storage::<comp::PhysicsState>()