mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
addressed review comments
This commit is contained in:
parent
e5fe64ccf6
commit
8fe5f2e708
@ -34,7 +34,7 @@ pub mod projectile;
|
||||
pub mod shockwave;
|
||||
pub mod skillset;
|
||||
mod stats;
|
||||
mod teleport;
|
||||
pub mod teleport;
|
||||
pub mod visual;
|
||||
|
||||
// Reexports
|
||||
|
@ -4,6 +4,11 @@ use vek::Vec3;
|
||||
|
||||
use crate::resources::{Secs, Time};
|
||||
|
||||
pub enum TeleporterEvent {
|
||||
PortalTeleport { entity: Entity, target: Vec3<f32> },
|
||||
SetPortalActive { portal: Entity, active: bool },
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Teleporter {
|
||||
pub target: Vec3<f32>,
|
||||
|
@ -332,6 +332,7 @@ pub enum ServerEvent {
|
||||
RemoveLightEmitter {
|
||||
entity: EcsEntity,
|
||||
},
|
||||
PortalEvent(comp::teleport::TeleporterEvent),
|
||||
}
|
||||
|
||||
pub struct EventBus<E> {
|
||||
|
@ -21,6 +21,8 @@ use common::{
|
||||
inventory::item::{AbilityMap, MaterialStatManifest},
|
||||
item::flatten_counted_items,
|
||||
loot_owner::LootOwnerKind,
|
||||
object,
|
||||
teleport::TeleporterEvent,
|
||||
Alignment, Auras, Body, CharacterState, Energy, Group, Health, HealthChange, Inventory,
|
||||
Player, Poise, Pos, SkillSet, Stats,
|
||||
},
|
||||
@ -1656,3 +1658,31 @@ pub fn handle_remove_light_emitter(server: &mut Server, entity: EcsEntity) {
|
||||
.write_storage::<comp::LightEmitter>()
|
||||
.remove(entity);
|
||||
}
|
||||
|
||||
pub fn handle_portal_event(server: &mut Server, event: TeleporterEvent) {
|
||||
let ecs = server.state.ecs();
|
||||
|
||||
match event {
|
||||
TeleporterEvent::PortalTeleport { entity, target } => {
|
||||
ecs.write_storage::<comp::Pos>()
|
||||
.get_mut(entity)
|
||||
.map(|old_position| {
|
||||
old_position.0 = target;
|
||||
});
|
||||
ecs.write_storage::<comp::ForceUpdate>()
|
||||
.get_mut(entity)
|
||||
.map(|forced_update| forced_update.update());
|
||||
},
|
||||
TeleporterEvent::SetPortalActive { portal, active } => {
|
||||
ecs.write_storage::<comp::Body>()
|
||||
.get_mut(portal)
|
||||
.map(|mut body| {
|
||||
*body = comp::body::Body::Object(if active {
|
||||
object::Body::PortalActive
|
||||
} else {
|
||||
object::Body::Portal
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
events::{
|
||||
entity_creation::handle_create_teleporter,
|
||||
entity_manipulation::handle_portal_event,
|
||||
interaction::{handle_mount_volume, handle_tame_pet},
|
||||
},
|
||||
persistence::PersistedComponents,
|
||||
@ -299,6 +300,7 @@ impl Server {
|
||||
ServerEvent::RemoveLightEmitter { entity } => {
|
||||
handle_remove_light_emitter(self, entity)
|
||||
},
|
||||
ServerEvent::PortalEvent(event) => handle_portal_event(self, event),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,10 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use common::{
|
||||
comp::{
|
||||
ability::AbilityMeta, object, Agent, Body, CharacterState, ForceUpdate, Player, Pos,
|
||||
Teleporter, Teleporting,
|
||||
object, teleport::TeleporterEvent, Agent, Body, CharacterState, Player, Pos, Teleporter,
|
||||
Teleporting,
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
resources::Time,
|
||||
states::{
|
||||
blink,
|
||||
utils::{AbilityInfo, StageSection},
|
||||
},
|
||||
CachedSpatialGrid,
|
||||
};
|
||||
use common_ecs::{Origin, Phase, System};
|
||||
@ -29,16 +24,16 @@ fn in_portal_range(player_pos: Vec3<f32>, portal_pos: Vec3<f32>) -> bool {
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
WriteStorage<'a, Pos>,
|
||||
ReadStorage<'a, Pos>,
|
||||
ReadStorage<'a, Player>,
|
||||
ReadStorage<'a, Teleporter>,
|
||||
ReadStorage<'a, Agent>,
|
||||
WriteStorage<'a, ForceUpdate>,
|
||||
WriteStorage<'a, Teleporting>,
|
||||
WriteStorage<'a, Body>,
|
||||
WriteStorage<'a, CharacterState>,
|
||||
ReadStorage<'a, Body>,
|
||||
ReadStorage<'a, CharacterState>,
|
||||
Read<'a, CachedSpatialGrid>,
|
||||
Read<'a, Time>,
|
||||
Read<'a, EventBus<ServerEvent>>,
|
||||
);
|
||||
|
||||
const NAME: &'static str = "teleporter";
|
||||
@ -49,26 +44,23 @@ impl<'a> System<'a> for Sys {
|
||||
_job: &mut common_ecs::Job<Self>,
|
||||
(
|
||||
entities,
|
||||
mut positions,
|
||||
positions,
|
||||
players,
|
||||
teleporters,
|
||||
agent,
|
||||
mut forced_update,
|
||||
mut teleporting,
|
||||
mut bodies,
|
||||
mut character_states,
|
||||
bodies,
|
||||
character_states,
|
||||
spatial_grid,
|
||||
time,
|
||||
event_bus,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let mut attempt_teleport = vec![];
|
||||
let mut cancel_teleport = vec![];
|
||||
|
||||
let mut player_data = (
|
||||
&entities,
|
||||
&positions,
|
||||
&players,
|
||||
&mut character_states,
|
||||
&character_states,
|
||||
teleporting.entries(),
|
||||
)
|
||||
.join();
|
||||
@ -86,8 +78,8 @@ impl<'a> System<'a> for Sys {
|
||||
})
|
||||
};
|
||||
|
||||
for (portal_entity, teleporter_pos, mut body, teleporter) in
|
||||
(&entities, &positions, &mut bodies, &teleporters).join()
|
||||
for (portal_entity, teleporter_pos, body, teleporter) in
|
||||
(&entities, &positions, &bodies, &teleporters).join()
|
||||
{
|
||||
let nearby_entities = spatial_grid
|
||||
.0
|
||||
@ -95,7 +87,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
let mut is_active = false;
|
||||
|
||||
for (entity, pos, _, mut character_state, teleporting) in
|
||||
for (entity, pos, _, character_state, teleporting) in
|
||||
nearby_entities.filter_map(|entity| {
|
||||
player_data
|
||||
.get(entity, &entities)
|
||||
@ -104,7 +96,11 @@ impl<'a> System<'a> for Sys {
|
||||
})
|
||||
})
|
||||
{
|
||||
if teleporter.requires_no_aggro && check_aggro(entity, pos.0) {
|
||||
if !matches!(
|
||||
character_state,
|
||||
CharacterState::Idle(_) | CharacterState::Wielding(_)
|
||||
) || (teleporter.requires_no_aggro && check_aggro(entity, pos.0))
|
||||
{
|
||||
if let StorageEntry::Occupied(entry) = teleporting {
|
||||
entry.remove();
|
||||
};
|
||||
@ -118,81 +114,40 @@ impl<'a> System<'a> for Sys {
|
||||
portal: portal_entity,
|
||||
end_time: Time(time.0 + teleporter.buildup_time.0),
|
||||
});
|
||||
} else if let Some(remaining) = if let StorageEntry::Occupied(entry) = teleporting {
|
||||
let teleporting = entry.get();
|
||||
((time.0 - teleporting.teleport_start.0) >= teleporter.buildup_time.0 / 3.
|
||||
&& !matches!(*character_state, CharacterState::Blink(_)))
|
||||
.then_some(teleporter.buildup_time.0 - (time.0 - teleporting.teleport_start.0))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
// Move into blink character state at half buildup time
|
||||
*character_state = CharacterState::Blink(blink::Data {
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Buildup,
|
||||
static_data: blink::StaticData {
|
||||
buildup_duration: Duration::from_secs_f64(remaining),
|
||||
recover_duration: Duration::default(),
|
||||
max_range: 0.,
|
||||
ability_info: AbilityInfo {
|
||||
tool: None,
|
||||
hand: None,
|
||||
input: common::comp::InputKind::Primary,
|
||||
ability_meta: AbilityMeta::default(),
|
||||
ability: None,
|
||||
input_attr: None,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
is_active = true;
|
||||
}
|
||||
|
||||
if (*body == Body::Object(object::Body::PortalActive)) != is_active {
|
||||
*body = Body::Object(if is_active {
|
||||
object::Body::PortalActive
|
||||
} else {
|
||||
object::Body::Portal
|
||||
});
|
||||
event_bus.emit_now(ServerEvent::PortalEvent(TeleporterEvent::SetPortalActive {
|
||||
portal: portal_entity,
|
||||
active: is_active,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
for (entity, position, _, teleporting) in
|
||||
(&entities, &positions, &players, &teleporting).join()
|
||||
for (entity, position, _, teleporting_entry) in
|
||||
(&entities, &positions, &players, teleporting.entries()).join()
|
||||
{
|
||||
let portal_pos = positions.get(teleporting.portal);
|
||||
let Some(teleporter) = teleporters.get(teleporting.portal) else {
|
||||
cancel_teleport.push(entity);
|
||||
let StorageEntry::Occupied(teleporting) = teleporting_entry else { continue };
|
||||
let portal_pos = positions.get(teleporting.get().portal);
|
||||
let Some(teleporter) = teleporters.get(teleporting.get().portal) else {
|
||||
teleporting.remove();
|
||||
continue
|
||||
};
|
||||
|
||||
if portal_pos.map_or(true, |portal_pos| {
|
||||
!in_portal_range(position.0, portal_pos.0)
|
||||
}) {
|
||||
cancel_teleport.push(entity);
|
||||
} else if teleporting.end_time.0 <= time.0 {
|
||||
attempt_teleport.push((entity, *teleporter));
|
||||
cancel_teleport.push(entity);
|
||||
teleporting.remove();
|
||||
} else if teleporting.get().end_time.0 <= time.0 {
|
||||
teleporting.remove();
|
||||
event_bus.emit_now(ServerEvent::PortalEvent(TeleporterEvent::PortalTeleport {
|
||||
entity,
|
||||
target: teleporter.target,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
for entity in cancel_teleport {
|
||||
teleporting.remove(entity);
|
||||
character_states.get_mut(entity).map(|mut state| {
|
||||
if let CharacterState::Blink(data) = &mut *state {
|
||||
data.stage_section = StageSection::Recover;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (entity, teleporter) in attempt_teleport {
|
||||
positions
|
||||
.get_mut(entity)
|
||||
.map(|position| position.0 = teleporter.target);
|
||||
forced_update
|
||||
.get_mut(entity)
|
||||
.map(|forced_update| forced_update.update());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1047,16 +1047,6 @@ impl Floor {
|
||||
let tiles = Arc::clone(&tiles);
|
||||
make_wall_contours(tiles, floor_corner, floor_z, wall_thickness, tunnel_height)
|
||||
}));
|
||||
let walls_fat = painter.prim(Primitive::sampling(floor_prim, {
|
||||
let tiles = Arc::clone(&tiles);
|
||||
make_wall_contours(
|
||||
tiles,
|
||||
floor_corner,
|
||||
floor_z,
|
||||
wall_thickness - 1.,
|
||||
tunnel_height + 1.,
|
||||
)
|
||||
}));
|
||||
|
||||
// The surface 1 unit thicker than the walls is used to place the torches onto
|
||||
let wall_contour_surface = painter.prim(Primitive::sampling(floor_prim, {
|
||||
@ -1123,13 +1113,10 @@ impl Floor {
|
||||
.without(lighting_mask_x.intersect(lighting_mask_y))
|
||||
};
|
||||
|
||||
let walls_only = painter.prim(Primitive::without(wall_contours, walls_fat));
|
||||
|
||||
// Declare collections of various disjoint primitives that need postprocessing
|
||||
// after handling all the local information per-tile
|
||||
let mut stairs_bb = Vec::new();
|
||||
let mut stairs = Vec::new();
|
||||
let mut stair_walls = Vec::new();
|
||||
let mut pillars = Vec::new();
|
||||
let mut boss_room_center = None;
|
||||
let mut sprites = Vec::new();
|
||||
@ -1159,10 +1146,9 @@ impl Floor {
|
||||
outer_tile_aabr(0),
|
||||
floor_z - 2..(floor_z + tunnel_height as i32) + 2,
|
||||
)));
|
||||
let walls_in_tile = painter.prim(Primitive::intersect(outer_tile_aabb, walls_only));
|
||||
|
||||
// Fill Walls
|
||||
painter.fill(walls_in_tile, Fill::Block(stone_wall));
|
||||
painter.fill(outer_tile_aabb, Fill::Block(stone_wall));
|
||||
|
||||
let tile_floor_fill = painter.prim(Primitive::Aabb(aabr_with_z(
|
||||
tile_aabr,
|
||||
@ -1203,10 +1189,12 @@ impl Floor {
|
||||
StairsKind::Spiral => Primitive::Cylinder(aabb),
|
||||
StairsKind::WallSpiral => Primitive::Aabb(aabb),
|
||||
});
|
||||
let outer_bb = painter.prim(match kind {
|
||||
|
||||
painter.fill(painter.prim(match kind {
|
||||
StairsKind::WallSpiral => Primitive::Aabb(outer_aabb),
|
||||
StairsKind::Spiral => Primitive::Cylinder(outer_aabb),
|
||||
});
|
||||
}), Fill::Block(stone_wall));
|
||||
|
||||
let stair = painter.prim(Primitive::sampling(bb, match kind {
|
||||
StairsKind::Spiral => spiral_staircase(center, radius, 0.5, 9.0),
|
||||
StairsKind::WallSpiral => wall_staircase(center, radius, 27.0),
|
||||
@ -1231,7 +1219,6 @@ impl Floor {
|
||||
}
|
||||
lights = painter.prim(Primitive::intersect(lights, lighting_mask));
|
||||
stairs_bb.push(bb);
|
||||
stair_walls.push(outer_bb);
|
||||
stairs.push((stair, lights));
|
||||
}
|
||||
|
||||
@ -1395,14 +1382,10 @@ impl Floor {
|
||||
}
|
||||
|
||||
// Carve out space for the stairs
|
||||
for (stair_bb, outer_stairs_bb) in stairs_bb.iter().zip(stair_walls.iter()) {
|
||||
painter.fill(
|
||||
painter.prim(Primitive::without(*outer_stairs_bb, *stair_bb)),
|
||||
Fill::Block(stone_wall),
|
||||
);
|
||||
painter.fill(*stair_bb, Fill::Block(vacant));
|
||||
for stair_bb in stairs_bb {
|
||||
painter.fill(stair_bb, Fill::Block(vacant));
|
||||
// Prevent sprites from floating above the stairs
|
||||
let stair_bb_up = painter.prim(Primitive::translate(*stair_bb, Vec3::unit_z()));
|
||||
let stair_bb_up = painter.prim(Primitive::translate(stair_bb, Vec3::unit_z()));
|
||||
for (sprite, _) in sprites.iter_mut() {
|
||||
*sprite = painter.prim(Primitive::without(*sprite, stair_bb_up));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user