From 065a04fc93e947fe2c934b4fce90097ed3e7cb67 Mon Sep 17 00:00:00 2001 From: craisinlord Date: Sat, 29 Aug 2026 23:15:51 -0500 Subject: [PATCH] first pass royal decrees, time dilation transitions, kings tree fixes, manticore changes --- .../antarchy/config/AntarchySettings.java | 51 +++++ .../antarchy/content/AntarchySoundEvents.java | 26 ++- .../client/renderer/RoyalBossRenderer.java | 42 ++++ .../entity/portal/DimensionalTearEntity.java | 71 ++++++ .../content/entity/royal/KingEntity.java | 112 ++++++++++ .../content/entity/royal/QueenEntity.java | 206 ++++++++++++++++++ .../content/entity/royal/RoyalBossEntity.java | 92 +++++++- .../royal/RoyalBossMultipartLayout.java | 6 +- .../content/entity/royal/RoyalHead.java | 4 + .../royal/beam/RoyalBeamController.java | 12 +- .../entity/royal/beam/RoyalBeamSettings.java | 6 + .../entity/royal/decree/AdvanceDecree.java | 9 + .../royal/decree/CloseQuartersDecree.java | 8 + .../royal/decree/KeepYourDistanceDecree.java | 9 + .../entity/royal/decree/NoRetreatDecree.java | 8 + .../entity/royal/decree/RoyalDecree.java | 10 + .../content/time/TimeDilationFieldEntity.java | 4 + .../time/TimeDilationFieldSampler.java | 2 +- .../content/time/TimeDilationMath.java | 22 ++ .../worldgen/elythia/ElythiaBiomeSource.java | 46 +++- .../template_pool/kings_tree/kings_tree1.json | 9 +- .../template_pool/kings_tree/kings_tree3.json | 9 +- .../template_pool/kings_tree/kings_tree4.json | 9 +- .../kings_tree/kings_tree_bottom.json | 2 +- .../fabric/AntarchyFabricContent.java | 10 +- .../fabric/registry/AntarchyFabricItems.java | 2 +- .../AntarchyConfigModuleNeoforge.java | 17 ++ .../antarchy/neoforge/AntarchyMobsConfig.java | 41 ++++ .../antarchy/neoforge/AntarchyNeoforge.java | 10 +- .../registry/AntarchyNeoforgeItems.java | 2 +- 30 files changed, 833 insertions(+), 24 deletions(-) create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/AdvanceDecree.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/CloseQuartersDecree.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/KeepYourDistanceDecree.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/NoRetreatDecree.java create mode 100644 common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/RoyalDecree.java diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java index c9947dec..de54bc70 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/config/AntarchySettings.java @@ -513,6 +513,23 @@ public final class AntarchySettings { private static double manticoreAttackDamage = 7.0D; private static int manticoreStingPoisonTicks = 100; 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 jerryInfantAttackDamage = 2.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 int queenManticoreCap() { return queenManticoreCap; } 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 void setJerryInfantHealth(double v) { jerryInfantHealth = v; } public static double jerryInfantAttackDamage() { return jerryInfantAttackDamage; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/AntarchySoundEvents.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/AntarchySoundEvents.java index 4b12b5d7..8a2764e6 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/AntarchySoundEvents.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/AntarchySoundEvents.java @@ -186,6 +186,14 @@ public final class AntarchySoundEvents { public static Supplier QUEEN_HURT = (Supplier) UNBOUND; public static Supplier QUEEN_DEATH = (Supplier) UNBOUND; public static Supplier QUEEN_BITE = (Supplier) UNBOUND; + public static Supplier QUEEN_ROAR = (Supplier) UNBOUND; + public static Supplier KING_BEAM_SHOOT = (Supplier) UNBOUND; + public static Supplier KING_FIREBALL_SHOOT = (Supplier) UNBOUND; + public static Supplier KING_DECREE_CAST = (Supplier) UNBOUND; + public static Supplier QUEEN_BEAM_SHOOT = (Supplier) UNBOUND; + public static Supplier QUEEN_BEAM_START = (Supplier) UNBOUND; + public static Supplier QUEEN_BEAM_LOOP = (Supplier) UNBOUND; + public static Supplier QUEEN_BEAM_END = (Supplier) UNBOUND; private AntarchySoundEvents() { } @@ -367,7 +375,15 @@ public final class AntarchySoundEvents { Supplier queenIdle, Supplier queenHurt, Supplier queenDeath, - Supplier queenBite + Supplier queenBite, + Supplier queenRoar, + Supplier kingBeamShoot, + Supplier kingFireballShoot, + Supplier kingDecreeCast, + Supplier queenBeamShoot, + Supplier queenBeamStart, + Supplier queenBeamLoop, + Supplier queenBeamEnd ) { SQUIDZOOKA_FIRE = squidzookaFire; SHRINK_RAY_CHARGE = shrinkRayCharge; @@ -546,5 +562,13 @@ public final class AntarchySoundEvents { QUEEN_HURT = queenHurt; QUEEN_DEATH = queenDeath; 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; } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java index 4125a103..56e60ed7 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/client/renderer/RoyalBossRenderer.java @@ -8,6 +8,7 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRendererProvider; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import software.bernie.geckolib.cache.object.BakedGeoModel; import software.bernie.geckolib.renderer.GeoEntityRenderer; @@ -30,4 +31,45 @@ public class RoyalBossRenderer extends GeoEntityRenderer { poseStack.scale(RoyalBossEntity.MODEL_RENDER_SCALE, RoyalBossEntity.MODEL_RENDER_SCALE, 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); + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java index 25020b5e..41234884 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/portal/DimensionalTearEntity.java @@ -3,6 +3,8 @@ package com.craisinlord.antarchy.content.entity.portal; import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.content.AntarchyObjects; 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.List; import java.util.Map; @@ -74,6 +76,10 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { private int eventTicks; private int nextEventTicks; private TearState pendingEvent = TearState.NORMAL; + @Nullable + private UUID queenOwnerId; + private int queenManticoreCount; + private boolean queenManticoreSpawned; public DimensionalTearEntity(EntityType entityType, Level level) { super(entityType, level); @@ -90,6 +96,14 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { 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) { this.linkedTearId = other.getUUID(); this.linkedFallbackPos = other.position(); @@ -121,6 +135,10 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { return; } + if (this.queenOwnerId != null && this.ageTicks == OPENING_ANIMATION_TICKS) { + this.spawnQueenManticores((ServerLevel) this.level()); + } + DimensionalTearEntity linked = this.findLinkedTear(); if (linked == null || !linked.isAlive()) { 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); } + 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 private Mob createTaggedMob(ServerLevel level, TagKey> 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("LinkedY", this.linkedFallbackPos.y); 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 @@ -346,6 +412,11 @@ public class DimensionalTearEntity extends Entity implements GeoEntity { this.linkedTearId = tag.getUUID("LinkedTearId"); } 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 diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java index 9e801da6..578ea957 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/KingEntity.java @@ -7,8 +7,30 @@ import net.minecraft.world.BossEvent; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; 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 { + @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 DECREES = List.of(new CloseQuartersDecree(), new KeepYourDistanceDecree(), new NoRetreatDecree(), new AdvanceDecree()); public KingEntity(EntityType entityType, Level level) { super(entityType, level); } @@ -51,4 +73,94 @@ public class KingEntity extends RoyalBossEntity { protected SoundEvent royalBiteSound() { 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); + } + } + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java index 562fb454..1a682234 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/QueenEntity.java @@ -2,13 +2,36 @@ package com.craisinlord.antarchy.content.entity.royal; import com.craisinlord.antarchy.config.AntarchySettings; 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.util.Mth; +import net.minecraft.world.entity.Entity; import net.minecraft.world.BossEvent; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.MobSpawnType; 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 { + 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 entityType, Level level) { super(entityType, level); } @@ -51,4 +74,187 @@ public class QueenEntity extends RoyalBossEntity { protected SoundEvent royalBiteSound() { 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")); + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java index ac650648..a47a4fe1 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossEntity.java @@ -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.MultipartPartDefinition; 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 net.minecraft.network.chat.Component; 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 static final float MODEL_RENDER_SCALE = 2.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 { 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.RIGHT) }; + private int beamCooldownTicks; + @Nullable + private RoyalHead activeBeamHead; + private int beamLoopSoundTicks; @Nullable private Entity[] multipartParts; @@ -136,6 +142,22 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult 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) { return Mob.createMobAttributes() .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.assignHeadTargets(primaryTarget); + this.tickRoyalBeam(primaryTarget); this.steerTowardTarget(primaryTarget); 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() { float fraction = this.getMaxHealth() <= 0.0F ? 1.0F : this.getHealth() / this.getMaxHealth(); if (fraction > PHASE_TWO_THRESHOLD) { @@ -512,6 +599,9 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult } public Vec3 getRoyalBeamShootFrom(float partialTicks) { + if (this.activeBeamHead != null) { + return this.headAnchor(this.activeBeamHead); + } double x = Mth.lerp(partialTicks, this.xo, this.getX()); double y = Mth.lerp(partialTicks, this.yo, this.getY()) + this.getBbHeight() * 0.72D; double z = Mth.lerp(partialTicks, this.zo, this.getZ()); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossMultipartLayout.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossMultipartLayout.java index 35e78069..37b380e4 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossMultipartLayout.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalBossMultipartLayout.java @@ -9,11 +9,11 @@ public final class RoyalBossMultipartLayout implements MultipartLayout { public static final MultipartPartDefinition BODY = new MultipartPartDefinition( "body", 20.0F, 24.0F, 1.00F, 0.0D, 3.0D, 0.0D, true); 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( - "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( - "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( "left_wing", 14.0F, 16.0F, 0.85F, -2.0D, 14.0D, -13.0D, true); public static final MultipartPartDefinition RIGHT_WING = new MultipartPartDefinition( diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalHead.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalHead.java index 269db19d..9c403741 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalHead.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/RoyalHead.java @@ -94,6 +94,10 @@ public final class RoyalHead { return this.beamActive; } + public boolean shooting() { + return this.shootTicks > 0; + } + public boolean tickBiteHit() { if (this.biteTicks <= 0) { return false; diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java index 0c045d26..54f4a040 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamController.java @@ -1,6 +1,8 @@ package com.craisinlord.antarchy.content.entity.royal.beam; import java.util.List; +import java.util.HashSet; +import java.util.Set; import java.util.function.Consumer; import net.minecraft.core.BlockPos; import net.minecraft.util.Mth; @@ -117,15 +119,16 @@ public final class RoyalBeamController { Vec3 direction = beamEnd.subtract(shootFrom).normalize(); double distance = shootFrom.distanceTo(beamEnd); DamageSource damageSource = this.owner.damageSources().mobAttack(this.owner); + Set damagedThisTick = new HashSet<>(); for (double walked = settings.pathStep(); walked < Math.min(distance, settings.range()); walked += settings.pathStep()) { 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)) { 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))) { mutateTerrainAround(beamEnd, settings.impactTerrainRadius(), settings, terrainMode); } @@ -145,7 +148,8 @@ public final class RoyalBeamController { float damageAmount, float knockbackAmount, DamageSource damageSource, - boolean requireLineOfSight + boolean requireLineOfSight, + Set damagedThisTick ) { if (radius <= 0.0F || damageAmount <= 0.0F) { return false; @@ -163,10 +167,12 @@ public final class RoyalBeamController { || this.owner.isAlliedTo(living) || living.getType() == this.owner.getType() || living.distanceToSqr(center) > radius * radius + || damagedThisTick.contains(living.getId()) || requireLineOfSight && !canEntityBeHurtFrom(center, living)) { continue; } if (living.hurt(damageSource, damageAmount)) { + damagedThisTick.add(living.getId()); hurtAny = true; knockbackTarget(living, knockbackAmount); } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamSettings.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamSettings.java index ba437f57..082338ee 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamSettings.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/beam/RoyalBeamSettings.java @@ -4,6 +4,8 @@ public record RoyalBeamSettings( double range, double targetTracking, double pathStep, + int durationTicks, + int cooldownTicks, float pathDamageRadius, float impactDamageRadius, float damage, @@ -24,6 +26,8 @@ public record RoyalBeamSettings( 100.0D, 0.1D, 7.5D, + 30, + 90, 6.0F, 6.0F, damage, @@ -45,6 +49,8 @@ public record RoyalBeamSettings( range = Math.max(1.0D, range); targetTracking = Math.clamp(targetTracking, 0.0D, 1.0D); pathStep = Math.max(1.0D, pathStep); + durationTicks = Math.max(1, durationTicks); + cooldownTicks = Math.max(1, cooldownTicks); pathDamageRadius = Math.max(0.0F, pathDamageRadius); impactDamageRadius = Math.max(0.0F, impactDamageRadius); damage = Math.max(0.0F, damage); diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/AdvanceDecree.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/AdvanceDecree.java new file mode 100644 index 00000000..480f0029 --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/AdvanceDecree.java @@ -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; } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/CloseQuartersDecree.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/CloseQuartersDecree.java new file mode 100644 index 00000000..e0eeb77d --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/CloseQuartersDecree.java @@ -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); } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/KeepYourDistanceDecree.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/KeepYourDistanceDecree.java new file mode 100644 index 00000000..35da79bd --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/KeepYourDistanceDecree.java @@ -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; } } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/NoRetreatDecree.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/NoRetreatDecree.java new file mode 100644 index 00000000..0a0b8ebf --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/NoRetreatDecree.java @@ -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); } +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/RoyalDecree.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/RoyalDecree.java new file mode 100644 index 00000000..ba93acdb --- /dev/null +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/entity/royal/decree/RoyalDecree.java @@ -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); +} diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java index b8814456..12f51078 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldEntity.java @@ -78,6 +78,10 @@ public class TimeDilationFieldEntity extends Entity { return TimeDilationMath.clampRate(this.entityData.get(RATE)); } + public double effectiveFieldRate() { + return TimeDilationMath.effectiveFieldRate(this.fieldRate(), this.age, this.durationTicks); + } + public int fieldDurationTicks() { return this.durationTicks; } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldSampler.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldSampler.java index abd67e99..04b62d39 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldSampler.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationFieldSampler.java @@ -23,7 +23,7 @@ public final class TimeDilationFieldSampler { continue; } 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); } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationMath.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationMath.java index 6a5cf1cf..d8b83a82 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationMath.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/time/TimeDilationMath.java @@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.time; public final class TimeDilationMath { public static final double MIN_RATE = 0.05D; 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 TimeDilationMath() { @@ -31,4 +32,25 @@ public final class TimeDilationMath { } 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; + } } diff --git a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java index 3f385678..2867f200 100644 --- a/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java +++ b/common-1.21.1/src/main/java/com/craisinlord/antarchy/content/worldgen/elythia/ElythiaBiomeSource.java @@ -103,6 +103,7 @@ public class ElythiaBiomeSource extends BiomeSource { private final Holder glimmeringPoolsHolder; private final Holder ouranwoodForestHolder; private final Holder cloudSeaHolder; + private final Holder firstConfiguredHolder; public ElythiaBiomeSource(Climate.ParameterList> parameters, int molewormCavesMaxY, int surfaceBiomeSampleY, int oceanMaxY, int seaLevel, int cloudSeaMinY) { this.parameters = parameters; @@ -145,6 +146,10 @@ public class ElythiaBiomeSource extends BiomeSource { .filter(h -> h.is(CLOUD_SEA)) .findFirst() .orElse(null); + this.firstConfiguredHolder = parameters.values().stream() + .map(Pair::getSecond) + .findFirst() + .orElse(null); } private Climate.ParameterList> parameters() { return this.parameters; } @@ -178,6 +183,9 @@ public class ElythiaBiomeSource extends BiomeSource { } Holder 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" // 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; Holder seaLevelBiome = this.delegate.getNoiseBiome(x, this.seaLevelQuartY, z, sampler); 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)) { return oceanHolder; @@ -221,17 +229,17 @@ public class ElythiaBiomeSource extends BiomeSource { } private static boolean allowedBelowSeaLevel(Holder biome) { - return biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES) - || biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES); + return biome != null && (biome.is(MOLEWORM_CAVES) || biome.is(ELYTHIA_LUSH_CAVES) + || biome.is(ELYTHIA_OCEAN) || biome.is(ELYTHIA_CORAL_SPIKES)); } private static boolean isOceanBiome(Holder 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) { - return biome.is(OURANWOOD_FOREST) || biome.is(SPARSE_OURANWOOD_FOREST) - || biome.is(FUNGAL_OURANWOOD_FOREST); + return biome != null && (biome.is(OURANWOOD_FOREST) || biome.is(SPARSE_OURANWOOD_FOREST) + || biome.is(FUNGAL_OURANWOOD_FOREST)); } private static boolean isGlimmeringPoolsCandidate(Holder 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.value = result; @@ -336,6 +345,7 @@ public class ElythiaBiomeSource extends BiomeSource { } result = resolved != null ? resolved : (defaultLandHolder != null ? defaultLandHolder : result); } + result = nullToConfiguredFallback(result, x, this.surfaceBiomeSampleQuartY, z, sampler); cache.key = key; cache.value = result; @@ -344,6 +354,9 @@ public class ElythiaBiomeSource extends BiomeSource { @SafeVarargs private static boolean isExcluded(Holder biome, ResourceKey... excluded) { + if (biome == null) { + return true; + } for (ResourceKey key : excluded) { if (biome.is(key)) return true; } @@ -351,11 +364,30 @@ public class ElythiaBiomeSource extends BiomeSource { } private static boolean isOceanOrCave(Holder 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(GLIMMERING_POOLS) || biome.is(CLOUD_SEA); } + private Holder nullToConfiguredFallback(Holder biome, int x, int y, int z, Climate.Sampler sampler) { + return biome != null ? biome : resolveConfiguredFallback(x, y, z, sampler); + } + + private Holder 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 public void addDebugInfo(java.util.List debug, net.minecraft.core.BlockPos pos, Climate.Sampler sampler) { try { diff --git a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree1.json b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree1.json index d5abbdbc..dd1f23f7 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree1.json +++ b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree1.json @@ -8,7 +8,14 @@ "location": "antarchy:kings_tree/kings_tree2", "processors": "antarchy:generic_processor", "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" } } ] diff --git a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree3.json b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree3.json index 20fddb55..5dc88b5b 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree3.json +++ b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree3.json @@ -8,7 +8,14 @@ "location": "antarchy:kings_tree/kings_tree3", "processors": "antarchy:generic_processor", "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" } } ] diff --git a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree4.json b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree4.json index 5a6610c9..39a3812c 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree4.json +++ b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree4.json @@ -8,7 +8,14 @@ "location": "antarchy:kings_tree/kings_tree4", "processors": "antarchy:generic_processor", "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" } } ] diff --git a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree_bottom.json b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree_bottom.json index b23895b7..15b2406e 100644 --- a/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree_bottom.json +++ b/common-1.21.1/src/main/resources/data/antarchy/worldgen/template_pool/kings_tree/kings_tree_bottom.json @@ -11,7 +11,7 @@ "enhanced_terrain_adaptation": { "type": "integrated_api:custom", "carves": true, - "beards": false, + "beards": true, "kernel_size": 35, "kernel_distance": 35 }, diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java index 37d28a6c..56738aac 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/AntarchyFabricContent.java @@ -313,7 +313,15 @@ public final class AntarchyFabricContent { AntarchyFabricSounds.QUEEN_IDLE, AntarchyFabricSounds.QUEEN_HURT, 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); diff --git a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java index 2f89fee0..54ceff6c 100644 --- a/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java +++ b/fabric-1.21.1/src/main/java/com/craisinlord/antarchy/fabric/registry/AntarchyFabricItems.java @@ -1807,7 +1807,7 @@ public final class AntarchyFabricItems { () -> new DeferredSpawnEggItem(AntarchyFabricEntities.LURKING_TERROR, 0x2D5A1B, 0x8B0000, new Item.Properties())); public static final DeferredItem 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 HERCULES_BEETLE_SPAWN_EGG = ITEMS.register("hercules_beetle_spawn_egg", diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java index c896593b..4faeb123 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyConfigModuleNeoforge.java @@ -149,6 +149,20 @@ public final class AntarchyConfigModuleNeoforge { AntarchySettings.setRoyalBossBiteReach(AntarchyMobsConfig.royalBossBiteReach()); AntarchySettings.setRoyalBossBiteDamageMultiplier(AntarchyMobsConfig.royalBossBiteDamageMultiplier()); 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.setBrutalflySwipeDamage(AntarchyMobsConfig.brutalflySwipeDamage()); @@ -286,6 +300,9 @@ public final class AntarchyConfigModuleNeoforge { AntarchySettings.setManticoreAttackDamage(AntarchyMobsConfig.manticoreAttackDamage()); AntarchySettings.setManticoreStingPoisonTicks(AntarchyMobsConfig.manticoreStingPoisonTicks()); AntarchySettings.setQueenManticoreCap(AntarchyMobsConfig.queenManticoreCap()); + AntarchySettings.setQueenManticoreSummonCooldownTicks(AntarchyMobsConfig.queenManticoreSummonCooldownTicks()); + AntarchySettings.setQueenManticoreSummonCount(AntarchyMobsConfig.queenManticoreSummonCount()); + AntarchySettings.setQueenManticoreSummonRange(AntarchyMobsConfig.queenManticoreSummonRange()); AntarchySettings.setJerryInfantHealth(AntarchyMobsConfig.jerryInfantHealth()); AntarchySettings.setJerryInfantAttackDamage(AntarchyMobsConfig.jerryInfantAttackDamage()); AntarchySettings.setJerryMatureHealth(AntarchyMobsConfig.jerryMatureHealth()); diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java index 86d9465c..0c368b83 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyMobsConfig.java @@ -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_DAMAGE_MULTIPLIER; 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 @@ -273,6 +277,9 @@ public final class AntarchyMobsConfig { private static final ModConfigSpec.DoubleValue MANTICORE_ATTACK_DAMAGE; private static final ModConfigSpec.IntValue MANTICORE_STING_POISON_TICKS; 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 @@ -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_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); + 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(); @@ -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_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_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.push("jerry"); @@ -928,6 +952,20 @@ public final class AntarchyMobsConfig { static double royalBossBiteReach() { return ROYAL_BOSS_BITE_REACH.get(); } static double royalBossBiteDamageMultiplier() { return ROYAL_BOSS_BITE_DAMAGE_MULTIPLIER.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 brutalflySwipeDamage() { return BRUTALFLY_SWIPE_DAMAGE.get(); } @@ -1064,6 +1102,9 @@ public final class AntarchyMobsConfig { static double manticoreAttackDamage() { return MANTICORE_ATTACK_DAMAGE.get(); } static int manticoreStingPoisonTicks() { return MANTICORE_STING_POISON_TICKS.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 jerryInfantAttackDamage() { return JERRY_INFANT_ATTACK_DAMAGE.get(); } static double jerryMatureHealth() { return JERRY_MATURE_HEALTH.get(); } diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java index 15109c62..cd0e3aa9 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/AntarchyNeoforge.java @@ -208,7 +208,15 @@ public class AntarchyNeoforge { AntarchyNeoforgeSounds.QUEEN_IDLE, AntarchyNeoforgeSounds.QUEEN_HURT, 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(); ScorpionWhipTetherSync.setSink((player, targetId) -> PacketDistributor.sendToPlayersTrackingEntityAndSelf( diff --git a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java index 6d3df24c..70a3b5ec 100644 --- a/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java +++ b/neoforge-1.21.1/src/main/java/com/craisinlord/antarchy/neoforge/registry/AntarchyNeoforgeItems.java @@ -1158,7 +1158,7 @@ public final class AntarchyNeoforgeItems { public static final DeferredItem LURKING_TERROR_SPAWN_EGG = ITEMS.register("lurking_terror_spawn_egg", () -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.LURKING_TERROR, 0x2D5A1B, 0x8B0000, new Item.Properties())); public static final DeferredItem 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 HERCULES_BEETLE_SPAWN_EGG = ITEMS.register("hercules_beetle_spawn_egg", () -> new DeferredSpawnEggItem(AntarchyNeoforgeEntites.HERCULES_BEETLE, 0x6B1F2A, 0xD4AF37, new Item.Properties().rarity(Rarity.RARE))); public static final DeferredItem JERRY_SPAWN_EGG = ITEMS.register("jerry_spawn_egg",