Merge branch 'synis/beam-aura-spatial-grid' into 'master'

Use SpatialGrid for Beam and Aura

See merge request veloren/veloren!2214
This commit is contained in:
Imbris 2021-04-29 13:00:55 +00:00
commit 27fb8a9f6c
2 changed files with 48 additions and 27 deletions

View File

@ -22,6 +22,7 @@ pub struct ReadData<'a> {
dt: Read<'a, DeltaTime>, dt: Read<'a, DeltaTime>,
server_bus: Read<'a, EventBus<ServerEvent>>, server_bus: Read<'a, EventBus<ServerEvent>>,
uid_allocator: Read<'a, UidAllocator>, uid_allocator: Read<'a, UidAllocator>,
cached_spatial_grid: Read<'a, common::CachedSpatialGrid>,
positions: ReadStorage<'a, Pos>, positions: ReadStorage<'a, Pos>,
char_states: ReadStorage<'a, CharacterState>, char_states: ReadStorage<'a, CharacterState>,
healths: ReadStorage<'a, Health>, healths: ReadStorage<'a, Health>,
@ -81,15 +82,25 @@ impl<'a> System<'a> for Sys {
expired_auras.push(key); expired_auras.push(key);
} }
} }
for (target, target_pos, mut target_buffs, health, target_uid) in ( let target_iter = read_data
&read_data.entities, .cached_spatial_grid
&read_data.positions, .0
&mut buffs, .in_circle_aabr(pos.0.xy(), aura.radius)
&read_data.healths, .filter_map(|target| {
&read_data.uids, read_data
) .positions
.join() .get(target)
{ .and_then(|l| read_data.healths.get(target).map(|r| (l, r)))
.and_then(|l| read_data.uids.get(target).map(|r| (l, r)))
.map(|((target_pos, health), target_uid)| {
(target, target_pos, health, target_uid)
})
});
target_iter.for_each(|(target, target_pos, health, target_uid)| {
let mut target_buffs = match buffs.get_mut(target) {
Some(buff) => buff,
None => return,
};
// Ensure entity is within the aura radius // Ensure entity is within the aura radius
if target_pos.0.distance_squared(pos.0) < aura.radius.powi(2) { if target_pos.0.distance_squared(pos.0) < aura.radius.powi(2) {
if let AuraTarget::GroupOf(uid) = aura.target { if let AuraTarget::GroupOf(uid) = aura.target {
@ -103,7 +114,7 @@ impl<'a> System<'a> for Sys {
|| *target_uid == uid; || *target_uid == uid;
if !same_group { if !same_group {
continue; return;
} }
} }
@ -127,8 +138,9 @@ impl<'a> System<'a> for Sys {
_ => true, _ => true,
}; };
if apply_buff { if apply_buff {
// Checks that target is not already receiving a buff from an // Checks that target is not already receiving a buff from
// aura, where the buff is of the same kind, and is of at least // an aura, where
// the buff is of the same kind, and is of at least
// the same strength and of at least the same duration // the same strength and of at least the same duration
// If no such buff is present, adds the buff // If no such buff is present, adds the buff
let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| { let emit_buff = !target_buffs.buffs.iter().any(|(_, buff)| {
@ -152,7 +164,8 @@ impl<'a> System<'a> for Sys {
)), )),
}); });
} }
// Finds all buffs on target that are from an aura, are of the // Finds all buffs on target that are from an aura, are of
// the
// same buff kind, and are of at most the same strength // same buff kind, and are of at most the same strength
// For any such buffs, marks it as recently applied // For any such buffs, marks it as recently applied
for (_, buff) in for (_, buff) in
@ -175,7 +188,7 @@ impl<'a> System<'a> for Sys {
}, },
} }
} }
} });
} }
if !expired_auras.is_empty() { if !expired_auras.is_empty() {
server_emitter.emit(ServerEvent::Aura { server_emitter.emit(ServerEvent::Aura {

View File

@ -29,6 +29,7 @@ pub struct ReadData<'a> {
dt: Read<'a, DeltaTime>, dt: Read<'a, DeltaTime>,
terrain: ReadExpect<'a, TerrainGrid>, terrain: ReadExpect<'a, TerrainGrid>,
uid_allocator: Read<'a, UidAllocator>, uid_allocator: Read<'a, UidAllocator>,
cached_spatial_grid: Read<'a, common::CachedSpatialGrid>,
uids: ReadStorage<'a, Uid>, uids: ReadStorage<'a, Uid>,
positions: ReadStorage<'a, Pos>, positions: ReadStorage<'a, Pos>,
orientations: ReadStorage<'a, Ori>, orientations: ReadStorage<'a, Ori>,
@ -122,19 +123,26 @@ impl<'a> System<'a> for Sys {
return (server_events, add_hit_entities, outcomes); return (server_events, add_hit_entities, outcomes);
}; };
// Go through all other effectable entities // Go through all affectable entities by querying the spatial grid
for (target, uid_b, pos_b, health_b, body_b) in ( let target_iter = read_data
&read_data.entities, .cached_spatial_grid
&read_data.uids, .0
&read_data.positions, .in_circle_aabr(pos.0.xy(), frame_end_dist - frame_start_dist)
&read_data.healths, .filter_map(|target|{
&read_data.bodies, read_data
) .positions
.join() .get(target)
{ .and_then(|l| read_data.healths.get(target).map(|r| (l,r)))
.and_then(|l| read_data.uids.get(target).map(|r| (l,r)))
.and_then(|l| read_data.bodies.get(target).map(|r| (l,r)))
.map(|(((pos_b, health_b), uid_b), body_b)| {
(target, uid_b, pos_b, health_b, body_b)
})
});
target_iter.for_each(|(target, uid_b, pos_b, health_b, body_b)| {
// Check to see if entity has already been hit recently // Check to see if entity has already been hit recently
if hit_entities.iter().any(|&uid| uid == *uid_b) { if hit_entities.iter().any(|&uid| uid == *uid_b) {
continue; return;
} }
// Scales // Scales
@ -170,7 +178,7 @@ impl<'a> System<'a> for Sys {
// If owner, shouldn't heal or damage // If owner, shouldn't heal or damage
if Some(*uid_b) == beam_segment.owner { if Some(*uid_b) == beam_segment.owner {
continue; return;
} }
let attacker_info = let attacker_info =
@ -208,7 +216,7 @@ impl<'a> System<'a> for Sys {
add_hit_entities.push((beam_owner, *uid_b)); add_hit_entities.push((beam_owner, *uid_b));
} }
} });
(server_events, add_hit_entities, outcomes) (server_events, add_hit_entities, outcomes)
}).reduce(|| (Vec::new(), Vec::new(), Vec::new()), }).reduce(|| (Vec::new(), Vec::new(), Vec::new()),
|(mut events_a, mut hit_entities_a, mut outcomes_a), |(mut events_a, mut hit_entities_a, mut outcomes_a),