refactor teleporter system and include nearby pets

This commit is contained in:
Maxicarlos08 2023-08-03 20:36:19 +02:00
parent 92ab8dab9a
commit 0c9a942027
No known key found for this signature in database
7 changed files with 68 additions and 77 deletions

View File

@ -693,7 +693,6 @@ void main() {
spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5) spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5)
); );
break; break;
<<<<<<< HEAD
case INK: case INK:
f_reflect = 0.0; // Magic water doesn't reflect light, it emits it f_reflect = 0.0; // Magic water doesn't reflect light, it emits it
float black_color = 0.3 + 0.2 * rand3 + 0.3 * max(floor(rand4 + 0.3), 0.0); float black_color = 0.3 + 0.2 * rand3 + 0.3 * max(floor(rand4 + 0.3), 0.0);
@ -703,7 +702,8 @@ void main() {
vec3(ink_size), vec3(ink_size),
vec4(0.5 * black_color, 0.75 * black_color, black_color, 1), vec4(0.5 * black_color, 0.75 * black_color, black_color, 1),
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9) spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
======= );
break;
case UPWARD_PORTAL_FIZZ: case UPWARD_PORTAL_FIZZ:
f_reflect = 0.0; f_reflect = 0.0;
attr = Attr( attr = Attr(
@ -711,7 +711,6 @@ void main() {
vec3(max(1.0, 0.05 * length(start_pos + inst_dir * percent()))), vec3(max(1.0, 0.05 * length(start_pos + inst_dir * percent()))),
vec4(vec3(1.23, 1.41, 1.44), 1.0),// * (1.0 - length(inst_dir) * 0.1), vec4(vec3(1.23, 1.41, 1.44), 1.0),// * (1.0 - length(inst_dir) * 0.1),
identity()//spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0) identity()//spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0)
>>>>>>> 70e6945e87 (portal particles)
); );
break; break;
default: default:

View File

@ -331,7 +331,7 @@ impl Body {
Body::LightningBolt => "lightning_bolt", Body::LightningBolt => "lightning_bolt",
Body::SpearIcicle => "spear_icicle", Body::SpearIcicle => "spear_icicle",
Body::Portal => "portal", Body::Portal => "portal",
Self::PortalActive => "portal_active", Body::PortalActive => "portal_active",
} }
} }

View File

@ -339,7 +339,7 @@ pub enum ServerEvent {
StartTeleporting { StartTeleporting {
entity: EcsEntity, entity: EcsEntity,
portal: EcsEntity, portal: EcsEntity,
} },
} }
pub struct EventBus<E> { pub struct EventBus<E> {

View File

@ -140,12 +140,9 @@ impl<'a> System<'a> for Sys {
}, },
ControlEvent::ActivatePortal(portal_uid) => { ControlEvent::ActivatePortal(portal_uid) => {
if let Some(portal) = read_data.id_maps.uid_entity(portal_uid) { if let Some(portal) = read_data.id_maps.uid_entity(portal_uid) {
server_emitter.emit(ServerEvent::StartTeleporting { server_emitter.emit(ServerEvent::StartTeleporting { entity, portal });
entity,
portal,
});
} }
} },
} }
} }
} }

View File

@ -1693,10 +1693,9 @@ pub fn handle_start_teleporting(server: &mut Server, entity: EcsEntity, portal:
) )
}) })
{ {
let _ = teleportings let _ = teleportings.insert(entity, comp::Teleporting {
.insert(entity, comp::Teleporting { portal,
portal, end_time: Time(end_time),
end_time: Time(end_time), });
});
} }
} }

View File

