mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-10 02:21:33 -10:00
Test that a cave spider, husk and wither skeleton effect reaches a mob
doHurtTarget against mob 2 must carry poison 140 (normal), hunger 140 (effective difficulty 1.5) and wither 200 with the hit; without the fix the hit is a plain AttackMob and the mob keeps no effect (0 ticks). On easy the cave spider's timer is 0, so the hit stays plain.
This commit is contained in:
1 parent
e8191c9e8f
commit
713582bbdd
1 file changed
+119
@@ -2993,6 +2993,125 @@ mod poison_effect_tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod hit_effect_tests {
|
||||
use super::*;
|
||||
use crate::mobs::world::with_test_world;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The effects of a cave spider's bite, a bare-handed husk's blow and a
|
||||
/// wither skeleton's hit go to the `LivingEntity` the hit landed on:
|
||||
/// `doHurtTarget` tests `target instanceof LivingEntity`, not `Player`.
|
||||
/// Biting a mob carries the effect with the hit — poison for 140 ticks on
|
||||
/// normal, hunger for 140 (effective difficulty 1.5), wither for 200 —
|
||||
/// where the mob is hit 2. Without the fix each of these is a plain
|
||||
/// `AttackMob` and the mob keeps no effect at all (0 ticks).
|
||||
#[test]
|
||||
fn a_melee_effect_rides_the_hit_onto_a_mob() {
|
||||
let cases = [
|
||||
("minecraft:cave_spider", "minecraft:poison", 140),
|
||||
("minecraft:husk", "minecraft:hunger", 140),
|
||||
("minecraft:wither_skeleton", "minecraft:wither", 200),
|
||||
];
|
||||
let mut carried: Vec<(&str, Option<(u32, &'static str, i32, i32)>)> = Vec::new();
|
||||
let mut strays: Vec<(&str, bool, bool)> = Vec::new();
|
||||
let ran = with_test_world(&[], |w, types| {
|
||||
for (kind, _, _) in cases {
|
||||
let mut m = Mob::new(
|
||||
1,
|
||||
Arc::new(types.types[kind].clone()),
|
||||
Vec3::new(0.5, 64.0, 0.5),
|
||||
0.0,
|
||||
);
|
||||
let (mut lr, mut events) = (horizon_core::random::LegacyRandom::new(0), Vec::new());
|
||||
let mut cx = Cx {
|
||||
w,
|
||||
lr: &mut lr,
|
||||
events: &mut events,
|
||||
};
|
||||
do_hurt_target(&mut m, Who::Mob(2), &mut cx);
|
||||
carried.push((
|
||||
kind,
|
||||
events.iter().find_map(|e| match e {
|
||||
MobEvent::AttackMobWithEffect {
|
||||
target,
|
||||
effect,
|
||||
ticks,
|
||||
amplifier,
|
||||
..
|
||||
} => Some((*target, *effect, *ticks, *amplifier)),
|
||||
_ => None,
|
||||
}),
|
||||
));
|
||||
strays.push((
|
||||
kind,
|
||||
events
|
||||
.iter()
|
||||
.any(|e| matches!(e, MobEvent::EffectPlayer { .. })),
|
||||
events
|
||||
.iter()
|
||||
.any(|e| matches!(e, MobEvent::AttackMob { .. })),
|
||||
));
|
||||
}
|
||||
});
|
||||
if !ran {
|
||||
return;
|
||||
}
|
||||
let expected: Vec<(&str, Option<(u32, &'static str, i32, i32)>)> = cases
|
||||
.iter()
|
||||
.map(|(kind, effect, ticks)| (*kind, Some((2, *effect, *ticks, 0))))
|
||||
.collect();
|
||||
assert_eq!(carried, expected);
|
||||
for (kind, on_player, effectless) in strays {
|
||||
assert!(!on_player, "{kind} left its effect on the player");
|
||||
assert!(!effectless, "{kind} sent a second, effectless hit");
|
||||
}
|
||||
}
|
||||
|
||||
/// On easy the cave spider's poison timer is 0, so nothing rides the hit:
|
||||
/// the mob it bites takes the damage alone (`AttackMob`, no effect).
|
||||
#[test]
|
||||
fn an_easy_cave_spiders_bite_carries_no_effect() {
|
||||
let mut out: Option<Vec<String>> = None;
|
||||
let ran = with_test_world(&[], |w, types| {
|
||||
let mut easy = w.clone();
|
||||
easy.difficulty = super::super::spawning::LocalDifficulty::new(1, 18000, 0, 0.0);
|
||||
let mut m = Mob::new(
|
||||
1,
|
||||
Arc::new(types.types["minecraft:cave_spider"].clone()),
|
||||
Vec3::new(0.5, 64.0, 0.5),
|
||||
0.0,
|
||||
);
|
||||
let (mut lr, mut events) = (horizon_core::random::LegacyRandom::new(0), Vec::new());
|
||||
let mut cx = Cx {
|
||||
w: &easy,
|
||||
lr: &mut lr,
|
||||
events: &mut events,
|
||||
};
|
||||
do_hurt_target(&mut m, Who::Mob(2), &mut cx);
|
||||
out = Some(
|
||||
events
|
||||
.iter()
|
||||
.filter(|e| {
|
||||
matches!(
|
||||
e,
|
||||
MobEvent::AttackMob { .. } | MobEvent::AttackMobWithEffect { .. }
|
||||
)
|
||||
})
|
||||
.map(|e| match e {
|
||||
MobEvent::AttackMob { target, .. } => format!("plain {target}"),
|
||||
MobEvent::AttackMobWithEffect { effect, .. } => format!("effect {effect}"),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
});
|
||||
if !ran {
|
||||
return;
|
||||
}
|
||||
assert_eq!(out, Some(vec!["plain 2".to_owned()]));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod same_vehicle_push_tests {
|
||||
|
||||
Reference in new issue
Block a user