Skip to content

Commit

Permalink
Wither Minions no longer strafe when attacking
Browse files Browse the repository at this point in the history
  • Loading branch information
Insane96 committed Aug 28, 2022
1 parent 69b23ac commit 155b008
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 21 deletions.
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
* REGENERATE THE CONFIG
* Wither and Dragon config options now scale with max difficulty instead of current difficulty
* E.g. Dragon bonus health was 25 per difficulty, now is 200 at max difficulty
* Wither Minion
* Shoot every 1.5 seconds instead of 2 (1 in hard)
* No longer strafe when attacking
* Changed Ender Dragon enchanted golden apple drop (~~10%/20%/30%/40%~~ -> 10%/20%/30%/40%/50% chance at difficulties ~~5/6/7/8~~ -> 4/5/6/7/8)
* Removed "Apply to Vanilla Wither" config option

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,10 +296,10 @@ private boolean onImpact3DCloud(DragonFireball fireball, HitResult result) {

HitResult.Type raytraceresult$type = result.getType();
if (raytraceresult$type == HitResult.Type.ENTITY) {
Reflection.ProjectileEntity_onEntityHit(fireball, (EntityHitResult)result);
Reflection.Projectile_onHitEntity(fireball, (EntityHitResult)result);
}
else if (raytraceresult$type == HitResult.Type.BLOCK) {
Reflection.ProjectileEntity_onBlockHit(fireball, (BlockHitResult)result);
Reflection.Projectile_onHitBlock(fireball, (BlockHitResult)result);
}
Entity entity = fireball.getOwner();
if (entity != null && (result.getType() != HitResult.Type.ENTITY || !((EntityHitResult)result).getEntity().is(entity))) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package insane96mcp.progressivebosses.module.wither.ai;

import insane96mcp.progressivebosses.module.wither.entity.WitherMinion;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.item.BowItem;

import java.util.EnumSet;

// Same as RangedBowAttackGoal but without the strafing
public class RangedMinionAttackGoal extends Goal {
private final WitherMinion mob;
private final double speedModifier;
private int attackIntervalMin;
private final float attackRadiusSqr;
private int attackTime = -1;
private int seeTime;

public RangedMinionAttackGoal(WitherMinion p_25792_, double p_25793_, int p_25794_, float p_25795_) {
this.mob = p_25792_;
this.speedModifier = p_25793_;
this.attackIntervalMin = p_25794_;
this.attackRadiusSqr = p_25795_ * p_25795_;
this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
}

public void setMinAttackInterval(int p_25798_) {
this.attackIntervalMin = p_25798_;
}

public boolean canUse() {
return this.mob.getTarget() != null && this.isHoldingBow();
}

protected boolean isHoldingBow() {
return this.mob.isHolding(is -> is.getItem() instanceof BowItem);
}

public boolean canContinueToUse() {
return (this.canUse() || !this.mob.getNavigation().isDone()) && this.isHoldingBow();
}

public void start() {
super.start();
this.mob.setAggressive(true);
}

public void stop() {
super.stop();
this.mob.setAggressive(false);
this.seeTime = 0;
this.attackTime = -1;
this.mob.stopUsingItem();
}

public boolean requiresUpdateEveryTick() {
return true;
}

public void tick() {
LivingEntity livingentity = this.mob.getTarget();
if (livingentity != null) {
double d0 = this.mob.distanceToSqr(livingentity.getX(), livingentity.getY(), livingentity.getZ());
boolean flag = this.mob.getSensing().hasLineOfSight(livingentity);
boolean flag1 = this.seeTime > 0;
if (flag != flag1) {
this.seeTime = 0;
}

if (flag) {
++this.seeTime;
} else {
--this.seeTime;
}

if (!(d0 > (double)this.attackRadiusSqr) && this.seeTime >= 1) {
this.mob.getNavigation().stop();
} else {
this.mob.getNavigation().moveTo(livingentity, this.speedModifier);
}

this.mob.getLookControl().setLookAt(livingentity, 30.0F, 30.0F);

if (this.mob.isUsingItem()) {
if (!flag && this.seeTime < -60) {
this.mob.stopUsingItem();
} else if (flag) {
int i = this.mob.getTicksUsingItem();
if (i >= 20) {
this.mob.stopUsingItem();
this.mob.performRangedAttack(livingentity, BowItem.getPowerForTime(i));
this.attackTime = this.attackIntervalMin;
}
}
} else if (--this.attackTime <= 0 && this.seeTime >= -60) {
this.mob.startUsingItem(ProjectileUtil.getWeaponHoldingHand(this.mob, item -> item instanceof BowItem));
}

}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package insane96mcp.progressivebosses.module.wither.entity;

import insane96mcp.insanelib.ai.ILNearestAttackableTargetGoal;
import insane96mcp.progressivebosses.module.wither.ai.RangedMinionAttackGoal;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
Expand All @@ -20,6 +21,7 @@
import net.minecraft.world.entity.boss.wither.WitherBoss;
import net.minecraft.world.entity.monster.AbstractSkeleton;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
Expand All @@ -30,10 +32,13 @@

public class WitherMinion extends AbstractSkeleton {

protected final RangedMinionAttackGoal minionBowGoal = new RangedMinionAttackGoal(this, 1.0D, 20, 15.0F);

private static final Predicate<LivingEntity> NOT_UNDEAD = livingEntity -> livingEntity != null && livingEntity.getMobType() != MobType.UNDEAD && livingEntity.attackable();

public WitherMinion(EntityType<? extends AbstractSkeleton> type, Level worldIn) {
super(type, worldIn);
this.reassesMinionWeapon();
}

@Override
Expand Down Expand Up @@ -86,11 +91,33 @@ protected void populateDefaultEquipmentSlots(DifficultyInstance difficulty) {
@Nullable
public SpawnGroupData finalizeSpawn(ServerLevelAccessor worldIn, DifficultyInstance difficultyIn, MobSpawnType reason, @Nullable SpawnGroupData spawnDataIn, @Nullable CompoundTag dataTag) {
SpawnGroupData ilivingentitydata = super.finalizeSpawn(worldIn, difficultyIn, reason, spawnDataIn, dataTag);
this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0D);
this.reassessWeaponGoal();
return ilivingentitydata;
}

@Override
public void reassessWeaponGoal() {
super.reassessWeaponGoal();
if (this.minionBowGoal != null)
this.reassesMinionWeapon();
}

private void reassesMinionWeapon() {
if (!this.level.isClientSide) {
this.goalSelector.removeGoal(this.meleeGoal);
this.goalSelector.removeGoal(this.bowGoal);
this.goalSelector.removeGoal(this.minionBowGoal);
ItemStack itemstack = this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, item -> item instanceof net.minecraft.world.item.BowItem));
if (itemstack.is(Items.BOW)) {
this.minionBowGoal.setMinAttackInterval(30);
this.goalSelector.addGoal(4, this.minionBowGoal);
} else {
this.goalSelector.addGoal(4, this.meleeGoal);
}

}
}

public boolean doHurtTarget(Entity entityIn) {
if (!super.doHurtTarget(entityIn)) {
return false;
Expand Down Expand Up @@ -120,7 +147,7 @@ protected void createWitherRose(@Nullable LivingEntity entitySource) {
public static AttributeSupplier.Builder prepareAttributes() {
return LivingEntity.createLivingAttributes()
.add(Attributes.ATTACK_DAMAGE, 3.0d)
.add(Attributes.MAX_HEALTH, 20.0d)
.add(Attributes.MAX_HEALTH, 16.0d)
.add(Attributes.FOLLOW_RANGE, 64.0d)
.add(Attributes.MOVEMENT_SPEED, 0.25d)
.add(Attributes.ATTACK_KNOCKBACK, 1.5d);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class AttackFeature extends Feature {
public double maxChargeAttackChance = 0.06d;
public double chargeAttackBaseDamage = 16d;
//Barrage Attack
public double maxBarrageChance = 0.09d;
public double maxBarrageChance = 0.075d;
public int minBarrageDuration = 20;
public int maxBarrageDuration = 150;
//Skulls
Expand All @@ -76,8 +76,8 @@ public AttackFeature(Module module) {
//Barrage
Config.builder.push("Barrage Attack");
maxBarrageChanceConfig = Config.builder
.comment("Chance (at max difficulty) every time the Wither takes damage to start a barrage attack. Lower health and more damage taken increases the chance.\n" +
"This value is the chance at 0% health and when taking 10 damage.")
.comment("Chance (at max difficulty) every time the Wither takes damage to start a barrage attack. More damage taken increases the chance.\n" +
"This value is the chance when taking 10 damage.")
.defineInRange("Barrage Attack Chance", maxBarrageChance, 0d, 1d);
minBarrageDurationConfig = Config.builder
.comment("Min time (in ticks) for the duration of the barrage attack. Less health = longer barrage.")
Expand Down Expand Up @@ -218,7 +218,7 @@ private void doBarrage(WitherBoss wither, float damageTaken) {
CompoundTag witherTags = wither.getPersistentData();
double missingHealthPerc = 1d - wither.getHealth() / wither.getMaxHealth();

double chance = (this.maxBarrageChance * DifficultyHelper.getScalingDifficulty(wither)) * missingHealthPerc;
double chance = (this.maxBarrageChance * DifficultyHelper.getScalingDifficulty(wither));
chance *= (damageTaken / 10f);
double r = wither.getRandom().nextDouble();
if (r < chance) {
Expand Down
24 changes: 12 additions & 12 deletions src/main/java/insane96mcp/progressivebosses/setup/Reflection.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@
public class Reflection {
static MethodHandles.Lookup lookup = MethodHandles.lookup();

static Method onEntityHitMethod;
public static MethodHandle onEntityHitMH;
public static void ProjectileEntity_onEntityHit(Projectile projectileEntity, EntityHitResult p_213868_1_) {
static Method onHitEntityMethod;
static MethodHandle onHitEntityHandler;
public static void Projectile_onHitEntity(Projectile projectileEntity, EntityHitResult p_213868_1_) {
try {
onEntityHitMH.invoke(projectileEntity, p_213868_1_);
onHitEntityHandler.invoke(projectileEntity, p_213868_1_);
}
catch (Throwable throwable) {
throwable.printStackTrace();
}
}

static Method onBlockHitMethod;
public static MethodHandle onBlockHitMH;
public static void ProjectileEntity_onBlockHit(Projectile projectileEntity, BlockHitResult p_213868_1_) {
static Method onHitBlockMethod;
static MethodHandle onHitBlockHandler;
public static void Projectile_onHitBlock(Projectile projectileEntity, BlockHitResult p_213868_1_) {
try {
onBlockHitMH.invoke(projectileEntity, p_213868_1_);
onHitBlockHandler.invoke(projectileEntity, p_213868_1_);
}
catch (Throwable throwable) {
throwable.printStackTrace();
Expand All @@ -37,11 +37,11 @@ public static void ProjectileEntity_onBlockHit(Projectile projectileEntity, Bloc

public static void init() {
try {
onEntityHitMethod = ObfuscationReflectionHelper.findMethod(Projectile.class, "m_5790_", EntityHitResult.class);
onEntityHitMH = lookup.unreflect(onEntityHitMethod);
onHitEntityMethod = ObfuscationReflectionHelper.findMethod(Projectile.class, "m_5790_", EntityHitResult.class);
onHitEntityHandler = lookup.unreflect(onHitEntityMethod);

onBlockHitMethod = ObfuscationReflectionHelper.findMethod(Projectile.class, "m_8060_", BlockHitResult.class);
onBlockHitMH = lookup.unreflect(onBlockHitMethod);
onHitBlockMethod = ObfuscationReflectionHelper.findMethod(Projectile.class, "m_8060_", BlockHitResult.class);
onHitBlockHandler = lookup.unreflect(onHitBlockMethod);
} catch (IllegalAccessException e) {
ProgressiveBosses.LOGGER.error(e.toString());
}
Expand Down
6 changes: 5 additions & 1 deletion src/main/resources/META-INF/accesstransformer.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,8 @@ public-f net.minecraft.world.level.Explosion f_46010_ # mode

#GuardianEntity
public net.minecraft.world.entity.monster.Guardian m_32817_(I)V # setActiveAttackTarget
public net.minecraft.world.entity.monster.Guardian$GuardianAttackGoal
public net.minecraft.world.entity.monster.Guardian$GuardianAttackGoal

#AbstractSkeleton
public net.minecraft.world.entity.monster.AbstractSkeleton f_32130_ # bowGoal
public net.minecraft.world.entity.monster.AbstractSkeleton f_32131_ # meleeGoal

0 comments on commit 155b008

Please sign in to comment.