mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'zesterer/damage-fixes' into 'master'
Make items vanish after 5 minutes See merge request veloren/veloren!3963
This commit is contained in:
commit
e71eee0cd2
@ -69,6 +69,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Creatures flee less quickly when low on health
|
- Creatures flee less quickly when low on health
|
||||||
- All `/build_area_*` commands have been renamed to `/area_*`, and you will have to pass an additional area type
|
- All `/build_area_*` commands have been renamed to `/area_*`, and you will have to pass an additional area type
|
||||||
- Collision damage can now be applied in horizontal axes, in addition to the vertical axis
|
- Collision damage can now be applied in horizontal axes, in addition to the vertical axis
|
||||||
|
- Items will vanish after 5 minutes to minimise performance problems
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ macro_rules! synced_components {
|
|||||||
combo: Combo,
|
combo: Combo,
|
||||||
active_abilities: ActiveAbilities,
|
active_abilities: ActiveAbilities,
|
||||||
can_build: CanBuild,
|
can_build: CanBuild,
|
||||||
|
object: Object,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -253,3 +254,7 @@ impl NetSync for ActiveAbilities {
|
|||||||
impl NetSync for CanBuild {
|
impl NetSync for CanBuild {
|
||||||
const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
|
const SYNC_FROM: SyncFrom = SyncFrom::ClientEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NetSync for Object {
|
||||||
|
const SYNC_FROM: SyncFrom = SyncFrom::AnyEntity;
|
||||||
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use super::item::Reagent;
|
use super::item::Reagent;
|
||||||
use crate::uid::Uid;
|
use crate::{resources::Time, uid::Uid};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::Component;
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum Object {
|
pub enum Object {
|
||||||
Bomb {
|
Bomb {
|
||||||
owner: Option<Uid>,
|
owner: Option<Uid>,
|
||||||
@ -12,8 +13,12 @@ pub enum Object {
|
|||||||
owner: Option<Uid>,
|
owner: Option<Uid>,
|
||||||
reagent: Reagent,
|
reagent: Reagent,
|
||||||
},
|
},
|
||||||
|
DeleteAfter {
|
||||||
|
spawned_at: Time,
|
||||||
|
timeout: Duration,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Object {
|
impl Component for Object {
|
||||||
type Storage = specs::VecStorage<Self>;
|
type Storage = DerefFlaggedStorage<Self, specs::VecStorage<Self>>;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ use common::{
|
|||||||
self,
|
self,
|
||||||
item::{ItemKind, MaterialStatManifest},
|
item::{ItemKind, MaterialStatManifest},
|
||||||
skills::{GeneralSkill, Skill},
|
skills::{GeneralSkill, Skill},
|
||||||
ChatType, Group, Inventory, Item, LootOwner, Player, Poise, Presence, PresenceKind,
|
ChatType, Group, Inventory, Item, LootOwner, Object, Player, Poise, Presence, PresenceKind,
|
||||||
},
|
},
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
link::{Link, LinkHandle},
|
link::{Link, LinkHandle},
|
||||||
@ -40,7 +40,7 @@ use specs::{
|
|||||||
saveload::MarkerAllocator, Builder, Entity as EcsEntity, EntityBuilder as EcsEntityBuilder,
|
saveload::MarkerAllocator, Builder, Entity as EcsEntity, EntityBuilder as EcsEntityBuilder,
|
||||||
Join, WorldExt,
|
Join, WorldExt,
|
||||||
};
|
};
|
||||||
use std::time::Instant;
|
use std::time::{Duration, Instant};
|
||||||
use tracing::{trace, warn};
|
use tracing::{trace, warn};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
@ -366,6 +366,8 @@ impl StateExt for State {
|
|||||||
// Only if merging items fails do we give up and create a new item
|
// Only if merging items fails do we give up and create a new item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let spawned_at = *self.ecs().read_resource::<Time>();
|
||||||
|
|
||||||
let item_drop = comp::item_drop::Body::from(&item);
|
let item_drop = comp::item_drop::Body::from(&item);
|
||||||
let body = comp::Body::ItemDrop(item_drop);
|
let body = comp::Body::ItemDrop(item_drop);
|
||||||
let light_emitter = match &*item.kind() {
|
let light_emitter = match &*item.kind() {
|
||||||
@ -388,6 +390,11 @@ impl StateExt for State {
|
|||||||
.with(item_drop.density())
|
.with(item_drop.density())
|
||||||
.with(body.collider())
|
.with(body.collider())
|
||||||
.with(body)
|
.with(body)
|
||||||
|
.with(Object::DeleteAfter {
|
||||||
|
spawned_at,
|
||||||
|
// Delete the item drop after 5 minutes
|
||||||
|
timeout: Duration::from_secs(300),
|
||||||
|
})
|
||||||
.maybe_with(loot_owner)
|
.maybe_with(loot_owner)
|
||||||
.maybe_with(light_emitter)
|
.maybe_with(light_emitter)
|
||||||
.build(),
|
.build(),
|
||||||
|
@ -2,11 +2,11 @@ use common::{
|
|||||||
comp::{Object, PhysicsState, Pos, Vel},
|
comp::{Object, PhysicsState, Pos, Vel},
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
resources::DeltaTime,
|
resources::{DeltaTime, Time},
|
||||||
Damage, DamageKind, DamageSource, Explosion, RadiusEffect,
|
Damage, DamageKind, DamageSource, Explosion, RadiusEffect,
|
||||||
};
|
};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use specs::{Entities, Join, Read, ReadStorage, WriteStorage};
|
use specs::{Entities, Join, Read, ReadStorage};
|
||||||
use vek::Rgb;
|
use vek::Rgb;
|
||||||
|
|
||||||
/// This system is responsible for handling misc object behaviours
|
/// This system is responsible for handling misc object behaviours
|
||||||
@ -16,11 +16,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
type SystemData = (
|
type SystemData = (
|
||||||
Entities<'a>,
|
Entities<'a>,
|
||||||
Read<'a, DeltaTime>,
|
Read<'a, DeltaTime>,
|
||||||
|
Read<'a, Time>,
|
||||||
Read<'a, EventBus<ServerEvent>>,
|
Read<'a, EventBus<ServerEvent>>,
|
||||||
ReadStorage<'a, Pos>,
|
ReadStorage<'a, Pos>,
|
||||||
ReadStorage<'a, Vel>,
|
ReadStorage<'a, Vel>,
|
||||||
ReadStorage<'a, PhysicsState>,
|
ReadStorage<'a, PhysicsState>,
|
||||||
WriteStorage<'a, Object>,
|
ReadStorage<'a, Object>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const NAME: &'static str = "object";
|
const NAME: &'static str = "object";
|
||||||
@ -29,7 +30,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
_job: &mut Job<Self>,
|
_job: &mut Job<Self>,
|
||||||
(entities, _dt, server_bus, positions, velocities, physics_states, mut objects): Self::SystemData,
|
(entities, _dt, time, server_bus, positions, velocities, physics_states, objects): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut server_emitter = server_bus.emitter();
|
let mut server_emitter = server_bus.emitter();
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&positions,
|
&positions,
|
||||||
&velocities,
|
&velocities,
|
||||||
&physics_states,
|
&physics_states,
|
||||||
&mut objects,
|
&objects,
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
@ -160,6 +161,14 @@ impl<'a> System<'a> for Sys {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Object::DeleteAfter {
|
||||||
|
spawned_at,
|
||||||
|
timeout,
|
||||||
|
} => {
|
||||||
|
if (time.0 - spawned_at.0).max(0.0) > timeout.as_secs_f64() {
|
||||||
|
server_emitter.emit(ServerEvent::Delete(entity));
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,8 @@ use common::{
|
|||||||
item::{tool::AbilityContext, Hands, ItemKind, ToolKind},
|
item::{tool::AbilityContext, Hands, ItemKind, ToolKind},
|
||||||
ship::{self, figuredata::VOXEL_COLLIDER_MANIFEST},
|
ship::{self, figuredata::VOXEL_COLLIDER_MANIFEST},
|
||||||
Body, CharacterActivity, CharacterState, Collider, Controller, Health, Inventory, Item,
|
Body, CharacterActivity, CharacterState, Collider, Controller, Health, Inventory, Item,
|
||||||
ItemKey, Last, LightAnimation, LightEmitter, Ori, PhysicsState, PoiseState, Pos, Scale,
|
ItemKey, Last, LightAnimation, LightEmitter, Object, Ori, PhysicsState, PoiseState, Pos,
|
||||||
SkillSet, Stance, Vel,
|
Scale, SkillSet, Stance, Vel,
|
||||||
},
|
},
|
||||||
link::Is,
|
link::Is,
|
||||||
mounting::{Rider, VolumeRider},
|
mounting::{Rider, VolumeRider},
|
||||||
@ -6394,6 +6394,7 @@ impl FigureMgr {
|
|||||||
filter_state: impl Fn(&FigureStateMeta) -> bool,
|
filter_state: impl Fn(&FigureStateMeta) -> bool,
|
||||||
) {
|
) {
|
||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
|
let time = ecs.read_resource::<Time>();
|
||||||
let items = ecs.read_storage::<Item>();
|
let items = ecs.read_storage::<Item>();
|
||||||
(
|
(
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
@ -6404,11 +6405,13 @@ impl FigureMgr {
|
|||||||
ecs.read_storage::<Inventory>().maybe(),
|
ecs.read_storage::<Inventory>().maybe(),
|
||||||
ecs.read_storage::<Scale>().maybe(),
|
ecs.read_storage::<Scale>().maybe(),
|
||||||
ecs.read_storage::<Collider>().maybe(),
|
ecs.read_storage::<Collider>().maybe(),
|
||||||
|
ecs.read_storage::<Object>().maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
// Don't render dead entities
|
// Don't render dead entities
|
||||||
.filter(|(_, _, _, _, health, _, _, _)| health.map_or(true, |h| !h.is_dead))
|
.filter(|(_, _, _, _, health, _, _, _, _)| health.map_or(true, |h| !h.is_dead))
|
||||||
.for_each(|(entity, pos, _, body, _, inventory, scale, collider)| {
|
.filter(|(_, _, _, _, _, _, _, _, obj)| !self.should_flicker(*time, *obj))
|
||||||
|
.for_each(|(entity, pos, _, body, _, inventory, scale, collider, _)| {
|
||||||
if let Some((bound, model, _)) = self.get_model_for_render(
|
if let Some((bound, model, _)) = self.get_model_for_render(
|
||||||
tick,
|
tick,
|
||||||
camera,
|
camera,
|
||||||
@ -6541,6 +6544,19 @@ impl FigureMgr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns `true` if an object should flicker because it's about to vanish
|
||||||
|
fn should_flicker(&self, time: Time, obj: Option<&Object>) -> bool {
|
||||||
|
if let Some(Object::DeleteAfter {
|
||||||
|
spawned_at,
|
||||||
|
timeout,
|
||||||
|
}) = obj
|
||||||
|
{
|
||||||
|
time.0 > spawned_at.0 + timeout.as_secs_f64() - 10.0 && (time.0 * 8.0).fract() < 0.5
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render<'a>(
|
pub fn render<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
drawer: &mut FigureDrawer<'_, 'a>,
|
drawer: &mut FigureDrawer<'_, 'a>,
|
||||||
@ -6552,10 +6568,11 @@ impl FigureMgr {
|
|||||||
span!(_guard, "render", "FigureManager::render");
|
span!(_guard, "render", "FigureManager::render");
|
||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
|
|
||||||
|
let time = ecs.read_resource::<Time>();
|
||||||
let character_state_storage = state.read_storage::<CharacterState>();
|
let character_state_storage = state.read_storage::<CharacterState>();
|
||||||
let character_state = character_state_storage.get(viewpoint_entity);
|
let character_state = character_state_storage.get(viewpoint_entity);
|
||||||
let items = ecs.read_storage::<Item>();
|
let items = ecs.read_storage::<Item>();
|
||||||
for (entity, pos, body, _, inventory, scale, collider) in (
|
for (entity, pos, body, _, inventory, scale, collider, _) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
&ecs.read_storage::<Body>(),
|
&ecs.read_storage::<Body>(),
|
||||||
@ -6563,12 +6580,14 @@ impl FigureMgr {
|
|||||||
ecs.read_storage::<Inventory>().maybe(),
|
ecs.read_storage::<Inventory>().maybe(),
|
||||||
ecs.read_storage::<Scale>().maybe(),
|
ecs.read_storage::<Scale>().maybe(),
|
||||||
ecs.read_storage::<Collider>().maybe(),
|
ecs.read_storage::<Collider>().maybe(),
|
||||||
|
ecs.read_storage::<Object>().maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
// Don't render dead entities
|
// Don't render dead entities
|
||||||
.filter(|(_, _, _, health, _, _, _)| health.map_or(true, |h| !h.is_dead))
|
.filter(|(_, _, _, health, _, _, _, _)| health.map_or(true, |h| !h.is_dead))
|
||||||
// Don't render player
|
// Don't render player
|
||||||
.filter(|(entity, _, _, _, _, _, _)| *entity != viewpoint_entity)
|
.filter(|(entity, _, _, _, _, _, _, _)| *entity != viewpoint_entity)
|
||||||
|
.filter(|(_, _, _, _, _, _, _, obj)| !self.should_flicker(*time, *obj))
|
||||||
{
|
{
|
||||||
if let Some((bound, model, atlas)) = self.get_model_for_render(
|
if let Some((bound, model, atlas)) = self.get_model_for_render(
|
||||||
tick,
|
tick,
|
||||||
|
Loading…
Reference in New Issue
Block a user