Improved basilisk AI and attack

This commit is contained in:
craisinlord committed 2026-06-22 22:45:41 -05:00
1 parent 3c6c54ebd6
commit 9784c0ed62
4 files changed
+79 -23

No files matched your search

@@ -147,8 +147,8 @@ public final class AntarchySettings {
private static boolean basiliskPetrifyingGazeEnabled = true;
private static int basiliskSpawnMaxLightLevel = 5;
private static double basiliskHealth = 150.0D;
private static double basiliskAttackDamage = 18.0D;
private static double basiliskMovementSpeed = 0.35D;
private static double basiliskAttackDamage = 8.0D;
private static double basiliskMovementSpeed = 0.30D;
private static double basiliskArmor = 6.0D;
private static double basiliskKnockbackResistance = 0.5D;
private static double basiliskFollowRange = 28.0D;
@@ -13,7 +13,10 @@ import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.Difficulty;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.core.Holder;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.EquipmentSlot;
@@ -71,11 +74,12 @@ public class BasiliskEntity extends Monster implements GeoEntity {
private static final RawAnimation ATTACK_ANIM = RawAnimation.begin().thenPlay("attack");
private static final RawAnimation DEATH_ANIM = RawAnimation.begin().thenPlay("death");
private static final float TURN_RATE_DEG_PER_TICK = 5.0F;
private static final float TURN_RATE_DEG_PER_TICK = 10.0F;
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
private int attackAnimTicks = 0;
private boolean attackDamagePending = false;
private int hissCooldown = AntarchySettings.basiliskHissCooldownTicks();
private int hissChargeTimer = 0;
@@ -148,23 +152,34 @@ public class BasiliskEntity extends Monster implements GeoEntity {
if (hurt) {
this.level().broadcastEntityEvent(this, ATTACK_ENTITY_EVENT);
this.playSound(AntarchySoundEvents.BASILISK_BITE.get(), 1.1F, 0.95F + this.random.nextFloat() * 0.08F);
}
return hurt;
}
private void performAoeAttack() {
if (this.level().isClientSide) return;
// Start the animation; damage fires later in tick() when attackAnimTicks reaches the damage threshold
this.attackAnimTicks = AntarchySettings.basiliskAttackAnimTicks();
this.attackDamagePending = true;
this.level().broadcastEntityEvent(this, ATTACK_ENTITY_EVENT);
}
private void tickAoeDamage() {
if (!this.attackDamagePending) return;
if (this.attackAnimTicks > AntarchySettings.basiliskAttackDamageTick()) return;
if (!(this.level() instanceof ServerLevel serverLevel)) return;
double attackReach = AntarchySettings.basiliskAttackReach();
Vec3 forward = Vec3.directionFromRotation(0, this.getYRot());
this.attackDamagePending = false;
Vec3 forward = Vec3.directionFromRotation(0, this.yBodyRot);
Vec3 right = new Vec3(-forward.z, 0, forward.x);
Vec3 origin = this.position();
double attackReach = AntarchySettings.basiliskAttackReach();
List<LivingEntity> candidates = this.level().getEntitiesOfClass(
LivingEntity.class,
this.getBoundingBox().inflate(Math.max(4.0D, attackReach + 1.5D)),
this.getBoundingBox().inflate(Math.max(8.0D, attackReach + 3.5D)),
e -> e != this && e.isAlive()
);
@@ -173,16 +188,15 @@ public class BasiliskEntity extends Monster implements GeoEntity {
Vec3 toEntity = entity.position().subtract(origin);
double fwdDist = toEntity.dot(forward);
double sideDist = toEntity.dot(right);
// Forward bite volume measured from the basilisk's center.
if (fwdDist >= 1.0 && fwdDist <= attackReach && Math.abs(sideDist) <= 1.5) {
double upDist = toEntity.y;
if (fwdDist >= 2.0 && fwdDist <= 7.0 && Math.abs(sideDist) <= 2.25 && upDist >= -1.0 && upDist <= 3.0) {
if (entity.hurt(AntarchyDamageSources.basiliskBite(serverLevel, this),
(float) this.getAttributeValue(Attributes.ATTACK_DAMAGE))) {
hitAnything = true;
}
}
}
this.level().broadcastEntityEvent(this, ATTACK_ENTITY_EVENT);
if (hitAnything) {
this.playSound(AntarchySoundEvents.BASILISK_BITE.get(), 1.1F, 0.95F + this.random.nextFloat() * 0.08F);
}
@@ -207,6 +221,7 @@ public class BasiliskEntity extends Monster implements GeoEntity {
this.tickPlayerPetrification();
this.tickPreyPetrification();
this.tickAoeDamage();
this.updateAnimationState();
}
@@ -399,16 +414,13 @@ public class BasiliskEntity extends Monster implements GeoEntity {
}
private PlayState mainController(AnimationState<BasiliskEntity> state) {
if (this.getAnimationState() == ANIM_DEATH) {
if (this.isDeadOrDying()) {
return state.setAndContinue(DEATH_ANIM);
}
if (this.getAnimationState() == ANIM_ATTACK) {
if (this.attackAnimTicks > 0) {
return state.setAndContinue(ATTACK_ANIM);
}
if (this.getAnimationState() == ANIM_WALK) {
return state.setAndContinue(WALK_ANIM);
}
if (state.isMoving()) {
if (this.getAnimationState() == ANIM_WALK || state.isMoving()) {
return state.setAndContinue(WALK_ANIM);
}
return state.setAndContinue(IDLE_ANIM);
@@ -434,6 +446,7 @@ public class BasiliskEntity extends Monster implements GeoEntity {
if (!this.level().isClientSide) {
this.setAnimationState(ANIM_DEATH);
this.attackAnimTicks = 0;
this.attackDamagePending = false;
this.hissChargeTimer = 0;
this.pendingTargetId = null;
this.getNavigation().stop();
@@ -494,9 +507,22 @@ public class BasiliskEntity extends Monster implements GeoEntity {
return super.canAttack(target);
}
@Override
public float maxUpStep() {
return 1.5F;
}
@Override
public boolean canBeAffected(MobEffectInstance effectInstance) {
Holder<MobEffect> effect = effectInstance.getEffect();
if (effect == MobEffects.POISON) return false;
if (effect == AntarchyObjects.PARALYZED_EFFECT.get()) return false;
return super.canBeAffected(effectInstance);
}
@Override
public boolean isWithinMeleeAttackRange(LivingEntity target) {
double reach = AntarchySettings.basiliskAttackReach();
double reach = AntarchySettings.basiliskAttackReach() + 4.0;
return this.distanceToSqr(target) <= reach * reach;
}
@@ -560,16 +586,33 @@ public class BasiliskEntity extends Monster implements GeoEntity {
private final class BasiliskMeleeAttackGoal extends MeleeAttackGoal {
private BasiliskMeleeAttackGoal() {
super(BasiliskEntity.this, 1.1D, true);
super(BasiliskEntity.this, 1.2D, true);
}
@Override
public void tick() {
if (BasiliskEntity.this.hissChargeTimer > 0) {
BasiliskEntity.this.getNavigation().stop();
LivingEntity target = BasiliskEntity.this.getTarget();
if (target != null) {
BasiliskEntity.this.getLookControl().setLookAt(target, 30.0F, 30.0F);
}
if (BasiliskEntity.this.hissChargeTimer > 0 || BasiliskEntity.this.attackAnimTicks > 0) {
this.stopMovement();
return;
}
super.tick();
// If we're in range after super ran, kill movement so the basilisk stops and bites
if (target != null && BasiliskEntity.this.isWithinMeleeAttackRange(target)) {
this.stopMovement();
}
}
private void stopMovement() {
BasiliskEntity.this.getNavigation().stop();
BasiliskEntity.this.setSpeed(0.0F);
BasiliskEntity.this.setZza(0.0F);
}
@Override
@@ -560,7 +560,9 @@ public class NightmareEntity extends Monster implements GeoEntity {
private boolean shouldUseFlight() {
if (this.landingCooldown > 0) return false;
LivingEntity target = this.getTarget();
return target != null && this.distanceToSqr(target) > FLIGHT_ENGAGE_RANGE_SQR;
return target != null
&& this.distanceToSqr(target) > FLIGHT_ENGAGE_RANGE_SQR
&& !this.isTooCloseToCeiling();
}
private boolean canStartAttackOn(LivingEntity target) {
@@ -745,7 +747,8 @@ public class NightmareEntity extends Monster implements GeoEntity {
LivingEntity target = NightmareEntity.this.getTarget();
return target != null
&& NightmareEntity.this.landingCooldown <= 0
&& NightmareEntity.this.distanceToSqr(target) > FLIGHT_ENGAGE_RANGE_SQR;
&& NightmareEntity.this.distanceToSqr(target) > FLIGHT_ENGAGE_RANGE_SQR
&& !NightmareEntity.this.isTooCloseToCeiling();
}
@Override
@@ -770,6 +773,11 @@ public class NightmareEntity extends Monster implements GeoEntity {
public void tick() {
LivingEntity target = NightmareEntity.this.getTarget();
if (target == null) return;
if (NightmareEntity.this.isTooCloseToCeiling()) {
NightmareEntity.this.flyingToTarget = false;
NightmareEntity.this.getNavigation().stop();
return;
}
if (NightmareEntity.this.attackCooldown <= 0 && NightmareEntity.this.canStartAttackOn(target)) {
NightmareEntity.this.startAttack(target);
return;
@@ -409,6 +409,11 @@
"attack": {
"loop": false,
"animation_length": 1,
"sound_effects": {
"0.3333": {
"effect": "antarchy:basilisk_bite|1.1|1.0"
}
},
"bones": {
"Basilisk": {
"position": {