diff --git a/assets/common/abilities/adlet/icepicker/leap.ron b/assets/common/abilities/adlet/icepicker/leap.ron index 59dc111fe7..9357edf48c 100644 --- a/assets/common/abilities/adlet/icepicker/leap.ron +++ b/assets/common/abilities/adlet/icepicker/leap.ron @@ -12,8 +12,8 @@ LeapMelee( energy_regen: 0, ), range: 4, - angle: 30, + angle: 360, ), - forward_leap_strength: 18, - vertical_leap_strength: 8, + forward_leap_strength: 24, + vertical_leap_strength: 16, ) diff --git a/server/agent/src/action_nodes.rs b/server/agent/src/action_nodes.rs index 712f28a267..77603b387a 100644 --- a/server/agent/src/action_nodes.rs +++ b/server/agent/src/action_nodes.rs @@ -1463,16 +1463,11 @@ impl<'a> AgentData<'a> { Tactic::AdletHunter => { self.handle_adlet_hunter(agent, controller, &attack_data, tgt_data, read_data, rng) }, - Tactic::AdletIcepicker => self.handle_adlet_icepicker( - agent, - controller, - &attack_data, - tgt_data, - read_data, - rng, - ), + Tactic::AdletIcepicker => { + self.handle_adlet_icepicker(agent, controller, &attack_data, tgt_data, read_data) + }, Tactic::AdletTracker => { - self.handle_adlet_tracker(agent, controller, &attack_data, tgt_data, read_data, rng) + self.handle_adlet_tracker(agent, controller, &attack_data, tgt_data, read_data) }, } } diff --git a/server/agent/src/attack.rs b/server/agent/src/attack.rs index 2a03424c19..28354974f4 100644 --- a/server/agent/src/attack.rs +++ b/server/agent/src/attack.rs @@ -4578,6 +4578,13 @@ impl<'a> AgentData<'a> { read_data: &ReadData, rng: &mut impl Rng, ) { + const ROTATE_TIMER: usize = 0; + const ROTATE_DIR_CONDITION: usize = 0; + agent.action_state.timers[ROTATE_TIMER] -= read_data.dt.0; + if agent.action_state.timers[ROTATE_TIMER] < 0.0 { + agent.action_state.conditions[ROTATE_DIR_CONDITION] = rng.gen_bool(0.5); + agent.action_state.timers[ROTATE_TIMER] = rng.gen::() * 5.0; + } let primary = self.extract_ability(AbilityInput::Primary); let secondary = self.extract_ability(AbilityInput::Secondary); let could_use_input = |input| match input { @@ -4608,6 +4615,21 @@ impl<'a> AgentData<'a> { Path::Separate, None, ); + } else { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); + let dir = if agent.action_state.conditions[ROTATE_DIR_CONDITION] { + 1.0 + } else { + -1.0 + }; + controller.inputs.move_dir.rotate_z(PI / 2.0 * dir); } } @@ -4618,8 +4640,38 @@ impl<'a> AgentData<'a> { attack_data: &AttackData, tgt_data: &TargetData, read_data: &ReadData, - rng: &mut impl Rng, ) { + let primary = self.extract_ability(AbilityInput::Primary); + let secondary = self.extract_ability(AbilityInput::Secondary); + let could_use_input = |input| match input { + InputKind::Primary => primary.as_ref().map_or(false, |p| { + p.could_use(attack_data, self, tgt_data, read_data, 0.0) + }), + InputKind::Secondary => secondary.as_ref().map_or(false, |s| { + s.could_use(attack_data, self, tgt_data, read_data, 0.0) + }), + _ => false, + }; + let move_forwards = if could_use_input(InputKind::Primary) { + controller.push_basic_input(InputKind::Primary); + false + } else if could_use_input(InputKind::Secondary) && attack_data.dist_sqrd > 5_f32.powi(2) { + controller.push_basic_input(InputKind::Secondary); + false + } else { + true + }; + + if move_forwards && attack_data.dist_sqrd > 2_f32.powi(2) { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); + } } pub fn handle_adlet_tracker( @@ -4629,7 +4681,38 @@ impl<'a> AgentData<'a> { attack_data: &AttackData, tgt_data: &TargetData, read_data: &ReadData, - rng: &mut impl Rng, ) { + const TRAP_TIMER: usize = 0; + agent.action_state.timers[TRAP_TIMER] += read_data.dt.0; + if agent.action_state.timers[TRAP_TIMER] > 20.0 { + agent.action_state.timers[TRAP_TIMER] = 0.0; + } + let primary = self.extract_ability(AbilityInput::Primary); + let could_use_input = |input| match input { + InputKind::Primary => primary.as_ref().map_or(false, |p| { + p.could_use(attack_data, self, tgt_data, read_data, 0.0) + }), + _ => false, + }; + let move_forwards = if agent.action_state.timers[TRAP_TIMER] < 3.0 { + controller.push_basic_input(InputKind::Secondary); + false + } else if could_use_input(InputKind::Primary) { + controller.push_basic_input(InputKind::Primary); + false + } else { + true + }; + + if move_forwards && attack_data.dist_sqrd > 2_f32.powi(2) { + self.path_toward_target( + agent, + controller, + tgt_data.pos.0, + read_data, + Path::Separate, + None, + ); + } } } diff --git a/server/agent/src/data.rs b/server/agent/src/data.rs index a1cf709f3d..92f0f0bcee 100644 --- a/server/agent/src/data.rs +++ b/server/agent/src/data.rs @@ -347,6 +347,14 @@ pub enum AbilityData { range: f32, angle: f32, }, + LeapMelee { + energy: f32, + range: f32, + angle: f32, + forward_leap: f32, + vertical_leap: f32, + leap_dur: f32, + }, } impl AbilityData { @@ -486,6 +494,21 @@ impl AbilityData { range: melee_constructor.range, angle: melee_constructor.angle, }, + LeapMelee { + energy_cost, + movement_duration, + melee_constructor, + forward_leap_strength, + vertical_leap_strength, + .. + } => Self::LeapMelee { + energy: *energy_cost, + leap_dur: *movement_duration, + range: melee_constructor.range, + angle: melee_constructor.angle, + forward_leap: *forward_leap_strength, + vertical_leap: *vertical_leap_strength, + }, _ => return None, }; Some(inner) @@ -503,6 +526,14 @@ impl AbilityData { let range_inc = forced_movement.map_or(0.0, |fm| match fm { ForcedMovement::Forward(speed) => speed * 15.0, ForcedMovement::Reverse(speed) => -speed, + ForcedMovement::Leap { + vertical, forward, .. + } => { + let dur = vertical * 2.0 / GRAVITY; + // 0.8 factor to allow for fact that agent looks down as they approach, so won't + // go as far + forward * dur * 0.8 + }, _ => 0.0, }); let body_rad = agent_data.body.map_or(0.0, |b| b.max_radius()); @@ -646,6 +677,23 @@ impl AbilityData { range, angle, } => melee_check(*range, *angle, None) && energy_check(*energy), + LeapMelee { + energy, + range, + angle, + leap_dur, + forward_leap, + vertical_leap, + } => { + use common::states::utils::MovementDirection; + let forced_move = Some(ForcedMovement::Leap { + vertical: *vertical_leap * *leap_dur * 2.0, + forward: *forward_leap, + progress: 0.0, + direction: MovementDirection::Look, + }); + melee_check(*range, *angle, forced_move) && energy_check(*energy) + }, } } } diff --git a/world/src/site2/plot/adlet.rs b/world/src/site2/plot/adlet.rs index 9d494e3ff1..be408076f4 100644 --- a/world/src/site2/plot/adlet.rs +++ b/world/src/site2/plot/adlet.rs @@ -193,7 +193,7 @@ impl AdletStronghold { let mut cavern_structures = Vec::<(AdletStructure, Vec2, Dir)>::new(); fn valid_cavern_struct_pos( - structures: &Vec<(AdletStructure, Vec2, Dir)>, + structures: &[(AdletStructure, Vec2, Dir)], structure: AdletStructure, rpos: Vec2, ) -> bool {