mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 17:21:49 -10:00
Allays fly: their travel is travelFlying and their stroll hovers
An allay stood on the ground and fell when the block under it broke: Mob.travel sent it down the ordinary air travel, which applies the 0.08 gravity attribute whenever noGravity is off. Vanilla's Allay.travel is travelFlying(input, getSpeed()) — a travel with no gravity term — so an allay hangs mid-air even before a goal moves it. - Family::Allay routes to allay::travel, which calls travelFlying with the move control's current speed (LivingEntity.speed), like Allay.travel(input, getSpeed()); travel_flying is split so the three speeds can differ per mob. - Stroll::flying picked a land position, so the stroll never produced a MoveTo mid-air. WaterAvoidingRandomFlyingGoal.getPosition tries HoverRandomPos (8, 7, pi/2, 3, 1) on the view direction, then AirAndWaterRandomPos (8, 4, -2); Stroll::flying now does the same. The wither registers the same vanilla goal and benefits equally. Verified against the mob_ai probe: an allay spawned at y=-55 stays at -55, then RandomStrollGoal fires and it drifts to air targets, never falling — where it used to drop to the ground. Fixes #2594. Co-Authored-By: Devin (SWE-2 High) <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
783577d2de
commit
c216561daa
4 files changed
+57
-5
No files matched your search
@@ -1511,6 +1511,7 @@ pub fn custom_travel(m: &mut Mob, w: &MobWorld, input: Vec3, events: &mut Vec<Mo
|
||||
Family::Guardian => super::guardian::travel(m, w, input, events),
|
||||
// Shulkers never move on their own.
|
||||
Family::Shulker => true,
|
||||
Family::Allay => super::allay::travel(m, w, input, events),
|
||||
Family::Vex => super::vex::travel(m),
|
||||
Family::Nautilus => super::nautilus::travel(m, w, input, events),
|
||||
_ => false,
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
//! blocks and bring them to their player (or a liked note block), dance to
|
||||
//! jukeboxes and duplicate when given an amethyst shard mid-dance.
|
||||
use super::{
|
||||
Mob,
|
||||
Mob, MobEvent, MobWorld,
|
||||
anim::{Poses, State},
|
||||
control::MoveKind,
|
||||
goals::{Cx, Goal, LookAtPlayer, MOVE, Panic, RandomLookAround, Stroll, goal_clone},
|
||||
nav::NavKind,
|
||||
};
|
||||
use horizon_core::geometry::Vec3;
|
||||
use horizon_core::geometry::trig::Mth;
|
||||
|
||||
// Allay state: `main_hand` the held item, `ints[1]` how many it carries,
|
||||
@@ -120,6 +121,14 @@ impl Goal for StayClose {
|
||||
}
|
||||
}
|
||||
}
|
||||
/// `Allay.travel`: `travelFlying(input, getSpeed())` — the airborne speed is
|
||||
/// the one the move control set this tick, and no gravity applies, so an
|
||||
/// allay never falls under its own travel.
|
||||
pub fn travel(m: &mut Mob, w: &MobWorld, input: Vec3, events: &mut Vec<MobEvent>) -> bool {
|
||||
let speed = m.ai.speed;
|
||||
m.travel_flying_speeds(w, input, events, 0.02, 0.02, speed);
|
||||
true
|
||||
}
|
||||
/// `Allay.aiStep` / `tick`: healing, cooldowns, the hold and spin clocks.
|
||||
pub fn ai_step(m: &mut Mob) {
|
||||
if m.alive() && m.age.is_multiple_of(10) {
|
||||
|
||||
@@ -734,6 +734,8 @@ pub struct Stroll {
|
||||
pub water_avoiding: Option<f32>,
|
||||
/// RandomSwimmingGoal: BehaviorUtils.getRandomSwimmablePos.
|
||||
pub swim: bool,
|
||||
/// WaterAvoidingRandomFlyingGoal: a hover spot, else an air or water pos.
|
||||
pub flying: bool,
|
||||
pub force: bool,
|
||||
wanted: [f64; 3],
|
||||
}
|
||||
@@ -745,6 +747,7 @@ impl Stroll {
|
||||
check_no_action: true,
|
||||
water_avoiding: None,
|
||||
swim: false,
|
||||
flying: false,
|
||||
force: false,
|
||||
wanted: [0.0; 3],
|
||||
}
|
||||
@@ -761,7 +764,10 @@ impl Stroll {
|
||||
}
|
||||
/// WaterAvoidingRandomFlyingGoal (a nearby air position).
|
||||
pub fn flying(speed: f64) -> Self {
|
||||
Self::new(speed)
|
||||
Self {
|
||||
flying: true,
|
||||
..Self::new(speed)
|
||||
}
|
||||
}
|
||||
/// RandomSwimmingGoal(speed, interval)
|
||||
pub fn swimming(speed: f64, interval: i32) -> Self {
|
||||
@@ -822,6 +828,21 @@ impl Goal for Stroll {
|
||||
}
|
||||
p
|
||||
}
|
||||
None if self.flying => {
|
||||
// WaterAvoidingRandomFlyingGoal.getPosition.
|
||||
let [xd, _, zd] = m.view_vector();
|
||||
m.hover_random_pos(
|
||||
cx.w,
|
||||
8,
|
||||
7,
|
||||
xd,
|
||||
zd,
|
||||
f64::from(std::f32::consts::FRAC_PI_2),
|
||||
3,
|
||||
1,
|
||||
)
|
||||
.or_else(|| m.air_and_water_random_pos(cx.w, 8, 4, -2, xd, zd))
|
||||
}
|
||||
None => m.default_random_pos(cx.w, 10, 7),
|
||||
};
|
||||
let Some(p) = pos else { return false };
|
||||
|
||||
@@ -694,12 +694,33 @@ impl Mob {
|
||||
} else {
|
||||
0.02
|
||||
};
|
||||
self.travel_flying_speeds(
|
||||
w,
|
||||
input,
|
||||
events,
|
||||
fluid_speed,
|
||||
fluid_speed,
|
||||
self.kind.air_speed,
|
||||
);
|
||||
}
|
||||
/// `LivingEntity.travelFlying(input, waterSpeed, lavaSpeed, airSpeed)`:
|
||||
/// the speeds vary per mob (an allay flies at the speed its move control
|
||||
/// set, `Allay.travel`).
|
||||
pub fn travel_flying_speeds(
|
||||
&mut self,
|
||||
w: &MobWorld,
|
||||
input: Vec3,
|
||||
events: &mut Vec<MobEvent>,
|
||||
water_speed: f32,
|
||||
lava_speed: f32,
|
||||
air_speed: f32,
|
||||
) {
|
||||
let (speed, drag) = if self.fluids.in_water {
|
||||
(fluid_speed, f64::from(0.8_f32))
|
||||
(water_speed, f64::from(0.8_f32))
|
||||
} else if self.fluids.in_lava {
|
||||
(fluid_speed, 0.5)
|
||||
(lava_speed, 0.5)
|
||||
} else {
|
||||
(self.kind.air_speed, f64::from(0.91_f32))
|
||||
(air_speed, f64::from(0.91_f32))
|
||||
};
|
||||
self.move_relative(speed, input);
|
||||
self.do_move(w, events);
|
||||
|
||||
Reference in new issue
Block a user