aboutsummaryrefslogtreecommitdiffstats
path: root/src/shared/ability.rs
diff options
context:
space:
mode:
authorLibravatar Alexander Foremny <aforemny@posteo.de>2024-03-19 05:14:57 +0100
committerLibravatar Alexander Foremny <aforemny@posteo.de>2024-03-19 05:14:57 +0100
commit6805c6db39c1a9409b39aaf601f78db92b684c0d (patch)
tree2f9657d97c3b188a82c07cf228c9def712223414 /src/shared/ability.rs
parentee2bc9dca88e52b92a49a9ff21db8832b3b66255 (diff)
feat: pull ability
Diffstat (limited to 'src/shared/ability.rs')
-rw-r--r--src/shared/ability.rs122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/shared/ability.rs b/src/shared/ability.rs
index e8b2a26..2c581e7 100644
--- a/src/shared/ability.rs
+++ b/src/shared/ability.rs
@@ -51,6 +51,7 @@ pub enum ActivatedAbility {
#[derive(Copy, Clone, PartialEq, Debug, Deserialize, Serialize)]
pub enum DirectionalAbility {
Dash,
+ Pull,
Spear,
}
@@ -62,6 +63,7 @@ impl DirectionalAbility {
pub fn activate(self) -> DirectionalAbilityActivation {
match self {
DirectionalAbility::Dash => DirectionalAbilityActivation(dash_activation),
+ DirectionalAbility::Pull => DirectionalAbilityActivation(pull_activation),
DirectionalAbility::Spear => DirectionalAbilityActivation(spear_activation),
}
}
@@ -159,6 +161,126 @@ pub fn dash_collision(
}
}
+fn pull_activation(commands: &mut Commands, source_player: PlayerId, direction: Vec2) {
+ commands.add(move |world: &mut World| {
+ world.run_system_once(
+ move |players: Query<(Entity, &PlayerId)>,
+ mut set: ParamSet<(
+ Query<&mut PlayerPosition>,
+ Query<(&PlayerId, &PlayerPosition)>,
+ )>| {
+ let Some(source_entity) = ({
+ let mut source_entity = None;
+ for (entity, player_id) in players.iter() {
+ if *player_id != source_player {
+ continue;
+ }
+ source_entity = Some(entity);
+ break;
+ }
+ source_entity
+ }) else {
+ return;
+ };
+
+ let Some(source_position) = ({
+ let positions = set.p0();
+ if let Ok(position) = positions.get(source_entity) {
+ Some(*position)
+ } else {
+ None
+ }
+ }) else {
+ return;
+ };
+
+ let Some((target_player, _, pull_end)) = ({
+ let pull_targets = set.p1();
+ pull_collision(
+ source_player,
+ source_position.0,
+ direction,
+ 150.,
+ &pull_targets,
+ )
+ }) else {
+ return;
+ };
+
+ let Some(target_entity) = ({
+ let mut target_entity = None;
+ for (entity, player_id) in players.iter() {
+ if *player_id != target_player {
+ continue;
+ }
+ target_entity = Some(entity);
+ break;
+ }
+ target_entity
+ }) else {
+ return;
+ };
+
+ let mut positions = set.p0();
+ if let Ok(mut position) = positions.get_mut(target_entity) {
+ position.0 = pull_end;
+ }
+ },
+ )
+ });
+}
+
+pub fn pull_collision(
+ source_id: PlayerId,
+ pull_start: Vec2,
+ pull_direction: Vec2,
+ pull_max_distance: f32,
+ player_positions: &Query<(&PlayerId, &PlayerPosition)>,
+) -> Option<(PlayerId, Vec2, Vec2)> {
+ let mut pull_collision = pull_max_distance * pull_direction;
+ let mut pull_player_id = None;
+ let mut pull_player_position = None;
+ for (player_id, position) in player_positions.iter() {
+ if *player_id == source_id {
+ continue;
+ }
+
+ let player_position = position.0 - pull_start;
+ let player_projection = player_position.project_onto(pull_collision);
+ let player_rejection = player_position - player_projection;
+ let scalar_factor = player_projection.dot(pull_collision).signum()
+ * player_projection.length()
+ / pull_collision.length();
+
+ if scalar_factor < 0. || scalar_factor > 1.0 {
+ continue;
+ }
+
+ if player_rejection.length() < 2. * PLAYER_RADIUS {
+ pull_player_id = Some(player_id);
+ pull_player_position = Some(position.0);
+ pull_collision = player_projection;
+ }
+ }
+
+ if let Some(target_id) = pull_player_id {
+ if let Some(target_position) = pull_player_position {
+ let pull_direction = pull_start - target_position;
+ Some((
+ *target_id,
+ target_position,
+ target_position
+ + (pull_direction.length() - 2. * PLAYER_RADIUS)
+ * pull_direction.normalize_or_zero(),
+ ))
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+}
+
fn spear_activation(commands: &mut Commands, source_player: PlayerId, direction: Vec2) {
commands.add(move |world: &mut World| {
world.run_system_once(