first pass royal decrees, time dilation transitions, kings tree fixes, manticore changes

This commit is contained in:
craisinlord committed 2026-08-29 23:15:51 -05:00
1 parent c573c574b9
commit 065a04fc93
30 files changed
+833 -24

No files matched your search

@@ -513,6 +513,23 @@ public final class AntarchySettings {
private static double manticoreAttackDamage = 7.0D; private static double manticoreAttackDamage = 7.0D;
private static int manticoreStingPoisonTicks = 100; private static int manticoreStingPoisonTicks = 100;
private static int queenManticoreCap = 15; private static int queenManticoreCap = 15;
private static int queenManticoreSummonCooldownTicks = 600;
private static int queenManticoreSummonCount = 3;
private static double queenManticoreSummonRange = 24.0D;
private static double queenBeamDamage = 45.0D;
private static double queenBeamRange = 100.0D;
private static int queenBeamDurationTicks = 30;
private static int queenBeamCooldownTicks = 90;
private static double queenBeamTracking = 0.1D;
private static double queenBeamTerrainRadius = 5.0D;
private static int queenBeamTerrainCap = 192;
private static double kingBeamDamage = 50.0D;
private static double kingBeamRange = 100.0D;
private static int kingBeamDurationTicks = 30;
private static int kingBeamCooldownTicks = 90;
private static double kingBeamTracking = 0.1D;
private static double kingBeamTerrainRadius = 5.0D;
private static int kingBeamTerrainCap = 192;
private static double jerryInfantHealth = 20.0D; private static double jerryInfantHealth = 20.0D;
private static double jerryInfantAttackDamage = 2.0D; private static double jerryInfantAttackDamage = 2.0D;
private static double jerryMatureHealth = 40.0D; private static double jerryMatureHealth = 40.0D;
@@ -2749,6 +2766,40 @@ public final class AntarchySettings {
public static void setManticoreStingPoisonTicks(int v) { manticoreStingPoisonTicks = v; } public static void setManticoreStingPoisonTicks(int v) { manticoreStingPoisonTicks = v; }
public static int queenManticoreCap() { return queenManticoreCap; } public static int queenManticoreCap() { return queenManticoreCap; }
public static void setQueenManticoreCap(int v) { queenManticoreCap = v; } public static void setQueenManticoreCap(int v) { queenManticoreCap = v; }
public static int queenManticoreSummonCooldownTicks() { return queenManticoreSummonCooldownTicks; }
public static void setQueenManticoreSummonCooldownTicks(int v) { queenManticoreSummonCooldownTicks = v; }
public static int queenManticoreSummonCount() { return queenManticoreSummonCount; }
public static void setQueenManticoreSummonCount(int v) { queenManticoreSummonCount = v; }
public static double queenManticoreSummonRange() { return queenManticoreSummonRange; }
public static void setQueenManticoreSummonRange(double v) { queenManticoreSummonRange = v; }
public static double queenBeamDamage() { return queenBeamDamage; }
public static void setQueenBeamDamage(double v) { queenBeamDamage = v; }
public static double queenBeamRange() { return queenBeamRange; }
public static void setQueenBeamRange(double v) { queenBeamRange = v; }
public static int queenBeamDurationTicks() { return queenBeamDurationTicks; }
public static void setQueenBeamDurationTicks(int v) { queenBeamDurationTicks = v; }
public static int queenBeamCooldownTicks() { return queenBeamCooldownTicks; }
public static void setQueenBeamCooldownTicks(int v) { queenBeamCooldownTicks = v; }
public static double queenBeamTracking() { return queenBeamTracking; }
public static void setQueenBeamTracking(double v) { queenBeamTracking = v; }
public static double queenBeamTerrainRadius() { return queenBeamTerrainRadius; }
public static void setQueenBeamTerrainRadius(double v) { queenBeamTerrainRadius = v; }
public static int queenBeamTerrainCap() { return queenBeamTerrainCap; }
public static void setQueenBeamTerrainCap(int v) { queenBeamTerrainCap = v; }
public static double kingBeamDamage() { return kingBeamDamage; }
public static void setKingBeamDamage(double v) { kingBeamDamage = v; }
public static double kingBeamRange() { return kingBeamRange; }
public static void setKingBeamRange(double v) { kingBeamRange = v; }
public static int kingBeamDurationTicks() { return kingBeamDurationTicks; }
public static void setKingBeamDurationTicks(int v) { kingBeamDurationTicks = v; }
public static int kingBeamCooldownTicks() { return kingBeamCooldownTicks; }
public static void setKingBeamCooldownTicks(int v) { kingBeamCooldownTicks = v; }
public static double kingBeamTracking() { return kingBeamTracking; }
public static void setKingBeamTracking(double v) { kingBeamTracking = v; }
public static double kingBeamTerrainRadius() { return kingBeamTerrainRadius; }
public static void setKingBeamTerrainRadius(double v) { kingBeamTerrainRadius = v; }
public static int kingBeamTerrainCap() { return kingBeamTerrainCap; }
public static void setKingBeamTerrainCap(int v) { kingBeamTerrainCap = v; }
public static double jerryInfantHealth() { return jerryInfantHealth; } public static double jerryInfantHealth() { return jerryInfantHealth; }
public static void setJerryInfantHealth(double v) { jerryInfantHealth = v; } public static void setJerryInfantHealth(double v) { jerryInfantHealth = v; }
public static double jerryInfantAttackDamage() { return jerryInfantAttackDamage; } public static double jerryInfantAttackDamage() { return jerryInfantAttackDamage; }
@@ -186,6 +186,14 @@ public final class AntarchySoundEvents {
public static Supplier<SoundEvent> QUEEN_HURT = (Supplier<SoundEvent>) UNBOUND; public static Supplier<SoundEvent> QUEEN_HURT = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> QUEEN_DEATH = (Supplier<SoundEvent>) UNBOUND; public static Supplier<SoundEvent> QUEEN_DEATH = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> QUEEN_BITE = (Supplier<SoundEvent>) UNBOUND; public static Supplier<SoundEvent> QUEEN_BITE = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> QUEEN_ROAR = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> KING_BEAM_SHOOT = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> KING_FIREBALL_SHOOT = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> KING_DECREE_CAST = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> QUEEN_BEAM_SHOOT = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> QUEEN_BEAM_START = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> QUEEN_BEAM_LOOP = (Supplier<SoundEvent>) UNBOUND;
public static Supplier<SoundEvent> QUEEN_BEAM_END = (Supplier<SoundEvent>) UNBOUND;
private AntarchySoundEvents() { private AntarchySoundEvents() {
} }
@@ -367,7 +375,15 @@ public final class AntarchySoundEvents {
Supplier<SoundEvent> queenIdle, Supplier<SoundEvent> queenIdle,
Supplier<SoundEvent> queenHurt, Supplier<SoundEvent> queenHurt,
Supplier<SoundEvent> queenDeath, Supplier<SoundEvent> queenDeath,
Supplier<SoundEvent> queenBite Supplier<SoundEvent> queenBite,
Supplier<SoundEvent> queenRoar,
Supplier<SoundEvent> kingBeamShoot,
Supplier<SoundEvent> kingFireballShoot,
Supplier<SoundEvent> kingDecreeCast,
Supplier<SoundEvent> queenBeamShoot,
Supplier<SoundEvent> queenBeamStart,
Supplier<SoundEvent> queenBeamLoop,
Supplier<SoundEvent> queenBeamEnd
) { ) {
SQUIDZOOKA_FIRE = squidzookaFire; SQUIDZOOKA_FIRE = squidzookaFire;
SHRINK_RAY_CHARGE = shrinkRayCharge; SHRINK_RAY_CHARGE = shrinkRayCharge;
@@ -546,5 +562,13 @@ public final class AntarchySoundEvents {
QUEEN_HURT = queenHurt; QUEEN_HURT = queenHurt;
QUEEN_DEATH = queenDeath; QUEEN_DEATH = queenDeath;
QUEEN_BITE = queenBite; QUEEN_BITE = queenBite;
QUEEN_ROAR = queenRoar;
KING_BEAM_SHOOT = kingBeamShoot;
KING_FIREBALL_SHOOT = kingFireballShoot;
KING_DECREE_CAST = kingDecreeCast;
QUEEN_BEAM_SHOOT = queenBeamShoot;
QUEEN_BEAM_START = queenBeamStart;
QUEEN_BEAM_LOOP = queenBeamLoop;
QUEEN_BEAM_END = queenBeamEnd;
} }
} }
@@ -8,6 +8,7 @@ import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import software.bernie.geckolib.cache.object.BakedGeoModel; import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.renderer.GeoEntityRenderer; import software.bernie.geckolib.renderer.GeoEntityRenderer;
@@ -30,4 +31,45 @@ public class RoyalBossRenderer extends GeoEntityRenderer<RoyalBossEntity> {
poseStack.scale(RoyalBossEntity.MODEL_RENDER_SCALE, RoyalBossEntity.MODEL_RENDER_SCALE, RoyalBossEntity.MODEL_RENDER_SCALE); poseStack.scale(RoyalBossEntity.MODEL_RENDER_SCALE, RoyalBossEntity.MODEL_RENDER_SCALE, RoyalBossEntity.MODEL_RENDER_SCALE);
this.shadowRadius = 8.0F * RoyalBossEntity.MODEL_RENDER_SCALE; this.shadowRadius = 8.0F * RoyalBossEntity.MODEL_RENDER_SCALE;
} }
@Override
public void render(RoyalBossEntity entity, float entityYaw, float partialTick, PoseStack poseStack,
MultiBufferSource bufferSource, int packedLight) {
super.render(entity, entityYaw, partialTick, poseStack, bufferSource, packedLight);
Vec3 end = entity.getRoyalBeamEndPosition();
if (!entity.isFiringRoyalBeam() || end == null) {
return;
}
double x = net.minecraft.util.Mth.lerp(partialTick, entity.xo, entity.getX());
double y = net.minecraft.util.Mth.lerp(partialTick, entity.yo, entity.getY());
double z = net.minecraft.util.Mth.lerp(partialTick, entity.zo, entity.getZ());
Vec3 start = entity.getRoyalBeamShootFrom(partialTick).subtract(x, y, z);
Vec3 finish = end.subtract(x, y, z);
Vec3 direction = finish.subtract(start).normalize();
Vec3 side = direction.cross(new Vec3(0.0D, 1.0D, 0.0D));
if (side.lengthSqr() < 1.0E-4D) {
side = direction.cross(new Vec3(1.0D, 0.0D, 0.0D));
}
side = side.normalize().scale(0.22D);
VertexConsumer vertices = bufferSource.getBuffer(RenderType.lightning());
poseStack.pushPose();
poseStack.scale(0.5F, 0.5F, 0.5F);
drawBeamQuad(vertices, poseStack, start, finish, side);
drawBeamQuad(vertices, poseStack, start, finish, new Vec3(-side.z, side.y, side.x));
poseStack.popPose();
}
private static void drawBeamQuad(VertexConsumer vertices, PoseStack poseStack, Vec3 start, Vec3 end, Vec3 side) {
var pose = poseStack.last().pose();
vertex(vertices, pose, start.subtract(side));
vertex(vertices, pose, start.add(side));
vertex(vertices, pose, end.add(side));
vertex(vertices, pose, end.subtract(side));
}
private static void vertex(VertexConsumer vertices, org.joml.Matrix4f pose, Vec3 pos) {
vertices.addVertex(pose, (float) pos.x, (float) pos.y, (float) pos.z)
.setColor(255, 255, 255, 255).setUv(0.0F, 0.0F).setUv2(15728880 & 65535, 15728880 >> 16)
.setNormal(0.0F, 1.0F, 0.0F);
}
} }
@@ -3,6 +3,8 @@ package com.craisinlord.antarchy.content.entity.portal;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchyObjects; import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchyTags; import com.craisinlord.antarchy.content.AntarchyTags;
import com.craisinlord.antarchy.content.entity.ManticoreEntity;
import com.craisinlord.antarchy.content.entity.royal.QueenEntity;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -74,6 +76,10 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
private int eventTicks; private int eventTicks;
private int nextEventTicks; private int nextEventTicks;
private TearState pendingEvent = TearState.NORMAL; private TearState pendingEvent = TearState.NORMAL;
@Nullable
private UUID queenOwnerId;
private int queenManticoreCount;
private boolean queenManticoreSpawned;
public DimensionalTearEntity(EntityType<? extends DimensionalTearEntity> entityType, Level level) { public DimensionalTearEntity(EntityType<? extends DimensionalTearEntity> entityType, Level level) {
super(entityType, level); super(entityType, level);
@@ -90,6 +96,14 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
return tear; return tear;
} }
public static DimensionalTearEntity createQueenManticoreTear(ServerLevel level, Vec3 pos, float yaw,
int lifetimeTicks, UUID queenId, int count) {
DimensionalTearEntity tear = create(level, pos, yaw, lifetimeTicks);
tear.queenOwnerId = queenId;
tear.queenManticoreCount = Math.max(1, count);
return tear;
}
public void linkTo(DimensionalTearEntity other) { public void linkTo(DimensionalTearEntity other) {
this.linkedTearId = other.getUUID(); this.linkedTearId = other.getUUID();
this.linkedFallbackPos = other.position(); this.linkedFallbackPos = other.position();
@@ -121,6 +135,10 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
return; return;
} }
if (this.queenOwnerId != null && this.ageTicks == OPENING_ANIMATION_TICKS) {
this.spawnQueenManticores((ServerLevel) this.level());
}
DimensionalTearEntity linked = this.findLinkedTear(); DimensionalTearEntity linked = this.findLinkedTear();
if (linked == null || !linked.isAlive()) { if (linked == null || !linked.isAlive()) {
this.discard(); this.discard();
@@ -179,6 +197,49 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
level.playSound(null, this.blockPosition(), eventState == TearState.LUCID ? SoundEvents.AMETHYST_BLOCK_CHIME : SoundEvents.ENDERMAN_SCREAM, SoundSource.HOSTILE, 0.75F, eventState == TearState.LUCID ? 1.45F : 0.85F); level.playSound(null, this.blockPosition(), eventState == TearState.LUCID ? SoundEvents.AMETHYST_BLOCK_CHIME : SoundEvents.ENDERMAN_SCREAM, SoundSource.HOSTILE, 0.75F, eventState == TearState.LUCID ? 1.45F : 0.85F);
} }
private void spawnQueenManticores(ServerLevel level) {
if (this.queenManticoreSpawned) {
return;
}
this.queenManticoreSpawned = true;
Entity owner = level.getEntity(this.queenOwnerId);
if (!(owner instanceof QueenEntity queen) || !queen.isAlive()) {
return;
}
LivingEntity target = queen.getTarget();
for (int i = 0; i < this.queenManticoreCount; i++) {
if (ManticoreEntity.countSummonedBy(level, queen.getUUID()) >= com.craisinlord.antarchy.config.AntarchySettings.queenManticoreCap()) {
break;
}
ManticoreEntity manticore = AntarchyObjects.MANTICORE.get().create(level);
if (manticore == null) {
break;
}
Vec3 exit = this.exitPosition().add(0.0D, 0.8D + i * 0.35D, 0.0D);
manticore.moveTo(exit.x, exit.y, exit.z, this.getYRot(), 0.0F);
if (!level.noCollision(manticore)) {
manticore.discard();
continue;
}
manticore.finalizeSpawn(level, level.getCurrentDifficultyAt(BlockPos.containing(exit)), MobSpawnType.MOB_SUMMONED, null);
manticore.markQueenSummoned(queen.getUUID());
if (target != null && target.isAlive()) {
manticore.setTarget(target);
}
manticore.setDeltaMovement(this.getViewVector(1.0F).scale(0.2D).add(0.0D, 0.08D, 0.0D));
manticore.setNoGravity(true);
level.addFreshEntity(manticore);
}
}
public static void discardQueenOwnedTears(ServerLevel level, UUID queenId) {
for (DimensionalTearEntity tear : level.getEntitiesOfClass(DimensionalTearEntity.class,
new AABB(-3.0E7D, level.getMinBuildHeight(), -3.0E7D, 3.0E7D, level.getMaxBuildHeight(), 3.0E7D),
tear -> queenId.equals(tear.queenOwnerId))) {
tear.discard();
}
}
@Nullable @Nullable
private Mob createTaggedMob(ServerLevel level, TagKey<EntityType<?>> tag) { private Mob createTaggedMob(ServerLevel level, TagKey<EntityType<?>> tag) {
return BuiltInRegistries.ENTITY_TYPE.getTag(tag) return BuiltInRegistries.ENTITY_TYPE.getTag(tag)
@@ -331,6 +392,11 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
tag.putDouble("LinkedX", this.linkedFallbackPos.x); tag.putDouble("LinkedX", this.linkedFallbackPos.x);
tag.putDouble("LinkedY", this.linkedFallbackPos.y); tag.putDouble("LinkedY", this.linkedFallbackPos.y);
tag.putDouble("LinkedZ", this.linkedFallbackPos.z); tag.putDouble("LinkedZ", this.linkedFallbackPos.z);
if (this.queenOwnerId != null) {
tag.putUUID("QueenOwner", this.queenOwnerId);
tag.putInt("QueenManticoreCount", this.queenManticoreCount);
tag.putBoolean("QueenManticoreSpawned", this.queenManticoreSpawned);
}
} }
@Override @Override
@@ -346,6 +412,11 @@ public class DimensionalTearEntity extends Entity implements GeoEntity {
this.linkedTearId = tag.getUUID("LinkedTearId"); this.linkedTearId = tag.getUUID("LinkedTearId");
} }
this.linkedFallbackPos = new Vec3(tag.getDouble("LinkedX"), tag.getDouble("LinkedY"), tag.getDouble("LinkedZ")); this.linkedFallbackPos = new Vec3(tag.getDouble("LinkedX"), tag.getDouble("LinkedY"), tag.getDouble("LinkedZ"));
if (tag.hasUUID("QueenOwner")) {
this.queenOwnerId = tag.getUUID("QueenOwner");
this.queenManticoreCount = tag.getInt("QueenManticoreCount");
this.queenManticoreSpawned = tag.getBoolean("QueenManticoreSpawned");
}
} }
@Override @Override
@@ -7,8 +7,30 @@ import net.minecraft.world.BossEvent;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.entity.EntityType;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamSettings;
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamTerrainMode;
import com.craisinlord.antarchy.content.entity.royal.decree.AdvanceDecree;
import com.craisinlord.antarchy.content.entity.royal.decree.CloseQuartersDecree;
import com.craisinlord.antarchy.content.entity.royal.decree.KeepYourDistanceDecree;
import com.craisinlord.antarchy.content.entity.royal.decree.NoRetreatDecree;
import com.craisinlord.antarchy.content.entity.royal.decree.RoyalDecree;
import java.util.List;
public class KingEntity extends RoyalBossEntity { public class KingEntity extends RoyalBossEntity {
@Nullable
private Vec3 patrolCenter;
private int patrolCooldownTicks;
private int decreeCooldownTicks;
private int fireAttackCooldownTicks;
private int lightningAttackCooldownTicks;
private RoyalDecree activeDecree = new AdvanceDecree();
private static final List<RoyalDecree> DECREES = List.of(new CloseQuartersDecree(), new KeepYourDistanceDecree(), new NoRetreatDecree(), new AdvanceDecree());
public KingEntity(EntityType<? extends KingEntity> entityType, Level level) { public KingEntity(EntityType<? extends KingEntity> entityType, Level level) {
super(entityType, level); super(entityType, level);
} }
@@ -51,4 +73,94 @@ public class KingEntity extends RoyalBossEntity {
protected SoundEvent royalBiteSound() { protected SoundEvent royalBiteSound() {
return AntarchySoundEvents.KING_BITE.get(); return AntarchySoundEvents.KING_BITE.get();
} }
@Override
protected SoundEvent royalBeamShootSound() { return AntarchySoundEvents.KING_BEAM_SHOOT.get(); }
@Override
protected SoundEvent royalBeamStartSound() { return AntarchySoundEvents.KING_BEAM_SHOOT.get(); }
@Override
protected SoundEvent royalBeamLoopSound() { return AntarchySoundEvents.KING_BEAM_SHOOT.get(); }
@Override
protected SoundEvent royalBeamEndSound() { return AntarchySoundEvents.KING_BEAM_SHOOT.get(); }
@Override
protected RoyalBeamSettings royalBeamSettings() {
return new RoyalBeamSettings(AntarchySettings.kingBeamRange(), AntarchySettings.kingBeamTracking(), 7.5D,
AntarchySettings.kingBeamDurationTicks(), AntarchySettings.kingBeamCooldownTicks(), 6.0F, 6.0F,
(float) AntarchySettings.kingBeamDamage(), 1.0F, 3, 100.0D,
(float) AntarchySettings.kingBeamTerrainRadius(), 4.0F, AntarchySettings.kingBeamTerrainCap(),
1.0F, 0.08F, 15.0F, true, true);
}
@Override
protected RoyalBeamTerrainMode royalBeamTerrainMode() {
return RoyalBeamTerrainMode.BUILD_ICE;
}
@Override
protected RoyalBeamTerrainMode royalBeamTerrainMode(@Nullable RoyalHead head) {
return head != null && head.slot() == RoyalHead.Slot.RIGHT ? RoyalBeamTerrainMode.BUILD_ICE : RoyalBeamTerrainMode.NONE;
}
@Override
public void tick() {
super.tick();
if (!this.level().isClientSide && this.getTarget() != null && this.level() instanceof ServerLevel level) {
this.tickElementalAttacks(level, this.getTarget());
}
if (this.level().isClientSide || this.getTarget() != null || this.isDeadOrDying()
|| !(this.level() instanceof ServerLevel)) {
if (!this.level().isClientSide && this.getTarget() != null && this.level() instanceof ServerLevel level) {
this.tickDecree(level, this.getTarget());
}
return;
}
if (this.patrolCenter == null) {
this.patrolCenter = this.position();
}
if (this.patrolCooldownTicks-- <= 0) {
this.patrolCooldownTicks = 100 + this.random.nextInt(100);
double angle = this.random.nextDouble() * Math.PI * 2.0D;
double radius = 12.0D + this.random.nextDouble() * 18.0D;
this.getMoveControl().setWantedPosition(this.patrolCenter.x + Math.cos(angle) * radius,
this.patrolCenter.y + 6.0D + this.random.nextDouble() * 12.0D,
this.patrolCenter.z + Math.sin(angle) * radius, 1.0D);
}
}
private void tickDecree(ServerLevel level, net.minecraft.world.entity.LivingEntity target) {
if (this.decreeCooldownTicks-- <= 0) {
this.decreeCooldownTicks = 220;
this.activeDecree = DECREES.get(this.random.nextInt(DECREES.size()));
this.playSound(AntarchySoundEvents.KING_DECREE_CAST.get(), 3.0F, 0.9F + this.random.nextFloat() * 0.15F);
}
this.activeDecree.apply(level, this, target);
}
private void tickElementalAttacks(ServerLevel level, net.minecraft.world.entity.LivingEntity target) {
if (this.fireAttackCooldownTicks-- <= 0) {
this.fireAttackCooldownTicks = 110;
Vec3 start = this.position().add(0.0D, 5.0D, 0.0D);
RoyalBoltEntity bolt = new RoyalBoltEntity(AntarchyObjects.ROYAL_BOLT.get(), level);
bolt.setOwner(this);
bolt.setPos(start);
Vec3 delta = target.getEyePosition().subtract(start);
bolt.shoot(delta.x, delta.y, delta.z, 1.15F, 0.0F);
level.addFreshEntity(bolt);
this.playSound(AntarchySoundEvents.KING_FIREBALL_SHOOT.get(), 3.0F, 1.0F);
}
if (this.lightningAttackCooldownTicks-- <= 0) {
this.lightningAttackCooldownTicks = 150;
for (net.minecraft.world.entity.LivingEntity living : level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class,
target.getBoundingBox().inflate(5.0D), entity -> entity.isAlive() && entity != this)) {
LightningBolt bolt = EntityType.LIGHTNING_BOLT.create(level);
if (bolt == null) continue;
bolt.moveTo(living.getX(), living.getY(), living.getZ());
level.addFreshEntity(bolt);
}
}
}
} }
@@ -2,13 +2,36 @@ package com.craisinlord.antarchy.content.entity.royal;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.entity.ManticoreEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.BossEvent; import net.minecraft.world.BossEvent;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamSettings;
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamTerrainMode;
import com.craisinlord.antarchy.content.entity.portal.DimensionalTearEntity;
import com.craisinlord.antarchy.content.time.TimeDilationApi;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
public class QueenEntity extends RoyalBossEntity { public class QueenEntity extends RoyalBossEntity {
private static final String SUMMON_COOLDOWN_KEY = "ManticoreSummonCooldownTicks";
private static final int FAILED_SUMMON_RETRY_TICKS = 20;
private static final int POSITION_ATTEMPTS_PER_MANTICORE = 8;
private int manticoreSummonCooldownTicks;
private int gravityStompCooldownTicks;
private int timeFieldCooldownTicks;
public QueenEntity(EntityType<? extends QueenEntity> entityType, Level level) { public QueenEntity(EntityType<? extends QueenEntity> entityType, Level level) {
super(entityType, level); super(entityType, level);
} }
@@ -51,4 +74,187 @@ public class QueenEntity extends RoyalBossEntity {
protected SoundEvent royalBiteSound() { protected SoundEvent royalBiteSound() {
return AntarchySoundEvents.QUEEN_BITE.get(); return AntarchySoundEvents.QUEEN_BITE.get();
} }
@Override
protected SoundEvent royalBeamShootSound() { return AntarchySoundEvents.QUEEN_BEAM_SHOOT.get(); }
@Override
protected SoundEvent royalBeamStartSound() { return AntarchySoundEvents.QUEEN_BEAM_START.get(); }
@Override
protected SoundEvent royalBeamLoopSound() { return AntarchySoundEvents.QUEEN_BEAM_LOOP.get(); }
@Override
protected SoundEvent royalBeamEndSound() { return AntarchySoundEvents.QUEEN_BEAM_END.get(); }
@Override
protected RoyalBeamSettings royalBeamSettings() {
return new RoyalBeamSettings(AntarchySettings.queenBeamRange(), AntarchySettings.queenBeamTracking(), 7.5D,
AntarchySettings.queenBeamDurationTicks(), AntarchySettings.queenBeamCooldownTicks(), 6.0F, 6.0F,
(float) AntarchySettings.queenBeamDamage(), 1.0F, 3, 100.0D,
(float) AntarchySettings.queenBeamTerrainRadius(), 4.0F, AntarchySettings.queenBeamTerrainCap(),
1.0F, 0.08F, 15.0F, true, true);
}
@Override
protected RoyalBeamTerrainMode royalBeamTerrainMode() {
return RoyalBeamTerrainMode.DESTROY;
}
@Override
public void tick() {
super.tick();
if (this.level().isClientSide || this.isDeadOrDying()) {
return;
}
this.tickManticoreSummon();
this.tickGravityAttacks();
}
private void tickManticoreSummon() {
if (this.manticoreSummonCooldownTicks > 0) {
this.manticoreSummonCooldownTicks--;
return;
}
if (!(this.level() instanceof ServerLevel serverLevel)) {
return;
}
net.minecraft.world.entity.LivingEntity target = this.getTarget();
if (target == null || !target.isAlive() || !this.canAttack(target)) {
return;
}
int currentCount = ManticoreEntity.countSummonedBy(serverLevel, this.getUUID());
int cap = AntarchySettings.queenManticoreCap();
if (currentCount >= cap) {
this.manticoreSummonCooldownTicks = FAILED_SUMMON_RETRY_TICKS;
return;
}
int summonCount = Math.min(AntarchySettings.queenManticoreSummonCount(), cap - currentCount);
int spawned = this.spawnManticoreTears(serverLevel, target, summonCount);
this.manticoreSummonCooldownTicks = spawned > 0
? Math.max(20, AntarchySettings.queenManticoreSummonCooldownTicks())
: FAILED_SUMMON_RETRY_TICKS;
if (spawned > 0) {
this.triggerAnim("body_action", "minion_spawn");
this.playSound(AntarchySoundEvents.QUEEN_ROAR.get(), 3.0F, 0.8F + this.random.nextFloat() * 0.12F);
serverLevel.sendParticles(
net.minecraft.core.particles.ParticleTypes.PORTAL,
this.getX(), this.getY() + 2.0D, this.getZ(),
36, 3.0D, 2.0D, 3.0D, 0.15D);
}
}
private int spawnManticoreTears(ServerLevel level, net.minecraft.world.entity.LivingEntity target, int count) {
int pairs = Math.max(1, Math.min(3, (count + 1) / 2));
int created = 0;
for (int i = 0; i < pairs; i++) {
double angle = this.random.nextDouble() * Mth.TWO_PI;
double distance = Math.max(8.0D, AntarchySettings.queenManticoreSummonRange() * 0.65D);
Vec3 firstPos = this.position().add(Math.cos(angle) * distance, 1.0D, Math.sin(angle) * distance);
Vec3 secondPos = this.position().add(Math.cos(angle + Math.PI) * distance, 1.0D, Math.sin(angle + Math.PI) * distance);
DimensionalTearEntity first = DimensionalTearEntity.createQueenManticoreTear(level, firstPos,
(float) Math.toDegrees(angle), 240, this.getUUID(), Math.min(3, count));
DimensionalTearEntity second = DimensionalTearEntity.createQueenManticoreTear(level, secondPos,
(float) Math.toDegrees(angle + Math.PI), 240, this.getUUID(), Math.min(3, count));
first.linkTo(second);
second.linkTo(first);
level.addFreshEntity(first);
level.addFreshEntity(second);
created++;
}
return created;
}
private void tickGravityAttacks() {
if (this.gravityStompCooldownTicks > 0) {
this.gravityStompCooldownTicks--;
}
if (this.timeFieldCooldownTicks > 0) {
this.timeFieldCooldownTicks--;
}
if (!(this.level() instanceof ServerLevel level)) {
return;
}
net.minecraft.world.entity.LivingEntity target = this.getTarget();
if (target == null || !target.isAlive()) {
return;
}
if (this.gravityStompCooldownTicks <= 0) {
this.gravityStompCooldownTicks = 180;
this.triggerAnim("body_action", "stomp");
this.playSound(AntarchySoundEvents.QUEEN_ROAR.get(), 3.0F, 0.7F);
DamageSource source = this.damageSources().mobAttack(this);
for (net.minecraft.world.entity.LivingEntity living : level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class,
this.getBoundingBox().inflate(18.0D), entity -> entity instanceof Player && entity.isAlive())) {
double distance = Math.max(1.0D, living.distanceTo(this));
living.hurt(source, (float) (12.0D * Math.max(0.25D, 1.0D - distance / 24.0D)));
Vec3 push = living.position().subtract(this.position()).normalize().scale(1.3D);
living.setDeltaMovement(living.getDeltaMovement().add(push.x, 0.65D, push.z));
living.hasImpulse = true;
}
}
if (this.timeFieldCooldownTicks <= 0) {
this.timeFieldCooldownTicks = 260;
TimeDilationApi.createField(level, target.position(), 12.0D, 0.45D, 140);
this.triggerAnim("body_action", "wing_gust");
}
}
@Override
public void die(DamageSource damageSource) {
if (!this.level().isClientSide && this.level() instanceof ServerLevel level) {
DimensionalTearEntity.discardQueenOwnedTears(level, this.getUUID());
}
super.die(damageSource);
}
private boolean spawnManticore(ServerLevel serverLevel, net.minecraft.world.entity.LivingEntity target) {
double minimumDistance = Math.max(4.0D, this.getBbWidth() * 0.55D);
double maximumDistance = Math.max(minimumDistance + 1.0D, AntarchySettings.queenManticoreSummonRange());
for (int attempt = 0; attempt < POSITION_ATTEMPTS_PER_MANTICORE; attempt++) {
double angle = this.random.nextDouble() * Mth.TWO_PI;
double distance = Mth.lerp(this.random.nextDouble(), minimumDistance, maximumDistance);
double x = this.getX() + Math.cos(angle) * distance;
double y = this.getY() + (this.random.nextDouble() - 0.5D) * 2.0D;
double z = this.getZ() + Math.sin(angle) * distance;
ManticoreEntity manticore = AntarchyObjects.MANTICORE.get().create(serverLevel);
if (manticore == null) {
return false;
}
manticore.moveTo(x, y, z, this.random.nextFloat() * 360.0F, 0.0F);
BlockPos spawnPos = manticore.blockPosition();
if (!serverLevel.noCollision(manticore)
|| !serverLevel.isEmptyBlock(spawnPos)
|| !ManticoreEntity.canSpawn(AntarchyObjects.MANTICORE.get(), serverLevel, MobSpawnType.MOB_SUMMONED, spawnPos, this.random)) {
manticore.discard();
continue;
}
manticore.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(spawnPos), MobSpawnType.MOB_SUMMONED, null);
manticore.markQueenSummoned(this.getUUID());
manticore.setTarget(target);
serverLevel.addFreshEntity(manticore);
return true;
}
return false;
}
@Override
public void addAdditionalSaveData(CompoundTag tag) {
super.addAdditionalSaveData(tag);
tag.putInt(SUMMON_COOLDOWN_KEY, this.manticoreSummonCooldownTicks);
tag.putInt("GravityStompCooldownTicks", this.gravityStompCooldownTicks);
tag.putInt("TimeFieldCooldownTicks", this.timeFieldCooldownTicks);
}
@Override
public void readAdditionalSaveData(CompoundTag tag) {
super.readAdditionalSaveData(tag);
this.manticoreSummonCooldownTicks = Math.max(0, tag.getInt(SUMMON_COOLDOWN_KEY));
this.gravityStompCooldownTicks = Math.max(0, tag.getInt("GravityStompCooldownTicks"));
this.timeFieldCooldownTicks = Math.max(0, tag.getInt("TimeFieldCooldownTicks"));
}
} }
@@ -5,6 +5,8 @@ import com.craisinlord.antarchy.content.entity.multipart.MultipartEntityOwner;
import com.craisinlord.antarchy.content.entity.multipart.MultipartLayout; import com.craisinlord.antarchy.content.entity.multipart.MultipartLayout;
import com.craisinlord.antarchy.content.entity.multipart.MultipartPartDefinition; import com.craisinlord.antarchy.content.entity.multipart.MultipartPartDefinition;
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamController; import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamController;
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamSettings;
import com.craisinlord.antarchy.content.entity.royal.beam.RoyalBeamTerrainMode;
import java.util.List; import java.util.List;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
@@ -50,7 +52,7 @@ import software.bernie.geckolib.util.GeckoLibUtil;
public abstract class RoyalBossEntity extends Monster implements GeoEntity, MultipartEntityOwner { public abstract class RoyalBossEntity extends Monster implements GeoEntity, MultipartEntityOwner {
public static final float MODEL_RENDER_SCALE = 2.0F; public static final float MODEL_RENDER_SCALE = 2.0F;
public static final float GAMEPLAY_WIDTH = 30.0F; public static final float GAMEPLAY_WIDTH = 30.0F;
public static final float GAMEPLAY_HEIGHT = 30.0F; public static final float GAMEPLAY_HEIGHT = 15.0F;
public enum Phase { public enum Phase {
ONE(1, 1.00F), ONE(1, 1.00F),
@@ -109,6 +111,10 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
new RoyalHead(RoyalHead.Slot.CENTER), new RoyalHead(RoyalHead.Slot.CENTER),
new RoyalHead(RoyalHead.Slot.RIGHT) new RoyalHead(RoyalHead.Slot.RIGHT)
}; };
private int beamCooldownTicks;
@Nullable
private RoyalHead activeBeamHead;
private int beamLoopSoundTicks;
@Nullable @Nullable
private Entity[] multipartParts; private Entity[] multipartParts;
@@ -136,6 +142,22 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
protected abstract SoundEvent royalBiteSound(); protected abstract SoundEvent royalBiteSound();
protected abstract SoundEvent royalBeamShootSound();
protected abstract SoundEvent royalBeamStartSound();
protected abstract SoundEvent royalBeamLoopSound();
protected abstract SoundEvent royalBeamEndSound();
protected abstract RoyalBeamSettings royalBeamSettings();
protected abstract RoyalBeamTerrainMode royalBeamTerrainMode();
protected RoyalBeamTerrainMode royalBeamTerrainMode(@Nullable RoyalHead head) {
return this.royalBeamTerrainMode();
}
public static AttributeSupplier.Builder createBaseAttributes(double health, double attackDamage) { public static AttributeSupplier.Builder createBaseAttributes(double health, double attackDamage) {
return Mob.createMobAttributes() return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, health) .add(Attributes.MAX_HEALTH, health)
@@ -272,6 +294,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
this.getLookControl().setLookAt(primaryTarget, 30.0F, 30.0F); this.getLookControl().setLookAt(primaryTarget, 30.0F, 30.0F);
this.assignHeadTargets(primaryTarget); this.assignHeadTargets(primaryTarget);
this.tickRoyalBeam(primaryTarget);
this.steerTowardTarget(primaryTarget); this.steerTowardTarget(primaryTarget);
this.tickBodyCrush(); this.tickBodyCrush();
@@ -304,6 +327,70 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
} }
} }
private void tickRoyalBeam(LivingEntity primaryTarget) {
if (this.beamCooldownTicks > 0) {
this.beamCooldownTicks--;
}
if (this.activeBeamHead != null) {
LivingEntity beamTarget = this.activeBeamHead.target(this.level());
if (!this.activeBeamHead.shooting() || beamTarget == null || !beamTarget.isAlive()) {
this.stopRoyalBeam();
} else {
if (this.beamLoopSoundTicks-- <= 0) {
this.beamLoopSoundTicks = 20;
this.playSound(this.royalBeamLoopSound(), 2.5F, 1.0F);
}
this.beamController.tick(
this.headAnchor(this.activeBeamHead),
beamTarget,
this.royalBeamSettings(),
this.royalBeamTerrainMode(this.activeBeamHead),
this::setRoyalBeamEndPosition);
if (!this.beamController.isFiring()) {
this.stopRoyalBeam();
}
return;
}
}
if (this.beamCooldownTicks > 0) {
return;
}
Phase phase = this.phase();
for (RoyalHead head : this.heads) {
LivingEntity target = head.target(this.level());
if (!head.readyToAttack() || target == null || !this.canAttack(target)
|| this.headWithinBiteReach(head, target)) {
continue;
}
int duration = Math.max(1, this.royalBeamSettings().durationTicks());
int cooldown = Math.max(1, Mth.floor(this.royalBeamSettings().cooldownTicks() * phase.cooldownScale()));
head.startShoot(duration, cooldown);
head.setBeamActive(true);
this.activeBeamHead = head;
this.beamCooldownTicks = cooldown;
this.beamController.start(this.headAnchor(head), target.getEyePosition(), duration);
this.setFiringRoyalBeam(true);
this.triggerAnim(head.slot().controllerName(), "shoot");
this.beamLoopSoundTicks = 20;
this.playSound(this.royalBeamStartSound(), 3.0F, 1.0F);
this.playSound(this.royalBeamShootSound(), 3.0F, 1.0F);
return;
}
}
private void stopRoyalBeam() {
if (this.activeBeamHead != null) {
this.activeBeamHead.setBeamActive(false);
}
this.activeBeamHead = null;
this.beamController.stop();
this.playSound(this.royalBeamEndSound(), 2.5F, 1.0F);
this.setFiringRoyalBeam(false);
this.setRoyalBeamEndPosition(null);
}
public Phase phase() { public Phase phase() {
float fraction = this.getMaxHealth() <= 0.0F ? 1.0F : this.getHealth() / this.getMaxHealth(); float fraction = this.getMaxHealth() <= 0.0F ? 1.0F : this.getHealth() / this.getMaxHealth();
if (fraction > PHASE_TWO_THRESHOLD) { if (fraction > PHASE_TWO_THRESHOLD) {
@@ -512,6 +599,9 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
} }
public Vec3 getRoyalBeamShootFrom(float partialTicks) { public Vec3 getRoyalBeamShootFrom(float partialTicks) {
if (this.activeBeamHead != null) {
return this.headAnchor(this.activeBeamHead);
}
double x = Mth.lerp(partialTicks, this.xo, this.getX()); double x = Mth.lerp(partialTicks, this.xo, this.getX());
double y = Mth.lerp(partialTicks, this.yo, this.getY()) + this.getBbHeight() * 0.72D; double y = Mth.lerp(partialTicks, this.yo, this.getY()) + this.getBbHeight() * 0.72D;
double z = Mth.lerp(partialTicks, this.zo, this.getZ()); double z = Mth.lerp(partialTicks, this.zo, this.getZ());
@@ -9,11 +9,11 @@ public final class RoyalBossMultipartLayout implements MultipartLayout {
public static final MultipartPartDefinition BODY = new MultipartPartDefinition( public static final MultipartPartDefinition BODY = new MultipartPartDefinition(
"body", 20.0F, 24.0F, 1.00F, 0.0D, 3.0D, 0.0D, true); "body", 20.0F, 24.0F, 1.00F, 0.0D, 3.0D, 0.0D, true);
public static final MultipartPartDefinition LEFT_HEAD = new MultipartPartDefinition( public static final MultipartPartDefinition LEFT_HEAD = new MultipartPartDefinition(
"left_head", 8.0F, 8.0F, 1.30F, 12.0D, 20.0D, -7.0D, true); "left_head", 4.0F, 4.0F, 1.30F, 12.0D, 20.0D, -7.0D, true);
public static final MultipartPartDefinition CENTER_HEAD = new MultipartPartDefinition( public static final MultipartPartDefinition CENTER_HEAD = new MultipartPartDefinition(
"center_head", 9.0F, 9.0F, 1.20F, 13.0D, 22.0D, 0.0D, true); "center_head", 4.5F, 4.5F, 1.20F, 13.0D, 22.0D, 0.0D, true);
public static final MultipartPartDefinition RIGHT_HEAD = new MultipartPartDefinition( public static final MultipartPartDefinition RIGHT_HEAD = new MultipartPartDefinition(
"right_head", 8.0F, 8.0F, 1.30F, 12.0D, 20.0D, 7.0D, true); "right_head", 4.0F, 4.0F, 1.30F, 12.0D, 20.0D, 7.0D, true);
public static final MultipartPartDefinition LEFT_WING = new MultipartPartDefinition( public static final MultipartPartDefinition LEFT_WING = new MultipartPartDefinition(
"left_wing", 14.0F, 16.0F, 0.85F, -2.0D, 14.0D, -13.0D, true); "left_wing", 14.0F, 16.0F, 0.85F, -2.0D, 14.0D, -13.0D, true);
public static final MultipartPartDefinition RIGHT_WING = new MultipartPartDefinition( public static final MultipartPartDefinition RIGHT_WING = new MultipartPartDefinition(
@@ -94,6 +94,10 @@ public final class RoyalHead {
return this.beamActive; return this.beamActive;
} }
public boolean shooting() {
return this.shootTicks > 0;
}
public boolean tickBiteHit() { public boolean tickBiteHit() {
if (this.biteTicks <= 0) { if (this.biteTicks <= 0) {
return false; return false;
@@ -1,6 +1,8 @@
package com.craisinlord.antarchy.content.entity.royal.beam; package com.craisinlord.antarchy.content.entity.royal.beam;
import java.util.List; import java.util.List;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
@@ -117,15 +119,16 @@ public final class RoyalBeamController {
Vec3 direction = beamEnd.subtract(shootFrom).normalize(); Vec3 direction = beamEnd.subtract(shootFrom).normalize();
double distance = shootFrom.distanceTo(beamEnd); double distance = shootFrom.distanceTo(beamEnd);
DamageSource damageSource = this.owner.damageSources().mobAttack(this.owner); DamageSource damageSource = this.owner.damageSources().mobAttack(this.owner);
Set<Integer> damagedThisTick = new HashSet<>();
for (double walked = settings.pathStep(); walked < Math.min(distance, settings.range()); walked += settings.pathStep()) { for (double walked = settings.pathStep(); walked < Math.min(distance, settings.range()); walked += settings.pathStep()) {
Vec3 sample = shootFrom.add(direction.scale(walked)); Vec3 sample = shootFrom.add(direction.scale(walked));
hurtEntitiesAround(sample, settings.pathDamageRadius(), settings.damage(), settings.knockback(), damageSource, settings.requireLineOfSightForDamage()); hurtEntitiesAround(sample, settings.pathDamageRadius(), settings.damage(), settings.knockback(), damageSource, settings.requireLineOfSightForDamage(), damagedThisTick);
if (shouldMutateTerrain(settings, walked)) { if (shouldMutateTerrain(settings, walked)) {
mutateTerrainAround(sample, settings.pathTerrainRadius(), settings, terrainMode); mutateTerrainAround(sample, settings.pathTerrainRadius(), settings, terrainMode);
} }
} }
hurtEntitiesAround(beamEnd, settings.impactDamageRadius(), settings.damage(), settings.knockback(), damageSource, settings.requireLineOfSightForDamage()); hurtEntitiesAround(beamEnd, settings.impactDamageRadius(), settings.damage(), settings.knockback(), damageSource, settings.requireLineOfSightForDamage(), damagedThisTick);
if (shouldMutateTerrain(settings, shootFrom.distanceTo(beamEnd))) { if (shouldMutateTerrain(settings, shootFrom.distanceTo(beamEnd))) {
mutateTerrainAround(beamEnd, settings.impactTerrainRadius(), settings, terrainMode); mutateTerrainAround(beamEnd, settings.impactTerrainRadius(), settings, terrainMode);
} }
@@ -145,7 +148,8 @@ public final class RoyalBeamController {
float damageAmount, float damageAmount,
float knockbackAmount, float knockbackAmount,
DamageSource damageSource, DamageSource damageSource,
boolean requireLineOfSight boolean requireLineOfSight,
Set<Integer> damagedThisTick
) { ) {
if (radius <= 0.0F || damageAmount <= 0.0F) { if (radius <= 0.0F || damageAmount <= 0.0F) {
return false; return false;
@@ -163,10 +167,12 @@ public final class RoyalBeamController {
|| this.owner.isAlliedTo(living) || this.owner.isAlliedTo(living)
|| living.getType() == this.owner.getType() || living.getType() == this.owner.getType()
|| living.distanceToSqr(center) > radius * radius || living.distanceToSqr(center) > radius * radius
|| damagedThisTick.contains(living.getId())
|| requireLineOfSight && !canEntityBeHurtFrom(center, living)) { || requireLineOfSight && !canEntityBeHurtFrom(center, living)) {
continue; continue;
} }
if (living.hurt(damageSource, damageAmount)) { if (living.hurt(damageSource, damageAmount)) {
damagedThisTick.add(living.getId());
hurtAny = true; hurtAny = true;
knockbackTarget(living, knockbackAmount); knockbackTarget(living, knockbackAmount);
} }
@@ -4,6 +4,8 @@ public record RoyalBeamSettings(
double range, double range,
double targetTracking, double targetTracking,
double pathStep, double pathStep,
int durationTicks,
int cooldownTicks,
float pathDamageRadius, float pathDamageRadius,
float impactDamageRadius, float impactDamageRadius,
float damage, float damage,
@@ -24,6 +26,8 @@ public record RoyalBeamSettings(
100.0D, 100.0D,
0.1D, 0.1D,
7.5D, 7.5D,
30,
90,
6.0F, 6.0F,
6.0F, 6.0F,
damage, damage,
@@ -45,6 +49,8 @@ public record RoyalBeamSettings(
range = Math.max(1.0D, range); range = Math.max(1.0D, range);
targetTracking = Math.clamp(targetTracking, 0.0D, 1.0D); targetTracking = Math.clamp(targetTracking, 0.0D, 1.0D);
pathStep = Math.max(1.0D, pathStep); pathStep = Math.max(1.0D, pathStep);
durationTicks = Math.max(1, durationTicks);
cooldownTicks = Math.max(1, cooldownTicks);
pathDamageRadius = Math.max(0.0F, pathDamageRadius); pathDamageRadius = Math.max(0.0F, pathDamageRadius);
impactDamageRadius = Math.max(0.0F, impactDamageRadius); impactDamageRadius = Math.max(0.0F, impactDamageRadius);
damage = Math.max(0.0F, damage); damage = Math.max(0.0F, damage);
@@ -0,0 +1,9 @@
package com.craisinlord.antarchy.content.entity.royal.decree;
import com.craisinlord.antarchy.content.entity.royal.KingEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3;
public final class AdvanceDecree implements RoyalDecree {
public String name() { return "ADVANCE"; }
public void apply(ServerLevel level, KingEntity king, LivingEntity target) { Vec3 p = king.position().subtract(target.position()).normalize().scale(0.35D); target.setDeltaMovement(target.getDeltaMovement().add(p.x, 0.05D, p.z)); target.hasImpulse = true; }
}
@@ -0,0 +1,8 @@
package com.craisinlord.antarchy.content.entity.royal.decree;
import com.craisinlord.antarchy.content.entity.royal.KingEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
public final class CloseQuartersDecree implements RoyalDecree {
public String name() { return "CLOSE QUARTERS"; }
public void apply(ServerLevel level, KingEntity king, LivingEntity target) { if (target.distanceTo(king) <= 12.0D) target.hurt(king.damageSources().mobAttack(king), 4.0F); }
}
@@ -0,0 +1,9 @@
package com.craisinlord.antarchy.content.entity.royal.decree;
import com.craisinlord.antarchy.content.entity.royal.KingEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.phys.Vec3;
public final class KeepYourDistanceDecree implements RoyalDecree {
public String name() { return "KEEP YOUR DISTANCE"; }
public void apply(ServerLevel level, KingEntity king, LivingEntity target) { if (target.distanceTo(king) < 18.0D) { Vec3 p = target.position().subtract(king.position()).normalize().scale(0.8D); target.setDeltaMovement(target.getDeltaMovement().add(p.x, 0.2D, p.z)); target.hasImpulse = true; } }
}
@@ -0,0 +1,8 @@
package com.craisinlord.antarchy.content.entity.royal.decree;
import com.craisinlord.antarchy.content.entity.royal.KingEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
public final class NoRetreatDecree implements RoyalDecree {
public String name() { return "NO RETREAT"; }
public void apply(ServerLevel level, KingEntity king, LivingEntity target) { if (target.distanceTo(king) > 28.0D) target.hurt(king.damageSources().mobAttack(king), 3.0F); }
}
@@ -0,0 +1,10 @@
package com.craisinlord.antarchy.content.entity.royal.decree;
import com.craisinlord.antarchy.content.entity.royal.KingEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
public interface RoyalDecree {
String name();
void apply(ServerLevel level, KingEntity king, LivingEntity target);
}
@@ -78,6 +78,10 @@ public class TimeDilationFieldEntity extends Entity {
return TimeDilationMath.clampRate(this.entityData.get(RATE)); return TimeDilationMath.clampRate(this.entityData.get(RATE));
} }
public double effectiveFieldRate() {
return TimeDilationMath.effectiveFieldRate(this.fieldRate(), this.age, this.durationTicks);
}
public int fieldDurationTicks() { public int fieldDurationTicks() {
return this.durationTicks; return this.durationTicks;
} }
@@ -23,7 +23,7 @@ public final class TimeDilationFieldSampler {
continue; continue;
} }
double falloff = TimeDilationMath.gaussianFalloff(Math.sqrt(distanceSqr), field.fieldRadius()); double falloff = TimeDilationMath.gaussianFalloff(Math.sqrt(distanceSqr), field.fieldRadius());
combinedRate *= TimeDilationMath.localFieldRate(field.fieldRate(), falloff); combinedRate *= TimeDilationMath.localFieldRate(field.effectiveFieldRate(), falloff);
} }
return TimeDilationMath.clampRate(combinedRate); return TimeDilationMath.clampRate(combinedRate);
} }
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.time;
public final class TimeDilationMath { public final class TimeDilationMath {
public static final double MIN_RATE = 0.05D; public static final double MIN_RATE = 0.05D;
public static final double NORMAL_RATE = 1.0D; public static final double NORMAL_RATE = 1.0D;
public static final int FIELD_TRANSITION_TICKS = 20;
private static final double GAUSSIAN_EDGE_EXPONENT = -4.5D; private static final double GAUSSIAN_EDGE_EXPONENT = -4.5D;
private TimeDilationMath() { private TimeDilationMath() {
@@ -31,4 +32,25 @@ public final class TimeDilationMath {
} }
return Math.pow(clampedRate, clampedFalloff); return Math.pow(clampedRate, clampedFalloff);
} }
public static double smoothStep(double value) {
double clamped = Math.max(0.0D, Math.min(1.0D, value));
return clamped * clamped * (3.0D - 2.0D * clamped);
}
public static double fieldStrength(int age, int durationTicks) {
double fadeIn = smoothStep((double) age / FIELD_TRANSITION_TICKS);
if (durationTicks < 0) {
return fadeIn;
}
double remaining = durationTicks - age;
double fadeOut = smoothStep(remaining / FIELD_TRANSITION_TICKS);
return Math.min(fadeIn, fadeOut);
}
public static double effectiveFieldRate(double fieldRate, int age, int durationTicks) {
double strength = fieldStrength(age, durationTicks);
return NORMAL_RATE + (clampRate(fieldRate) - NORMAL_RATE) * strength;
}
} }
@@ -103,6 +103,7 @@ public class ElythiaBiomeSource extends BiomeSource {
private final Holder<Biome> glimmeringPoolsHolder; private final Holder<Biome> glimmeringPoolsHolder;
private final Holder<Biome> ouranwoodForestHolder; private final Holder<Biome> ouranwoodForestHolder;
private final Holder<Biome> cloudSeaHolder; private final Holder<Biome> cloudSeaHolder;
private final Holder<Biome> firstConfiguredHolder;
public ElythiaBiomeSource(Climate.ParameterList<Holder<Biome>> parameters, int molewormCavesMaxY, int surfaceBiomeSampleY, int oceanMaxY, int seaLevel, int cloudSeaMinY) { public ElythiaBiomeSource(Climate.ParameterList<Holder<Biome>> parameters, int molewormCavesMaxY, int surfaceBiomeSampleY, int oceanMaxY, int seaLevel, int cloudSeaMinY) {
this.parameters = parameters; this.parameters = parameters;
@@ -145,6 +146,10 @@ public class ElythiaBiomeSource extends BiomeSource {
.filter(h -> h.is(CLOUD_SEA)) .filter(h -> h.is(CLOUD_SEA))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
this.firstConfiguredHolder = parameters.values().stream()
.map(Pair::getSecond)
.findFirst()
.orElse(null);
} }
private Climate.ParameterList<Holder<Biome>> parameters() { return this.parameters; } private Climate.ParameterList<Holder<Biome>> parameters() { return this.parameters; }
@@ -178,6 +183,9 @@ public class ElythiaBiomeSource extends BiomeSource {
} }
Holder<Biome> biome = this.delegate.getNoiseBiome(x, y, z, sampler); Holder<Biome> biome = this.delegate.getNoiseBiome(x, y, z, sampler);
if (biome == null) {
return resolveConfiguredFallback(x, y, z, sampler);
}
// Defensive: cloud_sea's multi-noise parameter point is reserved far off in "offset" // Defensive: cloud_sea's multi-noise parameter point is reserved far off in "offset"
// so it shouldn't win nearest-neighbor on its own, but if it ever does for a query // so it shouldn't win nearest-neighbor on its own, but if it ever does for a query
@@ -196,7 +204,7 @@ public class ElythiaBiomeSource extends BiomeSource {
if (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)) return biome; if (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)) return biome;
Holder<Biome> seaLevelBiome = this.delegate.getNoiseBiome(x, this.seaLevelQuartY, z, sampler); Holder<Biome> seaLevelBiome = this.delegate.getNoiseBiome(x, this.seaLevelQuartY, z, sampler);
if (isOceanBiome(seaLevelBiome)) return seaLevelBiome; if (isOceanBiome(seaLevelBiome)) return seaLevelBiome;
return oceanHolder != null ? oceanHolder : seaLevelBiome; return oceanHolder != null ? oceanHolder : nullToConfiguredFallback(seaLevelBiome, x, y, z, sampler);
} }
if (y <= this.seaLevelQuartY && oceanHolder != null && !allowedBelowSeaLevel(biome)) { if (y <= this.seaLevelQuartY && oceanHolder != null && !allowedBelowSeaLevel(biome)) {
return oceanHolder; return oceanHolder;
@@ -221,17 +229,17 @@ public class ElythiaBiomeSource extends BiomeSource {
} }
private static boolean allowedBelowSeaLevel(Holder<Biome> biome) { private static boolean allowedBelowSeaLevel(Holder<Biome> biome) {
return biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES) return biome != null && (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)
|| biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES); || biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES));
} }
private static boolean isOceanBiome(Holder<Biome> biome) { private static boolean isOceanBiome(Holder<Biome> biome) {
return biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES); return biome != null && (biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES));
} }
private static boolean isOuranwoodBiome(Holder<Biome> biome) { private static boolean isOuranwoodBiome(Holder<Biome> biome) {
return biome.is(OURANWOOD_FOREST) || biome.is(SPARSE_OURANWOOD_FOREST) return biome != null && (biome.is(OURANWOOD_FOREST) || biome.is(SPARSE_OURANWOOD_FOREST)
|| biome.is(FUNGAL_OURANWOOD_FOREST); || biome.is(FUNGAL_OURANWOOD_FOREST));
} }
private static boolean isGlimmeringPoolsCandidate(Holder<Biome> biome, Climate.TargetPoint target, int x, int z) { private static boolean isGlimmeringPoolsCandidate(Holder<Biome> biome, Climate.TargetPoint target, int x, int z) {
@@ -311,6 +319,7 @@ public class ElythiaBiomeSource extends BiomeSource {
} }
} }
} }
result = nullToConfiguredFallback(result, x, this.surfaceBiomeSampleQuartY, z, sampler);
cache.key = key; cache.key = key;
cache.value = result; cache.value = result;
@@ -336,6 +345,7 @@ public class ElythiaBiomeSource extends BiomeSource {
} }
result = resolved != null ? resolved : (defaultLandHolder != null ? defaultLandHolder : result); result = resolved != null ? resolved : (defaultLandHolder != null ? defaultLandHolder : result);
} }
result = nullToConfiguredFallback(result, x, this.surfaceBiomeSampleQuartY, z, sampler);
cache.key = key; cache.key = key;
cache.value = result; cache.value = result;
@@ -344,6 +354,9 @@ public class ElythiaBiomeSource extends BiomeSource {
@SafeVarargs @SafeVarargs
private static boolean isExcluded(Holder<Biome> biome, ResourceKey<Biome>... excluded) { private static boolean isExcluded(Holder<Biome> biome, ResourceKey<Biome>... excluded) {
if (biome == null) {
return true;
}
for (ResourceKey<Biome> key : excluded) { for (ResourceKey<Biome> key : excluded) {
if (biome.is(key)) return true; if (biome.is(key)) return true;
} }
@@ -351,11 +364,30 @@ public class ElythiaBiomeSource extends BiomeSource {
} }
private static boolean isOceanOrCave(Holder<Biome> biome) { private static boolean isOceanOrCave(Holder<Biome> biome) {
return isOceanBiome(biome) || biome.is(ELYTHIA_BEACH) return biome == null || isOceanBiome(biome) || biome.is(ELYTHIA_BEACH)
|| biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES) || biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES)
|| biome.is(GLIMMERING_POOLS) || biome.is(CLOUD_SEA); || biome.is(GLIMMERING_POOLS) || biome.is(CLOUD_SEA);
} }
private Holder<Biome> nullToConfiguredFallback(Holder<Biome> biome, int x, int y, int z, Climate.Sampler sampler) {
return biome != null ? biome : resolveConfiguredFallback(x, y, z, sampler);
}
private Holder<Biome> resolveConfiguredFallback(int x, int y, int z, Climate.Sampler sampler) {
if (y <= this.oceanMaxQuartY && this.oceanHolder != null) {
Climate.TargetPoint target = sampler.sample(x, this.seaLevelQuartY, z);
if (target.continentalness() < OCEAN_CONTINENTALNESS_THRESHOLD) {
return this.oceanHolder;
}
}
if (this.defaultLandHolder != null) return this.defaultLandHolder;
if (this.ouranwoodForestHolder != null) return this.ouranwoodForestHolder;
if (this.glimmeringPoolsHolder != null) return this.glimmeringPoolsHolder;
if (this.oceanHolder != null) return this.oceanHolder;
if (this.cloudSeaHolder != null) return this.cloudSeaHolder;
return this.firstConfiguredHolder;
}
@Override @Override
public void addDebugInfo(java.util.List<String> debug, net.minecraft.core.BlockPos pos, Climate.Sampler sampler) { public void addDebugInfo(java.util.List<String> debug, net.minecraft.core.BlockPos pos, Climate.Sampler sampler) {
try { try {
@@ -8,7 +8,14 @@
"location": "antarchy:kings_tree/kings_tree2", "location": "antarchy:kings_tree/kings_tree2",
"processors": "antarchy:generic_processor", "processors": "antarchy:generic_processor",
"projection": "rigid", "projection": "rigid",
"element_type": "minecraft:single_pool_element" "enhanced_terrain_adaptation": {
"type": "integrated_api:custom",
"carves": true,
"beards": true,
"kernel_size": 35,
"kernel_distance": 35
},
"element_type": "integrated_api:integrated_api_single_pool_element"
} }
} }
] ]
@@ -8,7 +8,14 @@
"location": "antarchy:kings_tree/kings_tree3", "location": "antarchy:kings_tree/kings_tree3",
"processors": "antarchy:generic_processor", "processors": "antarchy:generic_processor",
"projection": "rigid", "projection": "rigid",
"element_type": "minecraft:single_pool_element" "enhanced_terrain_adaptation": {
"type": "integrated_api:custom",
"carves": true,
"beards": true,
"kernel_size": 35,
"kernel_distance": 35
},
"element_type": "integrated_api:integrated_api_single_pool_element"
} }
} }
] ]
@@ -8,7 +8,14 @@
"location": "antarchy:kings_tree/kings_tree4", "location": "antarchy:kings_tree/kings_tree4",
"processors": "antarchy:generic_processor", "processors": "antarchy:generic_processor",
"projection": "rigid", "projection": "rigid",
"element_type": "minecraft:single_pool_element" "enhanced_terrain_adaptation": {
"type": "integrated_api:custom",
"carves": true,
"beards": true,
"kernel_size": 35,
"kernel_distance": 35
},
"element_type": "integrated_api:integrated_api_single_pool_element"
} }
} }
] ]
@@ -11,7 +11,7 @@
"enhanced_terrain_adaptation": { "enhanced_terrain_adaptation": {
"type": "integrated_api:custom", "type": "integrated_api:custom",
"carves": true, "carves": true,
"beards": false, "beards": true,
"kernel_size": 35, "kernel_size": 35,
"kernel_distance": 35 "kernel_distance": 35
}, },
@@ -313,7 +313,15 @@ public final class AntarchyFabricContent {
AntarchyFabricSounds.QUEEN_IDLE, AntarchyFabricSounds.QUEEN_IDLE,
AntarchyFabricSounds.QUEEN_HURT, AntarchyFabricSounds.QUEEN_HURT,
AntarchyFabricSounds.QUEEN_DEATH, AntarchyFabricSounds.QUEEN_DEATH,
AntarchyFabricSounds.QUEEN_BITE AntarchyFabricSounds.QUEEN_BITE,
AntarchyFabricSounds.QUEEN_ROAR,
AntarchyFabricSounds.KING_BEAM_SHOOT,
AntarchyFabricSounds.KING_FIREBALL_SHOOT,
AntarchyFabricSounds.KING_DECREE_CAST,
AntarchyFabricSounds.QUEEN_BEAM_SHOOT,
AntarchyFabricSounds.QUEEN_BEAM_START,
AntarchyFabricSounds.QUEEN_BEAM_LOOP,
AntarchyFabricSounds.QUEEN_BEAM_END
); );
AntarchyObjects.setOctopusBomb(AntarchyFabricEntities.OCTOPUS_BOMB); AntarchyObjects.setOctopusBomb(AntarchyFabricEntities.OCTOPUS_BOMB);
@@ -1807,7 +1807,7 @@ public final class AntarchyFabricItems {
() -> new DeferredSpawnEggItem(AntarchyFabricEntities.LURKING_TERROR, 0x2D5A1B, 0x8B0000, new Item.Properties())); () -> new DeferredSpawnEggItem(AntarchyFabricEntities.LURKING_TERROR, 0x2D5A1B, 0x8B0000, new Item.Properties()));
public static final DeferredItem<DeferredSpawnEggItem> MANTICORE_SPAWN_EGG = ITEMS.register("manticore_spawn_egg", public static final DeferredItem<DeferredSpawnEggItem> MANTICORE_SPAWN_EGG = ITEMS.register("manticore_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyFabricEntities.MANTICORE, 0x8A3B1E, 0x2B1B12, new Item.Properties())); () -> new DeferredSpawnEggItem(AntarchyFabricEntities.MANTICORE, 0xA3AEE9, 0x956570, new Item.Properties()));
public static final DeferredItem<DeferredSpawnEggItem> HERCULES_BEETLE_SPAWN_EGG = ITEMS.register("hercules_beetle_spawn_egg", public static final DeferredItem<DeferredSpawnEggItem> HERCULES_BEETLE_SPAWN_EGG = ITEMS.register("hercules_beetle_spawn_egg",
@@ -149,6 +149,20 @@ public final class AntarchyConfigModuleNeoforge {
AntarchySettings.setRoyalBossBiteReach(AntarchyMobsConfig.royalBossBiteReach()); AntarchySettings.setRoyalBossBiteReach(AntarchyMobsConfig.royalBossBiteReach());
AntarchySettings.setRoyalBossBiteDamageMultiplier(AntarchyMobsConfig.royalBossBiteDamageMultiplier()); AntarchySettings.setRoyalBossBiteDamageMultiplier(AntarchyMobsConfig.royalBossBiteDamageMultiplier());
AntarchySettings.setRoyalBossBiteCooldownTicks(AntarchyMobsConfig.royalBossBiteCooldownTicks()); AntarchySettings.setRoyalBossBiteCooldownTicks(AntarchyMobsConfig.royalBossBiteCooldownTicks());
AntarchySettings.setQueenBeamDamage(AntarchyMobsConfig.queenBeamDamage());
AntarchySettings.setQueenBeamRange(AntarchyMobsConfig.queenBeamRange());
AntarchySettings.setQueenBeamDurationTicks(AntarchyMobsConfig.queenBeamDurationTicks());
AntarchySettings.setQueenBeamCooldownTicks(AntarchyMobsConfig.queenBeamCooldownTicks());
AntarchySettings.setQueenBeamTracking(AntarchyMobsConfig.queenBeamTracking());
AntarchySettings.setQueenBeamTerrainRadius(AntarchyMobsConfig.queenBeamTerrainRadius());
AntarchySettings.setQueenBeamTerrainCap(AntarchyMobsConfig.queenBeamTerrainCap());
AntarchySettings.setKingBeamDamage(AntarchyMobsConfig.kingBeamDamage());
AntarchySettings.setKingBeamRange(AntarchyMobsConfig.kingBeamRange());
AntarchySettings.setKingBeamDurationTicks(AntarchyMobsConfig.kingBeamDurationTicks());
AntarchySettings.setKingBeamCooldownTicks(AntarchyMobsConfig.kingBeamCooldownTicks());
AntarchySettings.setKingBeamTracking(AntarchyMobsConfig.kingBeamTracking());
AntarchySettings.setKingBeamTerrainRadius(AntarchyMobsConfig.kingBeamTerrainRadius());
AntarchySettings.setKingBeamTerrainCap(AntarchyMobsConfig.kingBeamTerrainCap());
AntarchySettings.setBrutalflyHealth(AntarchyMobsConfig.brutalflyHealth()); AntarchySettings.setBrutalflyHealth(AntarchyMobsConfig.brutalflyHealth());
AntarchySettings.setBrutalflySwipeDamage(AntarchyMobsConfig.brutalflySwipeDamage()); AntarchySettings.setBrutalflySwipeDamage(AntarchyMobsConfig.brutalflySwipeDamage());
@@ -286,6 +300,9 @@ public final class AntarchyConfigModuleNeoforge {
AntarchySettings.setManticoreAttackDamage(AntarchyMobsConfig.manticoreAttackDamage()); AntarchySettings.setManticoreAttackDamage(AntarchyMobsConfig.manticoreAttackDamage());
AntarchySettings.setManticoreStingPoisonTicks(AntarchyMobsConfig.manticoreStingPoisonTicks()); AntarchySettings.setManticoreStingPoisonTicks(AntarchyMobsConfig.manticoreStingPoisonTicks());
AntarchySettings.setQueenManticoreCap(AntarchyMobsConfig.queenManticoreCap()); AntarchySettings.setQueenManticoreCap(AntarchyMobsConfig.queenManticoreCap());
AntarchySettings.setQueenManticoreSummonCooldownTicks(AntarchyMobsConfig.queenManticoreSummonCooldownTicks());
AntarchySettings.setQueenManticoreSummonCount(AntarchyMobsConfig.queenManticoreSummonCount());
AntarchySettings.setQueenManticoreSummonRange(AntarchyMobsConfig.queenManticoreSummonRange());
AntarchySettings.setJerryInfantHealth(AntarchyMobsConfig.jerryInfantHealth()); AntarchySettings.setJerryInfantHealth(AntarchyMobsConfig.jerryInfantHealth());
AntarchySettings.setJerryInfantAttackDamage(AntarchyMobsConfig.jerryInfantAttackDamage()); AntarchySettings.setJerryInfantAttackDamage(AntarchyMobsConfig.jerryInfantAttackDamage());
AntarchySettings.setJerryMatureHealth(AntarchyMobsConfig.jerryMatureHealth()); AntarchySettings.setJerryMatureHealth(AntarchyMobsConfig.jerryMatureHealth());
@@ -124,6 +124,10 @@ public final class AntarchyMobsConfig {
private static final ModConfigSpec.DoubleValue ROYAL_BOSS_BITE_REACH; private static final ModConfigSpec.DoubleValue ROYAL_BOSS_BITE_REACH;
private static final ModConfigSpec.DoubleValue ROYAL_BOSS_BITE_DAMAGE_MULTIPLIER; private static final ModConfigSpec.DoubleValue ROYAL_BOSS_BITE_DAMAGE_MULTIPLIER;
private static final ModConfigSpec.IntValue ROYAL_BOSS_BITE_COOLDOWN_TICKS; private static final ModConfigSpec.IntValue ROYAL_BOSS_BITE_COOLDOWN_TICKS;
private static final ModConfigSpec.DoubleValue QUEEN_BEAM_DAMAGE, QUEEN_BEAM_RANGE, QUEEN_BEAM_TRACKING, QUEEN_BEAM_TERRAIN_RADIUS;
private static final ModConfigSpec.IntValue QUEEN_BEAM_DURATION_TICKS, QUEEN_BEAM_COOLDOWN_TICKS, QUEEN_BEAM_TERRAIN_CAP;
private static final ModConfigSpec.DoubleValue KING_BEAM_DAMAGE, KING_BEAM_RANGE, KING_BEAM_TRACKING, KING_BEAM_TERRAIN_RADIUS;
private static final ModConfigSpec.IntValue KING_BEAM_DURATION_TICKS, KING_BEAM_COOLDOWN_TICKS, KING_BEAM_TERRAIN_CAP;
// Brutalfly // Brutalfly
@@ -273,6 +277,9 @@ public final class AntarchyMobsConfig {
private static final ModConfigSpec.DoubleValue MANTICORE_ATTACK_DAMAGE; private static final ModConfigSpec.DoubleValue MANTICORE_ATTACK_DAMAGE;
private static final ModConfigSpec.IntValue MANTICORE_STING_POISON_TICKS; private static final ModConfigSpec.IntValue MANTICORE_STING_POISON_TICKS;
private static final ModConfigSpec.IntValue QUEEN_MANTICORE_CAP; private static final ModConfigSpec.IntValue QUEEN_MANTICORE_CAP;
private static final ModConfigSpec.IntValue QUEEN_MANTICORE_SUMMON_COOLDOWN_TICKS;
private static final ModConfigSpec.IntValue QUEEN_MANTICORE_SUMMON_COUNT;
private static final ModConfigSpec.DoubleValue QUEEN_MANTICORE_SUMMON_RANGE;
// Jerry // Jerry
@@ -549,6 +556,20 @@ public final class AntarchyMobsConfig {
ROYAL_BOSS_BITE_REACH = b.comment("Radius around each head anchor that a King or Queen bite can hit.").defineInRange("biteReach", 10.0D, 1.0D, 64.0D); ROYAL_BOSS_BITE_REACH = b.comment("Radius around each head anchor that a King or Queen bite can hit.").defineInRange("biteReach", 10.0D, 1.0D, 64.0D);
ROYAL_BOSS_BITE_DAMAGE_MULTIPLIER = b.comment("Multiplier applied to base attack damage for King and Queen head bites.").defineInRange("biteDamageMultiplier", 1.6D, 0.0D, 32.0D); ROYAL_BOSS_BITE_DAMAGE_MULTIPLIER = b.comment("Multiplier applied to base attack damage for King and Queen head bites.").defineInRange("biteDamageMultiplier", 1.6D, 0.0D, 32.0D);
ROYAL_BOSS_BITE_COOLDOWN_TICKS = b.comment("Base cooldown in ticks between bites for a single King or Queen head (scaled down at later phases).").defineInRange("biteCooldownTicks", 45, 1, 1200); ROYAL_BOSS_BITE_COOLDOWN_TICKS = b.comment("Base cooldown in ticks between bites for a single King or Queen head (scaled down at later phases).").defineInRange("biteCooldownTicks", 45, 1, 1200);
QUEEN_BEAM_DAMAGE = b.defineInRange("queenBeamDamage", 45.0D, 0.0D, 1024.0D);
QUEEN_BEAM_RANGE = b.defineInRange("queenBeamRange", 100.0D, 1.0D, 256.0D);
QUEEN_BEAM_DURATION_TICKS = b.defineInRange("queenBeamDurationTicks", 30, 1, 1200);
QUEEN_BEAM_COOLDOWN_TICKS = b.defineInRange("queenBeamCooldownTicks", 90, 1, 2400);
QUEEN_BEAM_TRACKING = b.defineInRange("queenBeamTracking", 0.1D, 0.0D, 1.0D);
QUEEN_BEAM_TERRAIN_RADIUS = b.defineInRange("queenBeamTerrainRadius", 5.0D, 0.0D, 32.0D);
QUEEN_BEAM_TERRAIN_CAP = b.defineInRange("queenBeamTerrainCap", 192, 0, 4096);
KING_BEAM_DAMAGE = b.defineInRange("kingBeamDamage", 50.0D, 0.0D, 1024.0D);
KING_BEAM_RANGE = b.defineInRange("kingBeamRange", 100.0D, 1.0D, 256.0D);
KING_BEAM_DURATION_TICKS = b.defineInRange("kingBeamDurationTicks", 30, 1, 1200);
KING_BEAM_COOLDOWN_TICKS = b.defineInRange("kingBeamCooldownTicks", 90, 1, 2400);
KING_BEAM_TRACKING = b.defineInRange("kingBeamTracking", 0.1D, 0.0D, 1.0D);
KING_BEAM_TERRAIN_RADIUS = b.defineInRange("kingBeamTerrainRadius", 5.0D, 0.0D, 32.0D);
KING_BEAM_TERRAIN_CAP = b.defineInRange("kingBeamTerrainCap", 192, 0, 4096);
b.pop(); b.pop();
@@ -772,6 +793,9 @@ public final class AntarchyMobsConfig {
MANTICORE_ATTACK_DAMAGE = b.comment("Base attack damage for bites and stings.").defineInRange("attackDamage", 7.0D, 0.0D, 1024.0D); MANTICORE_ATTACK_DAMAGE = b.comment("Base attack damage for bites and stings.").defineInRange("attackDamage", 7.0D, 0.0D, 1024.0D);
MANTICORE_STING_POISON_TICKS = b.comment("Poison duration in ticks applied by a Manticore sting.").defineInRange("stingPoisonTicks", 100, 0, 12000); MANTICORE_STING_POISON_TICKS = b.comment("Poison duration in ticks applied by a Manticore sting.").defineInRange("stingPoisonTicks", 100, 0, 12000);
QUEEN_MANTICORE_CAP = b.comment("Maximum number of living Manticores a single Queen may keep summoned.").defineInRange("queenSummonCap", 15, 1, 200); QUEEN_MANTICORE_CAP = b.comment("Maximum number of living Manticores a single Queen may keep summoned.").defineInRange("queenSummonCap", 15, 1, 200);
QUEEN_MANTICORE_SUMMON_COOLDOWN_TICKS = b.comment("Ticks between Queen Manticore summon attempts.").defineInRange("queenSummonCooldownTicks", 600, 20, 200000);
QUEEN_MANTICORE_SUMMON_COUNT = b.comment("Maximum Manticores created by one Queen summon attempt.").defineInRange("queenSummonCount", 3, 1, 32);
QUEEN_MANTICORE_SUMMON_RANGE = b.comment("Maximum horizontal distance from the Queen used for Manticore spawn positions.").defineInRange("queenSummonRange", 24.0D, 4.0D, 128.0D);
b.pop(); b.pop();
b.push("jerry"); b.push("jerry");
@@ -928,6 +952,20 @@ public final class AntarchyMobsConfig {
static double royalBossBiteReach() { return ROYAL_BOSS_BITE_REACH.get(); } static double royalBossBiteReach() { return ROYAL_BOSS_BITE_REACH.get(); }
static double royalBossBiteDamageMultiplier() { return ROYAL_BOSS_BITE_DAMAGE_MULTIPLIER.get(); } static double royalBossBiteDamageMultiplier() { return ROYAL_BOSS_BITE_DAMAGE_MULTIPLIER.get(); }
static int royalBossBiteCooldownTicks() { return ROYAL_BOSS_BITE_COOLDOWN_TICKS.get(); } static int royalBossBiteCooldownTicks() { return ROYAL_BOSS_BITE_COOLDOWN_TICKS.get(); }
static double queenBeamDamage() { return QUEEN_BEAM_DAMAGE.get(); }
static double queenBeamRange() { return QUEEN_BEAM_RANGE.get(); }
static int queenBeamDurationTicks() { return QUEEN_BEAM_DURATION_TICKS.get(); }
static int queenBeamCooldownTicks() { return QUEEN_BEAM_COOLDOWN_TICKS.get(); }
static double queenBeamTracking() { return QUEEN_BEAM_TRACKING.get(); }
static double queenBeamTerrainRadius() { return QUEEN_BEAM_TERRAIN_RADIUS.get(); }
static int queenBeamTerrainCap() { return QUEEN_BEAM_TERRAIN_CAP.get(); }
static double kingBeamDamage() { return KING_BEAM_DAMAGE.get(); }
static double kingBeamRange() { return KING_BEAM_RANGE.get(); }
static int kingBeamDurationTicks() { return KING_BEAM_DURATION_TICKS.get(); }
static int kingBeamCooldownTicks() { return KING_BEAM_COOLDOWN_TICKS.get(); }
static double kingBeamTracking() { return KING_BEAM_TRACKING.get(); }
static double kingBeamTerrainRadius() { return KING_BEAM_TERRAIN_RADIUS.get(); }
static int kingBeamTerrainCap() { return KING_BEAM_TERRAIN_CAP.get(); }
static double brutalflyHealth() { return BRUTALFLY_HEALTH.get(); } static double brutalflyHealth() { return BRUTALFLY_HEALTH.get(); }
static double brutalflySwipeDamage() { return BRUTALFLY_SWIPE_DAMAGE.get(); } static double brutalflySwipeDamage() { return BRUTALFLY_SWIPE_DAMAGE.get(); }
@@ -1064,6 +1102,9 @@ public final class AntarchyMobsConfig {
static double manticoreAttackDamage() { return MANTICORE_ATTACK_DAMAGE.get(); } static double manticoreAttackDamage() { return MANTICORE_ATTACK_DAMAGE.get(); }
static int manticoreStingPoisonTicks() { return MANTICORE_STING_POISON_TICKS.get(); } static int manticoreStingPoisonTicks() { return MANTICORE_STING_POISON_TICKS.get(); }
static int queenManticoreCap() { return QUEEN_MANTICORE_CAP.get(); } static int queenManticoreCap() { return QUEEN_MANTICORE_CAP.get(); }
static int queenManticoreSummonCooldownTicks() { return QUEEN_MANTICORE_SUMMON_COOLDOWN_TICKS.get(); }
static int queenManticoreSummonCount() { return QUEEN_MANTICORE_SUMMON_COUNT.get(); }
static double queenManticoreSummonRange() { return QUEEN_MANTICORE_SUMMON_RANGE.get(); }
static double jerryInfantHealth() { return JERRY_INFANT_HEALTH.get(); } static double jerryInfantHealth() { return JERRY_INFANT_HEALTH.get(); }
static double jerryInfantAttackDamage() { return JERRY_INFANT_ATTACK_DAMAGE.get(); } static double jerryInfantAttackDamage() { return JERRY_INFANT_ATTACK_DAMAGE.get(); }
static double jerryMatureHealth() { return JERRY_MATURE_HEALTH.get(); } static double jerryMatureHealth() { return JERRY_MATURE_HEALTH.get(); }
@@ -208,7 +208,15 @@ public class AntarchyNeoforge {
AntarchyNeoforgeSounds.QUEEN_IDLE, AntarchyNeoforgeSounds.QUEEN_IDLE,
AntarchyNeoforgeSounds.QUEEN_HURT, AntarchyNeoforgeSounds.QUEEN_HURT,
AntarchyNeoforgeSounds.QUEEN_DEATH, AntarchyNeoforgeSounds.QUEEN_DEATH,
AntarchyNeoforgeSounds.QUEEN_BITE AntarchyNeoforgeSounds.QUEEN_BITE,
AntarchyNeoforgeSounds.QUEEN_ROAR,
AntarchyNeoforgeSounds.KING_BEAM_SHOOT,
AntarchyNeoforgeSounds.KING_FIREBALL_SHOOT,
AntarchyNeoforgeSounds.KING_DECREE_CAST,
AntarchyNeoforgeSounds.QUEEN_BEAM_SHOOT,
AntarchyNeoforgeSounds.QUEEN_BEAM_START,
AntarchyNeoforgeSounds.QUEEN_BEAM_LOOP,
AntarchyNeoforgeSounds.QUEEN_BEAM_END
); );
bindCommonObjects(); bindCommonObjects();
ScorpionWhipTetherSync.setSink((player, targetId) -> PacketDistributor.sendToPlayersTrackingEntityAndSelf( ScorpionWhipTetherSync.setSink((player, targetId) -> PacketDistributor.sendToPlayersTrackingEntityAndSelf(
@@ -1158,7 +1158,7 @@ public final class AntarchyNeoforgeItems {
public static final DeferredItem<DeferredSpawnEggItem> LURKING_TERROR_SPAWN_EGG = ITEMS.register("lurking_terror_spawn_egg", public static final DeferredItem<DeferredSpawnEggItem> LURKING_TERROR_SPAWN_EGG = ITEMS.register("lurking_terror_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.LURKING_TERROR, 0x2D5A1B, 0x8B0000, new Item.Properties())); () -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.LURKING_TERROR, 0x2D5A1B, 0x8B0000, new Item.Properties()));
public static final DeferredItem<DeferredSpawnEggItem> MANTICORE_SPAWN_EGG = ITEMS.register("manticore_spawn_egg", public static final DeferredItem<DeferredSpawnEggItem> MANTICORE_SPAWN_EGG = ITEMS.register("manticore_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.MANTICORE, 0x8A3B1E, 0x2B1B12, new Item.Properties())); () -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.MANTICORE, 0xA3AEE9, 0x956570, new Item.Properties()));
public static final DeferredItem<DeferredSpawnEggItem> HERCULES_BEETLE_SPAWN_EGG = ITEMS.register("hercules_beetle_spawn_egg", public static final DeferredItem<DeferredSpawnEggItem> HERCULES_BEETLE_SPAWN_EGG = ITEMS.register("hercules_beetle_spawn_egg",
() -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.HERCULES_BEETLE, 0x6B1F2A, 0xD4AF37, new Item.Properties().rarity(Rarity.RARE))); () -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.HERCULES_BEETLE, 0x6B1F2A, 0xD4AF37, new Item.Properties().rarity(Rarity.RARE)));
public static final DeferredItem<DeferredSpawnEggItem> JERRY_SPAWN_EGG = ITEMS.register("jerry_spawn_egg", public static final DeferredItem<DeferredSpawnEggItem> JERRY_SPAWN_EGG = ITEMS.register("jerry_spawn_egg",