@ -1,15 +1,17 @@
use common::{ use common::{
comp::{object, Agent, Body, CharacterState, Pos, Teleporter, Teleporting}, comp::{object, Agent, Alignment, Body, CharacterState, Pos, Teleporter, Teleporting},
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
resources::Time, resources::Time,
uid::Uid,
CachedSpatialGrid, CachedSpatialGrid,
}; };
use common_ecs::{Origin, Phase, System}; use common_ecs::{Origin, Phase, System};
use specs::{Entities, Entity, Join, Read, ReadStorage, WriteStorage}; use specs::{Entities, Join, Read, ReadStorage, WriteStorage};
use vek::Vec3; use vek::Vec3;
pub const TELEPORT_RADIUS: f32 = 3.; pub const TELEPORT_RADIUS: f32 = 3.;
const MAX_AGGRO_DIST: f32 = 200.; // If an entity further than this is aggroed at a player, the portal will still work const MAX_AGGRO_DIST: f32 = 200.; // If an entity further than this is aggroed at a player, the portal will still work
const PET_TELEPORT_RADIUS: f32 = 20.;
#[derive(Default)] #[derive(Default)]
pub struct Sys; pub struct Sys;
@ -22,7 +24,9 @@ impl<'a> System<'a> for Sys {
type SystemData = ( type SystemData = (
Entities<'a>, Entities<'a>,
ReadStorage<'a, Pos>, ReadStorage<'a, Pos>,
ReadStorage<'a, Uid>,
ReadStorage<'a, Teleporter>, ReadStorage<'a, Teleporter>,
ReadStorage<'a, Alignment>,
ReadStorage<'a, Agent>, ReadStorage<'a, Agent>,
WriteStorage<'a, Teleporting>, WriteStorage<'a, Teleporting>,
ReadStorage<'a, Body>, ReadStorage<'a, Body>,
@ -41,7 +45,9 @@ impl<'a> System<'a> for Sys {
( (
entities, entities,
positions, positions,
uids,
teleporters, teleporters,
alignments,
agent, agent,
mut teleporting, mut teleporting,
bodies, bodies,
@ -64,44 +70,20 @@ impl<'a> System<'a> for Sys {
}) })
}; };
let mut teleporting_updates = Vec::new(); let mut cancel_teleporting = Vec::new();
for (portal_entity, teleporter_pos, body, teleporter) in for (portal_entity, teleporter_pos, body, _) in
(&entities, &positions, &bodies, &teleporters).join() (&entities, &positions, &bodies, &teleporters).join()
{ {
let nearby_entities = spatial_grid let is_active = spatial_grid
.0 .0
.in_circle_aabr(teleporter_pos.0.xy(), TELEPORT_RADIUS); .in_circle_aabr(teleporter_pos.0.xy(), TELEPORT_RADIUS)
.any(|entity| {
let mut is_active = false; (&positions, &teleporting)
for (entity, pos, character_state, teleporting) in
nearby_entities.filter_map(|entity| {
(
&entities,
&positions,
&character_states,
teleporting.maybe(),
)
.join() .join()
.get(entity, &entities) .get(entity, &entities)
.filter(|(_, pos, _, _)| in_portal_range(pos.0, teleporter_pos.0)) .map_or(false, |(pos, _)| in_portal_range(pos.0, teleporter_pos.0))
}) });
{
if !matches!(
character_state,
CharacterState::Idle(_) | CharacterState::Wielding(_)
) || (teleporter.requires_no_aggro && check_aggro(entity, pos.0))
{
if teleporting.is_some() {
teleporting_updates.push((entity, None));
};
continue;
}
is_active |= teleporting.is_some();
}
if (*body == Body::Object(object::Body::PortalActive)) != is_active { if (*body == Body::Object(object::Body::PortalActive)) != is_active {
event_bus.emit_now(ServerEvent::ChangeBody { event_bus.emit_now(ServerEvent::ChangeBody {
@ -115,41 +97,58 @@ impl<'a> System<'a> for Sys {
} }
} }
update_teleporting(&mut teleporting_updates, &mut teleporting); for (entity, uid, position, teleporting, character_state) in (
&entities,
for (entity, position, teleporting) in (&entities, &positions, &teleporting).join() { &uids,
let mut remove = || teleporting_updates.push((entity, None)); &positions,
&teleporting,
&character_states,
)
.join()
{
let portal_pos = positions.get(teleporting.portal); let portal_pos = positions.get(teleporting.portal);
let Some(teleporter) = teleporters.get(teleporting.portal) else { let Some(teleporter) = teleporters.get(teleporting.portal) else {
remove(); cancel_teleporting.push(entity);
continue continue
}; };
if portal_pos.map_or(true, |portal_pos| { if portal_pos.map_or(true, |portal_pos| {
!in_portal_range(position.0, portal_pos.0) !in_portal_range(position.0, portal_pos.0)
}) { }) || (teleporter.requires_no_aggro && check_aggro(entity, position.0))
remove(); || !matches!(
character_state,
CharacterState::Idle(_) | CharacterState::Wielding(_)
)
{
cancel_teleporting.push(entity);
} else if teleporting.end_time.0 <= time.0 { } else if teleporting.end_time.0 <= time.0 {
remove(); // Send teleport events for all nearby pets and the owner
event_bus.emit_now(ServerEvent::TeleportToPosition { let nearby = spatial_grid
entity, .0
position: teleporter.target, .in_circle_aabr(position.0.xy(), PET_TELEPORT_RADIUS)
}); .filter_map(|entity| {
(&entities, &positions, &alignments)
.join()
.get(entity, &entities)
})
.filter_map(|(entity, entity_position, alignment)| {
(matches!(alignment, Alignment::Owned(entity_uid) if entity_uid == uid)
&& entity_position.0.distance_squared(position.0)
<= PET_TELEPORT_RADIUS.powi(2))
.then_some(entity)
});
for entity in nearby {
cancel_teleporting.push(entity);
event_bus.emit_now(ServerEvent::TeleportToPosition {
entity,
position: teleporter.target,
});
}
} }
} }
update_teleporting(&mut teleporting_updates, &mut teleporting); for entity in cancel_teleporting {
}
}
fn update_teleporting(
updates: &mut Vec<(Entity, Option<Teleporting>)>,
teleporting: &mut WriteStorage<'_, Teleporting>,
) {
for (entity, update) in updates.drain(..) {
if let Some(add) = update {
let _ = teleporting.insert(entity, add);
} else {
let _ = teleporting.remove(entity); let _ = teleporting.remove(entity);
} }
} }

View File

@ -1029,10 +1029,7 @@ impl PlayState for SessionState {
Interactable::Entity(entity) => { Interactable::Entity(entity) => {
let body = client let body = client
.state() .state()
.ecs() .read_component_cloned::<comp::Body>(*entity);
.read_storage::<comp::Body>()
.get(*entity)
.map(ToOwned::to_owned);
if client if client
.state() .state()