package net.minecraft.world.entity.ai.goal; import java.util.EnumSet; import javax.annotation.Nullable; import net.minecraft.util.Mth; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.monster.RangedAttackMob; public class RangedAttackGoal extends Goal { private final Mob mob; private final RangedAttackMob rangedAttackMob; @Nullable private LivingEntity target; private int attackTime = -1; private final double speedModifier; private int seeTime; private final int attackIntervalMin; private final int attackIntervalMax; private final float attackRadius; private final float attackRadiusSqr; public RangedAttackGoal(RangedAttackMob p_25768_, double p_25769_, int p_25770_, float p_25771_) { this(p_25768_, p_25769_, p_25770_, p_25770_, p_25771_); } public RangedAttackGoal(RangedAttackMob p_25773_, double p_25774_, int p_25775_, int p_25776_, float p_25777_) { if (!(p_25773_ instanceof LivingEntity)) { throw new IllegalArgumentException("ArrowAttackGoal requires Mob implements RangedAttackMob"); } else { this.rangedAttackMob = p_25773_; this.mob = (Mob)p_25773_; this.speedModifier = p_25774_; this.attackIntervalMin = p_25775_; this.attackIntervalMax = p_25776_; this.attackRadius = p_25777_; this.attackRadiusSqr = p_25777_ * p_25777_; this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); } } @Override public boolean canUse() { LivingEntity livingentity = this.mob.getTarget(); if (livingentity != null && livingentity.isAlive()) { this.target = livingentity; return true; } else { return false; } } @Override public boolean canContinueToUse() { return this.canUse() || this.target.isAlive() && !this.mob.getNavigation().isDone(); } @Override public void stop() { this.target = null; this.seeTime = 0; this.attackTime = -1; } @Override public boolean requiresUpdateEveryTick() { return true; } @Override public void tick() { double d0 = this.mob.distanceToSqr(this.target.getX(), this.target.getY(), this.target.getZ()); boolean flag = this.mob.getSensing().hasLineOfSight(this.target); if (flag) { this.seeTime++; } else { this.seeTime = 0; } if (!(d0 > this.attackRadiusSqr) && this.seeTime >= 5) { this.mob.getNavigation().stop(); } else { this.mob.getNavigation().moveTo(this.target, this.speedModifier); } this.mob.getLookControl().setLookAt(this.target, 30.0F, 30.0F); if (--this.attackTime == 0) { if (!flag) { return; } float f = (float)Math.sqrt(d0) / this.attackRadius; float f1 = Mth.clamp(f, 0.1F, 1.0F); this.rangedAttackMob.performRangedAttack(this.target, f1); this.attackTime = Mth.floor(f * (this.attackIntervalMax - this.attackIntervalMin) + this.attackIntervalMin); } else if (this.attackTime < 0) { this.attackTime = Mth.floor(Mth.lerp(Math.sqrt(d0) / this.attackRadius, this.attackIntervalMin, this.attackIntervalMax)); } } }