mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Allow projectiles to react to triggers
This commit is contained in:
@ -9,6 +9,7 @@ mod last;
|
|||||||
mod location;
|
mod location;
|
||||||
mod phys;
|
mod phys;
|
||||||
mod player;
|
mod player;
|
||||||
|
pub mod projectile;
|
||||||
mod stats;
|
mod stats;
|
||||||
mod visual;
|
mod visual;
|
||||||
|
|
||||||
@ -24,5 +25,6 @@ pub use last::Last;
|
|||||||
pub use location::Waypoint;
|
pub use location::Waypoint;
|
||||||
pub use phys::{ForceUpdate, Mass, Ori, PhysicsState, Pos, Scale, Vel};
|
pub use phys::{ForceUpdate, Mass, Ori, PhysicsState, Pos, Scale, Vel};
|
||||||
pub use player::Player;
|
pub use player::Player;
|
||||||
|
pub use projectile::Projectile;
|
||||||
pub use stats::{Equipment, Exp, HealthSource, Level, Stats};
|
pub use stats::{Equipment, Exp, HealthSource, Level, Stats};
|
||||||
pub use visual::LightEmitter;
|
pub use visual::LightEmitter;
|
||||||
|
18
common/src/comp/projectile.rs
Normal file
18
common/src/comp/projectile.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use specs::{Component, FlaggedStorage, NullStorage};
|
||||||
|
use specs_idvs::IDVStorage;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum Effect {
|
||||||
|
Damage(u32),
|
||||||
|
Vanish,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Projectile {
|
||||||
|
pub hit_ground: Vec<Effect>,
|
||||||
|
pub hit_entity: Vec<Effect>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Projectile {
|
||||||
|
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
|
||||||
|
}
|
@ -25,7 +25,7 @@ pub enum ServerEvent {
|
|||||||
pos: Vec3<f32>,
|
pos: Vec3<f32>,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
},
|
},
|
||||||
Die {
|
Destroy {
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
cause: comp::HealthSource,
|
cause: comp::HealthSource,
|
||||||
},
|
},
|
||||||
|
@ -157,6 +157,7 @@ impl State {
|
|||||||
ecs.register::<comp::Inventory>();
|
ecs.register::<comp::Inventory>();
|
||||||
ecs.register::<comp::Admin>();
|
ecs.register::<comp::Admin>();
|
||||||
ecs.register::<comp::Waypoint>();
|
ecs.register::<comp::Waypoint>();
|
||||||
|
ecs.register::<comp::Projectile>();
|
||||||
|
|
||||||
// Register synced resources used by the ECS.
|
// Register synced resources used by the ECS.
|
||||||
ecs.insert_synced(TimeOfDay(0.0));
|
ecs.insert_synced(TimeOfDay(0.0));
|
||||||
|
@ -4,6 +4,7 @@ pub mod combat;
|
|||||||
pub mod controller;
|
pub mod controller;
|
||||||
pub mod movement;
|
pub mod movement;
|
||||||
pub mod phys;
|
pub mod phys;
|
||||||
|
mod projectile;
|
||||||
mod stats;
|
mod stats;
|
||||||
|
|
||||||
// External
|
// External
|
||||||
@ -14,6 +15,7 @@ const AGENT_SYS: &str = "agent_sys";
|
|||||||
const CONTROLLER_SYS: &str = "controller_sys";
|
const CONTROLLER_SYS: &str = "controller_sys";
|
||||||
const PHYS_SYS: &str = "phys_sys";
|
const PHYS_SYS: &str = "phys_sys";
|
||||||
const MOVEMENT_SYS: &str = "movement_sys";
|
const MOVEMENT_SYS: &str = "movement_sys";
|
||||||
|
const PROJECTILE_SYS: &str = "projectile_sys";
|
||||||
const COMBAT_SYS: &str = "combat_sys";
|
const COMBAT_SYS: &str = "combat_sys";
|
||||||
const STATS_SYS: &str = "stats_sys";
|
const STATS_SYS: &str = "stats_sys";
|
||||||
const CLEANUP_SYS: &str = "cleanup_sys";
|
const CLEANUP_SYS: &str = "cleanup_sys";
|
||||||
@ -22,7 +24,8 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
|
|||||||
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
|
dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
|
||||||
dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]);
|
dispatch_builder.add(controller::Sys, CONTROLLER_SYS, &[AGENT_SYS]);
|
||||||
dispatch_builder.add(movement::Sys, MOVEMENT_SYS, &[]);
|
dispatch_builder.add(movement::Sys, MOVEMENT_SYS, &[]);
|
||||||
dispatch_builder.add(combat::Sys, COMBAT_SYS, &[CONTROLLER_SYS]);
|
dispatch_builder.add(projectile::Sys, PROJECTILE_SYS, &[CONTROLLER_SYS]);
|
||||||
|
dispatch_builder.add(combat::Sys, COMBAT_SYS, &[PROJECTILE_SYS]);
|
||||||
dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]);
|
dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]);
|
||||||
dispatch_builder.add(
|
dispatch_builder.add(
|
||||||
phys::Sys,
|
phys::Sys,
|
||||||
|
84
common/src/sys/projectile.rs
Normal file
84
common/src/sys/projectile.rs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
use crate::{
|
||||||
|
comp::{
|
||||||
|
projectile, ActionState::*, CharacterState, Controller, ForceUpdate, HealthSource, Ori,
|
||||||
|
PhysicsState, Pos, Projectile, Stats, Vel,
|
||||||
|
},
|
||||||
|
event::{EventBus, ServerEvent},
|
||||||
|
state::{DeltaTime, Uid},
|
||||||
|
};
|
||||||
|
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||||
|
use std::time::Duration;
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
|
/// This system is responsible for handling projectile effect triggers
|
||||||
|
pub struct Sys;
|
||||||
|
impl<'a> System<'a> for Sys {
|
||||||
|
type SystemData = (
|
||||||
|
Entities<'a>,
|
||||||
|
ReadStorage<'a, Uid>,
|
||||||
|
Read<'a, DeltaTime>,
|
||||||
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
|
ReadStorage<'a, Pos>,
|
||||||
|
ReadStorage<'a, Ori>,
|
||||||
|
ReadStorage<'a, Vel>,
|
||||||
|
ReadStorage<'a, PhysicsState>,
|
||||||
|
WriteStorage<'a, Projectile>,
|
||||||
|
WriteStorage<'a, Stats>,
|
||||||
|
);
|
||||||
|
|
||||||
|
fn run(
|
||||||
|
&mut self,
|
||||||
|
(
|
||||||
|
entities,
|
||||||
|
uids,
|
||||||
|
dt,
|
||||||
|
server_bus,
|
||||||
|
positions,
|
||||||
|
velocities,
|
||||||
|
orientations,
|
||||||
|
physics_states,
|
||||||
|
mut projectiles,
|
||||||
|
mut stats,
|
||||||
|
): Self::SystemData,
|
||||||
|
) {
|
||||||
|
let mut server_emitter = server_bus.emitter();
|
||||||
|
|
||||||
|
// Attacks
|
||||||
|
for (entity, uid, pos, velocity, ori, physics, projectile) in (
|
||||||
|
&entities,
|
||||||
|
&uids,
|
||||||
|
&positions,
|
||||||
|
&velocities,
|
||||||
|
&orientations,
|
||||||
|
&physics_states,
|
||||||
|
&mut projectiles,
|
||||||
|
)
|
||||||
|
.join()
|
||||||
|
{
|
||||||
|
// Hit ground
|
||||||
|
if physics.on_ground {
|
||||||
|
for effect in projectile.hit_ground.drain(..) {
|
||||||
|
match effect {
|
||||||
|
projectile::Effect::Vanish => server_emitter.emit(ServerEvent::Destroy {
|
||||||
|
entity,
|
||||||
|
cause: HealthSource::World,
|
||||||
|
}),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Check entity hit
|
||||||
|
if false {
|
||||||
|
for effect in projectile.hit_entity.drain(..) {
|
||||||
|
match effect {
|
||||||
|
projectile::Effect::Vanish => server_emitter.emit(ServerEvent::Destroy {
|
||||||
|
entity,
|
||||||
|
cause: HealthSource::World,
|
||||||
|
}),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
for (entity, mut stat) in (&entities, &mut stats).join() {
|
for (entity, mut stat) in (&entities, &mut stats).join() {
|
||||||
if stat.should_die() && !stat.is_dead {
|
if stat.should_die() && !stat.is_dead {
|
||||||
event_emitter.emit(ServerEvent::Die {
|
event_emitter.emit(ServerEvent::Destroy {
|
||||||
entity,
|
entity,
|
||||||
cause: match stat.health.last_change {
|
cause: match stat.health.last_change {
|
||||||
Some(change) => change.2,
|
Some(change) => change.2,
|
||||||
|
@ -203,6 +203,7 @@ impl Server {
|
|||||||
pos: comp::Pos,
|
pos: comp::Pos,
|
||||||
vel: comp::Vel,
|
vel: comp::Vel,
|
||||||
body: comp::Body,
|
body: comp::Body,
|
||||||
|
projectile: comp::Projectile,
|
||||||
) -> EcsEntityBuilder {
|
) -> EcsEntityBuilder {
|
||||||
state
|
state
|
||||||
.ecs_mut()
|
.ecs_mut()
|
||||||
@ -211,6 +212,7 @@ impl Server {
|
|||||||
.with(vel)
|
.with(vel)
|
||||||
.with(comp::Ori(Vec3::unit_y()))
|
.with(comp::Ori(Vec3::unit_y()))
|
||||||
.with(body)
|
.with(body)
|
||||||
|
.with(projectile)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_player_character(
|
pub fn create_player_character(
|
||||||
@ -288,7 +290,7 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerEvent::Shoot(entity, dir) => {
|
ServerEvent::Shoot(entity, dir /*, projectile*/) => {
|
||||||
let pos = state
|
let pos = state
|
||||||
.ecs()
|
.ecs()
|
||||||
.read_storage::<comp::Pos>()
|
.read_storage::<comp::Pos>()
|
||||||
@ -300,11 +302,15 @@ impl Server {
|
|||||||
comp::Pos(pos),
|
comp::Pos(pos),
|
||||||
comp::Vel(dir * 100.0),
|
comp::Vel(dir * 100.0),
|
||||||
comp::Body::Object(comp::object::Body::Arrow),
|
comp::Body::Object(comp::object::Body::Arrow),
|
||||||
|
comp::Projectile {
|
||||||
|
hit_ground: vec![comp::projectile::Effect::Vanish],
|
||||||
|
hit_entity: vec![],
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerEvent::Die { entity, cause } => {
|
ServerEvent::Destroy { entity, cause } => {
|
||||||
let ecs = state.ecs_mut();
|
let ecs = state.ecs_mut();
|
||||||
// Chat message
|
// Chat message
|
||||||
if let Some(player) = ecs.read_storage::<comp::Player>().get(entity) {
|
if let Some(player) = ecs.read_storage::<comp::Player>().get(entity) {
|
||||||
@ -327,7 +333,7 @@ impl Server {
|
|||||||
clients.notify_registered(ServerMsg::kill(msg));
|
clients.notify_registered(ServerMsg::kill(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give EXP to the client
|
// Give EXP to the killer if entity had stats
|
||||||
let mut stats = ecs.write_storage::<comp::Stats>();
|
let mut stats = ecs.write_storage::<comp::Stats>();
|
||||||
|
|
||||||
if let Some(entity_stats) = stats.get(entity).cloned() {
|
if let Some(entity_stats) = stats.get(entity).cloned() {
|
||||||
|
Reference in New Issue
Block a user