undertrial sounds

inverted squidzooka, rpo
king and queen tweaks
fix attidue adjustor bug
This commit is contained in:
craisinlord committed 2026-09-15 23:20:54 -05:00
1 parent fc5028a15b
commit aefbfb9f32
25 files changed
+674 -66

No files matched your search

@@ -0,0 +1,14 @@
{
"structures": [
{
"structure": "antarchy:tigers_eye_shrine",
"weight": 1
}
],
"placement": {
"salt": 149275031,
"spacing": 24,
"separation": 16,
"type": "integrated_api:advanced_random_spread"
}
}
@@ -0,0 +1,18 @@
{
"structures": [
{
"structure": "antarchy:underside_ruins",
"weight": 2
},
{
"structure": "antarchy:underside_castle",
"weight": 1
}
],
"placement": {
"salt": 184736291,
"spacing": 24,
"separation": 12,
"type": "integrated_api:advanced_random_spread"
}
}
@@ -578,7 +578,7 @@ public final class AntarchySettings {
private static double kingBeamTracking = 0.1D; private static double kingBeamTracking = 0.1D;
private static double kingBeamTerrainRadius = 5.0D; private static double kingBeamTerrainRadius = 5.0D;
private static int kingBeamTerrainCap = 192; private static int kingBeamTerrainCap = 192;
private static int royalDecreeCooldownTicks = 1200; private static int royalDecreeCooldownTicks = 700;
private static int kingRoyalMusterCooldownTicks = 500; private static int kingRoyalMusterCooldownTicks = 500;
private static int kingRoyalMusterWindupTicks = 30; private static int kingRoyalMusterWindupTicks = 30;
private static int kingRoyalMusterDurationTicks = 600; private static int kingRoyalMusterDurationTicks = 600;
@@ -68,12 +68,32 @@ public final class QueenTrailSpawnMarkerBlockEntity extends BlockEntity {
level.getChunk(chunkX, chunkZ); level.getChunk(chunkX, chunkZ);
} }
} }
QueenEntity queen = QueenEntity.spawnFromUndersideTrail(level, marker.spawnPos, marker.homePos, marker.siteId, marker.yaw); marker.spawnNow(level);
if (queen != null) { }
marker.consumed = true;
marker.queenUuid = queen.getUUID(); @Nullable
marker.setChanged(); public QueenEntity spawnNow(ServerLevel level) {
if (!this.configured) {
return null;
} }
if (this.consumed) {
if (this.queenUuid != null && level.getEntity(this.queenUuid) instanceof QueenEntity queen) {
return queen;
}
return null;
}
for (int chunkX = (this.spawnPos.getX() - 16) >> 4; chunkX <= (this.spawnPos.getX() + 16) >> 4; chunkX++) {
for (int chunkZ = (this.spawnPos.getZ() - 16) >> 4; chunkZ <= (this.spawnPos.getZ() + 16) >> 4; chunkZ++) {
level.getChunk(chunkX, chunkZ);
}
}
QueenEntity queen = QueenEntity.spawnFromUndersideTrail(level, this.spawnPos, this.homePos, this.siteId, this.yaw);
if (queen != null) {
this.consumed = true;
this.queenUuid = queen.getUUID();
this.setChanged();
}
return queen;
} }
@Override @Override
@@ -92,6 +92,10 @@ public final class UndertrialSpawnerBlockEntity extends BlockEntity implements T
pos.getZ() + 0.5D + (level.random.nextDouble() - 0.5D) * 0.7D, 0.0D, 0.01D, 0.0D); pos.getZ() + 0.5D + (level.random.nextDouble() - 0.5D) * 0.7D, 0.0D, 0.01D, 0.0D);
} }
} else if (currentState == TrialSpawnerState.WAITING_FOR_PLAYERS && blockEntity.previousClientState != currentState) { } else if (currentState == TrialSpawnerState.WAITING_FOR_PLAYERS && blockEntity.previousClientState != currentState) {
ResourceLocation detectionSound = ResourceLocation.fromNamespaceAndPath(Antarchy.MODID,
level.random.nextBoolean() ? "undertrial_detect_player1" : "undertrial_detect_player2");
level.playSound(null, pos, BuiltInRegistries.SOUND_EVENT.get(detectionSound),
net.minecraft.sounds.SoundSource.BLOCKS, 1.0F, 1.0F);
for (int i = 0; i < 12; i++) { for (int i = 0; i < 12; i++) {
level.addParticle(blockEntity.particle("undertrial_spawner_detection"), pos.getX() + 0.5D + (level.random.nextDouble() - 0.5D) * 1.4D, level.addParticle(blockEntity.particle("undertrial_spawner_detection"), pos.getX() + 0.5D + (level.random.nextDouble() - 0.5D) * 1.4D,
pos.getY() + 0.15D + level.random.nextDouble() * 0.7D, pos.getY() + 0.15D + level.random.nextDouble() * 0.7D,
@@ -3,6 +3,7 @@ package com.craisinlord.antarchy.content.command;
import com.craisinlord.antarchy.Antarchy; import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.block.entity.QueenTrailSpawnMarkerBlockEntity; import com.craisinlord.antarchy.content.block.entity.QueenTrailSpawnMarkerBlockEntity;
import com.craisinlord.antarchy.content.worldgen.thoraxis.QueenTrailGrid; import com.craisinlord.antarchy.content.worldgen.thoraxis.QueenTrailGrid;
import com.craisinlord.antarchy.content.entity.royal.QueenEntity;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import java.util.ArrayList; import java.util.ArrayList;
@@ -67,7 +68,11 @@ public final class QueenLocateCommand {
if (marker == null) { if (marker == null) {
continue; continue;
} }
QueenEntity queen = marker.spawnNow(thoraxis);
BlockPos spawn = marker.getSpawnPos(); BlockPos spawn = marker.getSpawnPos();
if (queen != null) {
spawn = BlockPos.containing(queen.position());
}
int distance = Mth.floor(Math.sqrt(distanceSquared(originX, originZ, site))); int distance = Mth.floor(Math.sqrt(distanceSquared(originX, originZ, site)));
String coordinates = "[" + spawn.getX() + ", " + spawn.getY() + ", " + spawn.getZ() + "]"; String coordinates = "[" + spawn.getX() + ", " + spawn.getY() + ", " + spawn.getZ() + "]";
String teleportCommand = "/execute in " + THORAXIS.location() + " run tp @s " String teleportCommand = "/execute in " + THORAXIS.location() + " run tp @s "
@@ -6,6 +6,7 @@ import com.craisinlord.antarchy.content.entity.kraken.KrakenEntity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi; import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection; import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil; import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityTransition;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@@ -412,6 +413,9 @@ public class MissileSquidEntity extends Monster implements GeoEntity {
this.launchOwnerUuid = owner != null ? owner.getUUID() : null; this.launchOwnerUuid = owner != null ? owner.getUUID() : null;
this.setTarget(null); this.setTarget(null);
this.setNoGravity(false); this.setNoGravity(false);
if (owner != null && AntarchyGravityApi.isGravityInverted(owner)) {
AntarchyGravityApi.setAirborneGravityDirection(this, AntarchyGravityApi.getGravityDirection(owner), true, AntarchyGravityTransition.INSTANT);
}
this.setDeltaMovement(velocity); this.setDeltaMovement(velocity);
this.hasImpulse = true; this.hasImpulse = true;
this.updateAnimationState(); this.updateAnimationState();
@@ -357,6 +357,14 @@ public class OctopusBombEntity extends Monster implements GeoEntity {
public void launchAsExplosiveProjectile(net.minecraft.world.entity.Entity launcher, Vec3 velocity) { public void launchAsExplosiveProjectile(net.minecraft.world.entity.Entity launcher, Vec3 velocity) {
this.explosiveImpact = true; this.explosiveImpact = true;
this.explosiveLauncherId = launcher != null ? launcher.getUUID() : null; this.explosiveLauncherId = launcher != null ? launcher.getUUID() : null;
if (launcher != null && com.craisinlord.antarchy.content.gravity.AntarchyGravityApi.isGravityInverted(launcher)) {
com.craisinlord.antarchy.content.gravity.AntarchyGravityApi.setAirborneGravityDirection(
this,
com.craisinlord.antarchy.content.gravity.AntarchyGravityApi.getGravityDirection(launcher),
true,
com.craisinlord.antarchy.content.gravity.AntarchyGravityTransition.INSTANT
);
}
this.setDeltaMovement(velocity); this.setDeltaMovement(velocity);
this.hasImpulse = true; this.hasImpulse = true;
} }
@@ -1,6 +1,7 @@
package com.craisinlord.antarchy.content.entity.ant; package com.craisinlord.antarchy.content.entity.ant;
import com.craisinlord.antarchy.config.AntarchySettings; import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.portal.PermanentPortalType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
@@ -9,8 +10,8 @@ import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.PlayerRespawnLogic; import net.minecraft.server.level.PlayerRespawnLogic;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
@@ -37,6 +38,8 @@ import org.jetbrains.annotations.Nullable;
public final class AntTeleportHelper { public final class AntTeleportHelper {
private static final double COMPANION_FOLLOW_RADIUS = 16.0D; private static final double COMPANION_FOLLOW_RADIUS = 16.0D;
private static final int ARRIVAL_SEARCH_RADIUS = 24;
private static final int ARRIVAL_VERTICAL_SEARCH = 24;
private AntTeleportHelper() { private AntTeleportHelper() {
} }
@@ -256,11 +259,12 @@ public final class AntTeleportHelper {
return safeArrivalPos; return safeArrivalPos;
} }
return createEmergencyArrivalPlatform(destination, preferredPos); return createEmergencyArrivalPlatform(destination, findEmergencyPlatformPosition(destination, preferredPos));
} }
@Nullable @Nullable
private static Vec3 findSafeArrivalPosition(ServerPlayer player, ServerLevel destination, BlockPos preferredPos) { private static Vec3 findSafeArrivalPosition(ServerPlayer player, ServerLevel destination, BlockPos preferredPos) {
loadArrivalSearchArea(destination, preferredPos);
int[] yRange = getDimensionYRange(destination); int[] yRange = getDimensionYRange(destination);
if (yRange != null) { if (yRange != null) {
return findSafeArrivalPositionInYRange(player, destination, preferredPos, yRange[0], yRange[1]); return findSafeArrivalPositionInYRange(player, destination, preferredPos, yRange[0], yRange[1]);
@@ -277,7 +281,7 @@ public final class AntTeleportHelper {
addArrivalCandidate(candidates, PlayerRespawnLogic.getSpawnPosInChunk(destination, new ChunkPos(adjustedPreferredPos))); addArrivalCandidate(candidates, PlayerRespawnLogic.getSpawnPosInChunk(destination, new ChunkPos(adjustedPreferredPos)));
} }
for (int radius = 0; radius <= 4; radius++) { for (int radius = 0; radius <= ARRIVAL_SEARCH_RADIUS; radius++) {
for (int xOffset = -radius; xOffset <= radius; xOffset++) { for (int xOffset = -radius; xOffset <= radius; xOffset++) {
for (int zOffset = -radius; zOffset <= radius; zOffset++) { for (int zOffset = -radius; zOffset <= radius; zOffset++) {
if (radius > 0 && Math.abs(xOffset) != radius && Math.abs(zOffset) != radius) { if (radius > 0 && Math.abs(xOffset) != radius && Math.abs(zOffset) != radius) {
@@ -303,9 +307,27 @@ public final class AntTeleportHelper {
return null; return null;
} }
/**
* Arrival validation needs neighboring chunks for collision checks. Load a
* bounded area up front so unloaded terrain is not mistaken for an unsafe
* destination and sent straight to the emergency-platform path.
*/
private static void loadArrivalSearchArea(ServerLevel destination, BlockPos preferredPos) {
ChunkPos center = new ChunkPos(preferredPos);
int chunkRadius = (ARRIVAL_SEARCH_RADIUS >> 4) + 1;
for (int chunkX = center.x - chunkRadius; chunkX <= center.x + chunkRadius; chunkX++) {
for (int chunkZ = center.z - chunkRadius; chunkZ <= center.z + chunkRadius; chunkZ++) {
destination.getChunk(chunkX, chunkZ);
}
}
}
@Nullable @Nullable
private static int[] getDimensionYRange(ServerLevel destination) { private static int[] getDimensionYRange(ServerLevel destination) {
ResourceKey<Level> dim = destination.dimension(); ResourceKey<Level> dim = destination.dimension();
if (dim == PermanentPortalType.ELYTHIA.primaryDimension()) {
return new int[]{64, 240};
}
if (dim == AntarchySettings.termiteDestinationDimension()) { if (dim == AntarchySettings.termiteDestinationDimension()) {
return new int[]{100, 200}; return new int[]{100, 200};
} }
@@ -320,7 +342,48 @@ public final class AntTeleportHelper {
@Nullable @Nullable
private static Vec3 findSafeArrivalPositionInYRange(ServerPlayer player, ServerLevel destination, BlockPos preferredPos, int minY, int maxY) { private static Vec3 findSafeArrivalPositionInYRange(ServerPlayer player, ServerLevel destination, BlockPos preferredPos, int minY, int maxY) {
for (int radius = 0; radius <= 8; radius++) { Set<BlockPos> surfaceCandidates = new LinkedHashSet<>();
for (int radius = 0; radius <= ARRIVAL_SEARCH_RADIUS; radius++) {
for (int xOff = -radius; xOff <= radius; xOff++) {
for (int zOff = -radius; zOff <= radius; zOff++) {
if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) {
continue;
}
int x = preferredPos.getX() + xOff;
int z = preferredPos.getZ() + zOff;
BlockPos column = new BlockPos(x, preferredPos.getY(), z);
if (!destination.hasChunkAt(column)) {
continue;
}
BlockPos surface = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, column);
addArrivalCandidate(surfaceCandidates, surface);
addArrivalCandidate(surfaceCandidates, destination.getHeightmapPos(Heightmap.Types.WORLD_SURFACE, column));
for (int yOffset = 1; yOffset <= ARRIVAL_VERTICAL_SEARCH; yOffset++) {
surfaceCandidates.add(surface.above(yOffset));
surfaceCandidates.add(surface.below(yOffset));
}
}
}
}
// Prefer actual generated surfaces. This is especially important in
// Elythia, where the configured spawn height is not necessarily the
// playable surface.
for (BlockPos candidate : surfaceCandidates) {
if (candidate.getY() < minY || candidate.getY() > maxY) {
continue;
}
Vec3 safePos = tryFindSafeDismount(player, destination, candidate);
if (safePos != null && safePos.y >= minY && safePos.y <= maxY) {
return safePos;
}
}
// Heightmaps can be stale or unsuitable around structures, so retain a
// bounded exhaustive search as a final generated-terrain attempt.
for (int radius = 0; radius <= ARRIVAL_SEARCH_RADIUS; radius++) {
for (int xOff = -radius; xOff <= radius; xOff++) { for (int xOff = -radius; xOff <= radius; xOff++) {
for (int zOff = -radius; zOff <= radius; zOff++) { for (int zOff = -radius; zOff <= radius; zOff++) {
if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) { if (radius > 0 && Math.abs(xOff) != radius && Math.abs(zOff) != radius) {
@@ -412,6 +475,49 @@ public final class AntTeleportHelper {
return new BlockPos(preferredPos.getX(), Mth.clamp(preferredPos.getY(), minY, maxY), preferredPos.getZ()); return new BlockPos(preferredPos.getX(), Mth.clamp(preferredPos.getY(), minY, maxY), preferredPos.getZ());
} }
/**
* Keep the emergency platform grounded in generated terrain when possible.
* A configured/shared spawn can be an arbitrary coordinate in a custom
* dimension, so using its Y directly can strand the player in the sky.
*/
private static BlockPos findEmergencyPlatformPosition(ServerLevel destination, BlockPos preferredPos) {
BlockPos best = null;
int bestDistance = Integer.MAX_VALUE;
int minY = destination.getMinBuildHeight() + 1;
int maxY = destination.getMaxBuildHeight() - 2;
for (int radius = 0; radius <= 8; radius++) {
for (int xOffset = -radius; xOffset <= radius; xOffset++) {
for (int zOffset = -radius; zOffset <= radius; zOffset++) {
if (radius > 0 && Math.abs(xOffset) != radius && Math.abs(zOffset) != radius) {
continue;
}
BlockPos searchPos = preferredPos.offset(xOffset, 0, zOffset);
if (!destination.hasChunkAt(searchPos)) {
continue;
}
BlockPos surface = destination.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, searchPos);
if (surface.getY() < minY || surface.getY() > maxY) {
continue;
}
int distance = Math.abs(xOffset) + Math.abs(zOffset);
if (distance < bestDistance) {
best = surface;
bestDistance = distance;
}
}
}
if (best != null) {
break;
}
}
return best != null ? best : getClampedFallbackPosition(destination, preferredPos);
}
/** /**
* Last-resort landing location for custom dimensions whose generated spawn * Last-resort landing location for custom dimensions whose generated spawn
* area has no valid player-sized space. The normal search always runs first; * area has no valid player-sized space. The normal search always runs first;
@@ -424,7 +530,7 @@ public final class AntTeleportHelper {
center = new BlockPos(center.getX(), Mth.clamp(center.getY(), minY, maxY), center.getZ()); center = new BlockPos(center.getX(), Mth.clamp(center.getY(), minY, maxY), center.getZ());
destination.getChunkAt(center); destination.getChunkAt(center);
BlockState platformState = Blocks.STONE.defaultBlockState(); BlockState platformState = emergencyPlatformState(destination);
for (int xOffset = -2; xOffset <= 2; xOffset++) { for (int xOffset = -2; xOffset <= 2; xOffset++) {
for (int zOffset = -2; zOffset <= 2; zOffset++) { for (int zOffset = -2; zOffset <= 2; zOffset++) {
@@ -438,4 +544,23 @@ public final class AntTeleportHelper {
return Vec3.atBottomCenterOf(center); return Vec3.atBottomCenterOf(center);
} }
private static BlockState emergencyPlatformState(ServerLevel destination) {
if (destination.dimension() == PermanentPortalType.ELYTHIA.primaryDimension()) {
return PermanentPortalType.ELYTHIA.platformBlock().defaultBlockState();
}
if (destination.dimension() == PermanentPortalType.THORAXIS.primaryDimension()) {
return PermanentPortalType.THORAXIS.platformBlock().defaultBlockState();
}
if (destination.dimension() == PermanentPortalType.CAVARYN.primaryDimension()) {
return PermanentPortalType.CAVARYN.platformBlock().defaultBlockState();
}
if (destination.dimension() == Level.NETHER) {
return Blocks.NETHERRACK.defaultBlockState();
}
if (destination.dimension() == Level.END) {
return Blocks.END_STONE.defaultBlockState();
}
return Blocks.DIRT.defaultBlockState();
}
} }
@@ -34,6 +34,7 @@ import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.projectile.Arrow; import net.minecraft.world.entity.projectile.Arrow;
import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.util.Mth;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.MenuProvider; import net.minecraft.world.MenuProvider;
import net.minecraft.world.item.ArmorItem; import net.minecraft.world.item.ArmorItem;
@@ -93,6 +94,16 @@ public class KingEntity extends RoyalBossEntity {
private static final double COME_NO_CLOSER_RADIUS = 16.0D; private static final double COME_NO_CLOSER_RADIUS = 16.0D;
private static final int COME_NO_CLOSER_PARTICLE_INTERVAL = 4; private static final int COME_NO_CLOSER_PARTICLE_INTERVAL = 4;
private static final int COME_NO_CLOSER_PARTICLE_COUNT = 40; private static final int COME_NO_CLOSER_PARTICLE_COUNT = 40;
private static final double CLOSE_QUARTERS_RADIUS = 16.0D;
private static final int CLOSE_QUARTERS_APPROACH_TICKS = 120;
private static final int CLOSE_QUARTERS_EXIT_GRACE_TICKS = 40;
private static final int PROJECTILE_PRESSURE_MAX = 60;
private static final int PROJECTILE_PRESSURE_PER_HIT = 10;
private static final int GROUND_ASSAULT_TICKS = 200;
private static final int GROUND_ASSAULT_COOLDOWN_MIN = 600;
private static final int GROUND_ASSAULT_COOLDOWN_VARIANCE = 300;
private static final int COMBAT_WAYPOINT_MIN_TICKS = 45;
private static final int COMBAT_WAYPOINT_VARIANCE = 35;
@Nullable @Nullable
private Vec3 patrolCenter; private Vec3 patrolCenter;
@@ -105,6 +116,10 @@ public class KingEntity extends RoyalBossEntity {
private double treePatrolAngle; private double treePatrolAngle;
private boolean treePatrolBound; private boolean treePatrolBound;
private int patrolCooldownTicks; private int patrolCooldownTicks;
@Nullable
private Vec3 treePatrolProgressPosition;
private int treePatrolProgressTicks;
private int treePatrolFailures;
private int decreeCooldownTicks; private int decreeCooldownTicks;
private int activeDecreeTicks; private int activeDecreeTicks;
private int stompCooldownTicks; private int stompCooldownTicks;
@@ -113,6 +128,23 @@ public class KingEntity extends RoyalBossEntity {
private int iceballCooldownTicks = 120; private int iceballCooldownTicks = 120;
private int iceSpikeCooldownTicks = 160; private int iceSpikeCooldownTicks = 160;
private boolean decreeRetreatPressure; private boolean decreeRetreatPressure;
@Nullable
private String lastDecreeKey;
private boolean closeQuartersEntered;
private int closeQuartersOutsideTicks;
private int projectilePressure;
private int groundAssaultCooldownTicks = 400;
private int groundAssaultTicks;
private boolean kingLandingForCombat;
@Nullable
private Vec3 kingLandingWaypoint;
@Nullable
private Vec3 kingCombatWaypoint;
@Nullable
private Vec3 kingCombatProgressPosition;
private int kingCombatWaypointTicks;
private int kingCombatProgressTicks;
private int kingStrafeDirection = 1;
private int royalBoundaryGraceTicks; private int royalBoundaryGraceTicks;
@Nullable @Nullable
private ServerPlayer exileTarget; private ServerPlayer exileTarget;
@@ -156,12 +188,20 @@ public class KingEntity extends RoyalBossEntity {
return phase.maxConcurrentHeadAttacks(); return phase.maxConcurrentHeadAttacks();
} }
@Override
protected boolean managesOwnCombatLocomotion() {
return true;
}
public void setTreePatrolHome(Vec3 center, double minimumY, double maximumY, double angle) { public void setTreePatrolHome(Vec3 center, double minimumY, double maximumY, double angle) {
this.treePatrolCenter = center; this.treePatrolCenter = center;
this.treePatrolMinimumY = minimumY; this.treePatrolMinimumY = minimumY;
this.treePatrolMaximumY = maximumY; this.treePatrolMaximumY = maximumY;
this.treePatrolAngle = angle; this.treePatrolAngle = angle;
this.treePatrolWaypoint = null; this.treePatrolWaypoint = null;
this.treePatrolProgressPosition = null;
this.treePatrolProgressTicks = 0;
this.treePatrolFailures = 0;
this.treePatrolBound = true; this.treePatrolBound = true;
} }
@@ -383,11 +423,22 @@ public class KingEntity extends RoyalBossEntity {
ServerLevel serverLevel = (ServerLevel) this.level(); ServerLevel serverLevel = (ServerLevel) this.level();
this.iceBuildup.entrySet().removeIf(entry -> serverLevel.getEntity(entry.getKey()) == null); this.iceBuildup.entrySet().removeIf(entry -> serverLevel.getEntity(entry.getKey()) == null);
if (this.iceBuildup.size() > 16) this.iceBuildup.clear(); if (this.iceBuildup.size() > 16) this.iceBuildup.clear();
if (this.tickCount % 10 == 0 && this.projectilePressure > 0) {
this.projectilePressure--;
}
if (this.tickCount % 40 == 0) {
this.bumpBehavior(Behavior.RANGED, -1);
}
if (this.tickCount % 20 == 0 && this.getArrowCount() > 6) {
this.setArrowCount(6);
}
LivingEntity target = this.getTarget(); LivingEntity target = this.getTarget();
if (target != null && !this.isDeadOrDying() && this.level() instanceof ServerLevel level) { if (target != null && !this.isDeadOrDying() && this.level() instanceof ServerLevel level) {
this.trackBehavior(target); this.trackBehavior(target);
this.tickDecree(level, target); this.tickDecree(level, target);
this.tickKingWholeBody(level, target); this.tickKingWholeBody(level, target);
this.tickKingCombatMovement(target);
this.stabilizeKingRotation();
return; return;
} }
@@ -395,6 +446,7 @@ public class KingEntity extends RoyalBossEntity {
return; return;
} }
this.setRoyalFlying(true); this.setRoyalFlying(true);
this.resetKingCombatMovement();
this.decreeRetreatPressure = false; this.decreeRetreatPressure = false;
if (this.treePatrolBound && this.treePatrolCenter != null) { if (this.treePatrolBound && this.treePatrolCenter != null) {
this.tickTreePatrol(); this.tickTreePatrol();
@@ -416,16 +468,20 @@ public class KingEntity extends RoyalBossEntity {
} }
private void tickComeNoCloserIndicator() { private void tickComeNoCloserIndicator() {
if (!(this.activeDecree instanceof ComeNoCloserDecree) boolean keepOut = this.activeDecree instanceof ComeNoCloserDecree;
boolean closeQuarters = this.activeDecree instanceof CloseQuartersDecree;
if ((!keepOut && !closeQuarters)
|| this.tickCount % COME_NO_CLOSER_PARTICLE_INTERVAL != 0 || this.tickCount % COME_NO_CLOSER_PARTICLE_INTERVAL != 0
|| !(this.level() instanceof ServerLevel serverLevel)) { || !(this.level() instanceof ServerLevel serverLevel)) {
return; return;
} }
double radius = keepOut ? COME_NO_CLOSER_RADIUS : CLOSE_QUARTERS_RADIUS;
for (int index = 0; index < COME_NO_CLOSER_PARTICLE_COUNT; index++) { for (int index = 0; index < COME_NO_CLOSER_PARTICLE_COUNT; index++) {
double angle = (Math.PI * 2.0D * index) / COME_NO_CLOSER_PARTICLE_COUNT; double angle = (Math.PI * 2.0D * index) / COME_NO_CLOSER_PARTICLE_COUNT;
double x = this.getX() + Math.cos(angle) * COME_NO_CLOSER_RADIUS; double x = this.getX() + Math.cos(angle) * radius;
double z = this.getZ() + Math.sin(angle) * COME_NO_CLOSER_RADIUS; double z = this.getZ() + Math.sin(angle) * radius;
serverLevel.sendParticles(ParticleTypes.END_ROD, x, this.getY() + 0.25D, z, serverLevel.sendParticles(keepOut ? ParticleTypes.END_ROD : ParticleTypes.ENCHANT,
x, this.getY() + 0.25D, z,
1, 0.0D, 0.0D, 0.0D, 0.0D); 1, 0.0D, 0.0D, 0.0D, 0.0D);
} }
} }
@@ -440,9 +496,25 @@ public class KingEntity extends RoyalBossEntity {
this.treePatrolAngle -= Math.PI * 2.0D; this.treePatrolAngle -= Math.PI * 2.0D;
} }
Vec3 waypoint = this.treePatrolWaypoint; Vec3 waypoint = this.treePatrolWaypoint;
if (waypoint != null && ++this.treePatrolProgressTicks >= 40) {
if (this.treePatrolProgressPosition != null
&& this.position().distanceToSqr(this.treePatrolProgressPosition) < 1.0D
&& this.position().distanceToSqr(waypoint) > 36.0D) {
this.treePatrolWaypoint = null;
waypoint = null;
this.treePatrolFailures++;
this.treePatrolAngle += 0.35D;
} else {
this.treePatrolFailures = Math.max(0, this.treePatrolFailures - 1);
}
this.treePatrolProgressPosition = this.position();
this.treePatrolProgressTicks = 0;
}
if (waypoint == null || this.position().distanceToSqr(waypoint) < 36.0D) { if (waypoint == null || this.position().distanceToSqr(waypoint) < 36.0D) {
waypoint = this.findTreePatrolWaypoint(center, this.treePatrolAngle); waypoint = this.findTreePatrolWaypoint(center, this.treePatrolAngle);
this.treePatrolWaypoint = waypoint; this.treePatrolWaypoint = waypoint;
this.treePatrolProgressPosition = this.position();
this.treePatrolProgressTicks = 0;
} }
if (waypoint != null) { if (waypoint != null) {
this.getMoveControl().setWantedPosition(waypoint.x, waypoint.y, waypoint.z, 1.0D); this.getMoveControl().setWantedPosition(waypoint.x, waypoint.y, waypoint.z, 1.0D);
@@ -503,18 +575,40 @@ public class KingEntity extends RoyalBossEntity {
@Nullable @Nullable
private Vec3 findTreePatrolWaypoint(Vec3 center, double angle) { private Vec3 findTreePatrolWaypoint(Vec3 center, double angle) {
for (int attempt = 0; attempt < 10; attempt++) { double currentAngle = Math.atan2(this.getZ() - center.z, this.getX() - center.x);
double candidateAngle = angle + attempt * 0.22D; double baseAngle = Double.isFinite(currentAngle) ? currentAngle + 0.24D : angle;
double x = center.x + Math.cos(candidateAngle) * TREE_ORBIT_RADIUS; double[] radii = {TREE_ORBIT_RADIUS, TREE_ORBIT_RADIUS + 20.0D, TREE_ORBIT_RADIUS - 20.0D};
double z = center.z + Math.sin(candidateAngle) * TREE_ORBIT_RADIUS; double[] heightOffsets = {0.0D, 16.0D, -12.0D, 30.0D};
double vertical = 0.5D + 0.5D * Math.sin(candidateAngle); for (int angleAttempt = 0; angleAttempt < 8; angleAttempt++) {
double y = this.treePatrolMinimumY double candidateAngle = baseAngle + angleAttempt * 0.16D;
+ (this.treePatrolMaximumY - this.treePatrolMinimumY) * vertical; for (double radius : radii) {
Vec3 candidate = new Vec3(x, y, z); double x = center.x + Math.cos(candidateAngle) * radius;
if (this.clearTreePatrolPath(candidate)) { double z = center.z + Math.sin(candidateAngle) * radius;
return candidate; double vertical = 0.5D + 0.5D * Math.sin(candidateAngle);
double baseY = this.treePatrolMinimumY
+ (this.treePatrolMaximumY - this.treePatrolMinimumY) * vertical;
for (double heightOffset : heightOffsets) {
double y = Mth.clamp(baseY + heightOffset,
this.treePatrolMinimumY + 8.0D, this.treePatrolMaximumY - 8.0D);
Vec3 candidate = new Vec3(x, y, z);
if (this.clearTreePatrolPath(candidate)) {
return candidate;
}
}
} }
} }
Vec3 outward = this.position().subtract(center).multiply(1.0D, 0.0D, 1.0D);
if (outward.lengthSqr() < 1.0E-4D) {
outward = new Vec3(Math.cos(angle), 0.0D, Math.sin(angle));
}
Vec3 tangent = new Vec3(-outward.z, 0.0D, outward.x).normalize();
Vec3 recovery = this.position().add(tangent.scale(24.0D)).add(0.0D,
this.treePatrolFailures >= 2 ? 18.0D : 8.0D, 0.0D);
recovery = new Vec3(recovery.x,
Mth.clamp(recovery.y, this.treePatrolMinimumY + 8.0D, this.treePatrolMaximumY - 8.0D), recovery.z);
if (this.clearTreePatrolPath(recovery)) {
return recovery;
}
return null; return null;
} }
@@ -531,6 +625,179 @@ public class KingEntity extends RoyalBossEntity {
return true; return true;
} }
private void tickKingCombatMovement(LivingEntity target) {
boolean closeQuarters = this.activeDecree instanceof CloseQuartersDecree;
if (closeQuarters && this.isRoyalFlying() && !this.kingLandingForCombat) {
this.beginKingLanding(target);
} else if (!closeQuarters && this.isRoyalFlying() && !this.kingLandingForCombat
&& this.groundAssaultCooldownTicks-- <= 0 && target.onGround()) {
this.beginKingLanding(target);
}
if (this.kingLandingForCombat) {
if (!target.onGround() && !closeQuarters) {
this.kingLandingForCombat = false;
this.kingLandingWaypoint = null;
this.groundAssaultCooldownTicks = 160;
return;
}
if (this.kingLandingWaypoint == null) {
this.kingLandingWaypoint = this.findKingLandingPoint(target);
}
Vec3 landing = this.kingLandingWaypoint;
if (landing != null) {
this.setRoyalFlying(true);
this.getMoveControl().setWantedPosition(landing.x, landing.y, landing.z, 1.35D);
if (this.onGround() || this.getY() <= landing.y + 1.25D) {
this.setRoyalFlying(false);
this.kingLandingForCombat = false;
this.kingLandingWaypoint = null;
this.groundAssaultTicks = closeQuarters
? Math.max(GROUND_ASSAULT_TICKS, this.activeDecreeTicks + 20)
: GROUND_ASSAULT_TICKS;
}
}
return;
}
if (!this.isRoyalFlying()) {
if (closeQuarters) {
this.groundAssaultTicks = Math.max(this.groundAssaultTicks, this.activeDecreeTicks + 20);
}
this.getMoveControl().setWantedPosition(target.getX(), target.getY(), target.getZ(), 1.25D);
if (--this.groundAssaultTicks <= 0 && !closeQuarters) {
this.setRoyalFlying(true);
this.setDeltaMovement(this.getDeltaMovement().add(0.0D, 0.42D, 0.0D));
this.hasImpulse = true;
this.groundAssaultCooldownTicks = GROUND_ASSAULT_COOLDOWN_MIN
+ this.random.nextInt(GROUND_ASSAULT_COOLDOWN_VARIANCE + 1);
this.kingCombatWaypoint = null;
}
return;
}
if (this.kingCombatWaypoint != null && ++this.kingCombatProgressTicks >= 40) {
if (this.kingCombatProgressPosition != null
&& this.position().distanceToSqr(this.kingCombatProgressPosition) < 1.0D
&& this.position().distanceToSqr(this.kingCombatWaypoint) > 16.0D) {
this.kingCombatWaypoint = null;
this.kingStrafeDirection *= -1;
}
this.kingCombatProgressPosition = this.position();
this.kingCombatProgressTicks = 0;
}
if (this.kingCombatWaypoint == null || --this.kingCombatWaypointTicks <= 0
|| this.position().distanceToSqr(this.kingCombatWaypoint) < 16.0D) {
this.selectKingCombatWaypoint(target);
}
if (this.kingCombatWaypoint != null) {
double speed = this.projectilePressure >= 30 ? 1.4D : 1.15D;
this.getMoveControl().setWantedPosition(this.kingCombatWaypoint.x,
this.kingCombatWaypoint.y, this.kingCombatWaypoint.z, speed);
}
}
private void beginKingLanding(LivingEntity target) {
this.kingLandingWaypoint = this.findKingLandingPoint(target);
if (this.kingLandingWaypoint != null) {
this.kingLandingForCombat = true;
this.kingCombatWaypoint = null;
} else {
this.groundAssaultCooldownTicks = 100;
}
}
@Nullable
private Vec3 findKingLandingPoint(LivingEntity target) {
Vec3 away = this.position().subtract(target.position()).multiply(1.0D, 0.0D, 1.0D);
double baseAngle = away.lengthSqr() > 1.0E-4D ? Math.atan2(away.z, away.x) : this.random.nextDouble() * Mth.TWO_PI;
double[] radii = {9.0D, 13.0D, 17.0D, 6.0D};
for (int angleIndex = 0; angleIndex < 12; angleIndex++) {
double angle = baseAngle + angleIndex * Mth.TWO_PI / 12.0D;
for (double radius : radii) {
double x = target.getX() + Math.cos(angle) * radius;
double z = target.getZ() + Math.sin(angle) * radius;
double y = this.groundYBelow(x, z) + 0.1D;
Vec3 candidate = new Vec3(x, y, z);
AABB box = this.getBoundingBox().move(
candidate.x - this.getX(), candidate.y - this.getY(), candidate.z - this.getZ());
if (this.level().noCollision(this, box)) {
return candidate;
}
}
}
return null;
}
private void selectKingCombatWaypoint(LivingEntity target) {
Vec3 radial = this.position().subtract(target.position()).multiply(1.0D, 0.0D, 1.0D);
if (radial.lengthSqr() < 1.0E-4D) {
radial = new Vec3(1.0D, 0.0D, 0.0D);
}
radial = radial.normalize();
Vec3 tangent = new Vec3(-radial.z * this.kingStrafeDirection, 0.0D,
radial.x * this.kingStrafeDirection);
double range = this.activeDecree instanceof ComeNoCloserDecree || this.projectilePressure >= 30
? 40.0D : 34.0D;
Vec3 horizontal = target.position().add(radial.scale(range)).add(tangent.scale(12.0D));
double groundY = this.groundYBelow(horizontal.x, horizontal.z);
double y = Mth.clamp(target.getY() + 8.0D, groundY + FLYING_MIN_HOVER,
groundY + FLYING_MAX_HOVER_ABOVE_GROUND);
this.kingCombatWaypoint = new Vec3(horizontal.x, y, horizontal.z);
this.kingCombatWaypointTicks = COMBAT_WAYPOINT_MIN_TICKS
+ this.random.nextInt(COMBAT_WAYPOINT_VARIANCE + 1);
this.kingCombatProgressPosition = this.position();
this.kingCombatProgressTicks = 0;
if (this.random.nextInt(4) == 0) {
this.kingStrafeDirection *= -1;
}
}
private void stabilizeKingRotation() {
Vec3 movement = this.getDeltaMovement().multiply(1.0D, 0.0D, 1.0D);
if (movement.lengthSqr() < 0.0025D) {
return;
}
float desiredYaw = (float) (Mth.atan2(movement.z, movement.x) * 180.0D / Math.PI) - 90.0F;
float turn = Mth.clamp(Mth.wrapDegrees(desiredYaw - this.getYRot()), -7.0F, 7.0F);
this.setYRot(this.getYRot() + turn);
this.yBodyRot = this.getYRot();
}
private void resetKingCombatMovement() {
this.kingLandingForCombat = false;
this.kingLandingWaypoint = null;
this.kingCombatWaypoint = null;
this.kingCombatProgressPosition = null;
this.kingCombatWaypointTicks = 0;
this.kingCombatProgressTicks = 0;
this.groundAssaultTicks = 0;
if (this.groundAssaultCooldownTicks <= 0) {
this.groundAssaultCooldownTicks = 400;
}
}
public void requestCloseQuartersAssault(LivingEntity target) {
if (target != null && target.isAlive() && this.isRoyalFlying() && !this.kingLandingForCombat) {
this.beginKingLanding(target);
}
}
public RoyalDecree.Evaluation evaluateCloseQuarters(LivingEntity target) {
double distanceSquared = target.distanceToSqr(this);
if (distanceSquared <= CLOSE_QUARTERS_RADIUS * CLOSE_QUARTERS_RADIUS) {
this.closeQuartersEntered = true;
this.closeQuartersOutsideTicks = 0;
return RoyalDecree.Evaluation.COMPLIANT;
}
if (!this.closeQuartersEntered) {
return 300 - this.activeDecreeTicks >= CLOSE_QUARTERS_APPROACH_TICKS
? RoyalDecree.Evaluation.VIOLATED : RoyalDecree.Evaluation.COMPLIANT;
}
return ++this.closeQuartersOutsideTicks > CLOSE_QUARTERS_EXIT_GRACE_TICKS
? RoyalDecree.Evaluation.VIOLATED : RoyalDecree.Evaluation.COMPLIANT;
}
private void tickRoyalPunishment() { private void tickRoyalPunishment() {
if (this.exileTarget == null && this.titheTarget == null && this.targetShotPlayer == null && this.sealedTarget == null) { if (this.exileTarget == null && this.titheTarget == null && this.targetShotPlayer == null && this.sealedTarget == null) {
return; return;
@@ -742,6 +1009,8 @@ public class KingEntity extends RoyalBossEntity {
this.activeDecree = decree; this.activeDecree = decree;
this.activeDecreeTicks = 300; this.activeDecreeTicks = 300;
this.decreeCooldownTicks = 0; this.decreeCooldownTicks = 0;
this.closeQuartersEntered = false;
this.closeQuartersOutsideTicks = 0;
this.projectRoyalSound(AntarchySoundEvents.KING_DECREE.get(), 4.0F, 1.0F, target); this.projectRoyalSound(AntarchySoundEvents.KING_DECREE.get(), 4.0F, 1.0F, target);
this.sendDecreeTitle(target); this.sendDecreeTitle(target);
return true; return true;
@@ -1093,6 +1362,8 @@ public class KingEntity extends RoyalBossEntity {
this.activeDecreeTicks = 300; this.activeDecreeTicks = 300;
this.activeDecree = this.pickDecree(target); this.activeDecree = this.pickDecree(target);
this.decreeRetreatPressure = false; this.decreeRetreatPressure = false;
this.closeQuartersEntered = false;
this.closeQuartersOutsideTicks = 0;
this.playRoyalSound(AntarchySoundEvents.KING_DECREE_CAST.get(), 0.9F + this.random.nextFloat() * 0.15F); this.playRoyalSound(AntarchySoundEvents.KING_DECREE_CAST.get(), 0.9F + this.random.nextFloat() * 0.15F);
this.playRoyalSound(AntarchySoundEvents.KING_ROAR.get(), 0.8F + this.random.nextFloat() * 0.12F); this.playRoyalSound(AntarchySoundEvents.KING_ROAR.get(), 0.8F + this.random.nextFloat() * 0.12F);
this.projectRoyalSound(AntarchySoundEvents.KING_DECREE.get(), 4.0F, 1.0F, target); this.projectRoyalSound(AntarchySoundEvents.KING_DECREE.get(), 4.0F, 1.0F, target);
@@ -1115,10 +1386,19 @@ public class KingEntity extends RoyalBossEntity {
} }
private RoyalDecree pickDecree(LivingEntity target) { private RoyalDecree pickDecree(LivingEntity target) {
if ((this.projectilePressure >= 20 || this.behaviorScore(Behavior.RANGED) >= 6)
&& !"decree.antarchy.close_quarters".equals(this.lastDecreeKey)) {
return DECREES.stream()
.filter(CloseQuartersDecree.class::isInstance)
.findFirst()
.orElse(DECREES.get(0));
}
int totalWeight = 0; int totalWeight = 0;
int[] weights = new int[DECREES.size()]; int[] weights = new int[DECREES.size()];
for (int i = 0; i < DECREES.size(); i++) { for (int i = 0; i < DECREES.size(); i++) {
weights[i] = Math.max(1, DECREES.get(i).contextWeight(this, target)); RoyalDecree decree = DECREES.get(i);
weights[i] = decree.translationKey().equals(this.lastDecreeKey)
? 0 : Math.max(1, decree.contextWeight(this, target));
totalWeight += weights[i]; totalWeight += weights[i];
} }
int roll = this.random.nextInt(totalWeight); int roll = this.random.nextInt(totalWeight);
@@ -1145,11 +1425,14 @@ public class KingEntity extends RoyalBossEntity {
player.connection.send(new ClientboundClearTitlesPacket(false)); player.connection.send(new ClientboundClearTitlesPacket(false));
} }
if (this.activeDecree != null) { if (this.activeDecree != null) {
this.lastDecreeKey = this.activeDecree.translationKey();
this.activeDecree.onEnded(); this.activeDecree.onEnded();
} }
this.activeDecree = null; this.activeDecree = null;
this.activeDecreeTicks = 0; this.activeDecreeTicks = 0;
this.decreeRetreatPressure = false; this.decreeRetreatPressure = false;
this.closeQuartersEntered = false;
this.closeQuartersOutsideTicks = 0;
this.decreeCooldownTicks = AntarchySettings.royalDecreeCooldownTicks(); this.decreeCooldownTicks = AntarchySettings.royalDecreeCooldownTicks();
this.startRoyalRecovery(40); this.startRoyalRecovery(40);
} }
@@ -1166,13 +1449,63 @@ public class KingEntity extends RoyalBossEntity {
if (this.activeDecree == null || target == null || !target.isAlive()) { if (this.activeDecree == null || target == null || !target.isAlive()) {
return; return;
} }
if (target instanceof ServerPlayer player) { this.attackScheduler.cancel(RoyalAttackLane.DECREE);
this.projectRoyalSound(AntarchySoundEvents.KING_JUDGEMENT.get(), 4.0F, 1.0F, target); this.attackScheduler.cancel(RoyalAttackLane.HAZARD);
this.debugTriggerPunishment(RoyalPunishmentType.ROYAL_EXILE, player);
} else {
this.invokeJudgment(target);
}
this.endDecree(target); this.endDecree(target);
this.projectRoyalSound(AntarchySoundEvents.KING_JUDGEMENT.get(), 4.0F, 1.0F, target);
if (target instanceof ServerPlayer player) {
this.sendDecreeViolationTitle(player);
}
this.startRoyalJudgmentBarrage(target);
}
private void sendDecreeViolationTitle(ServerPlayer player) {
player.connection.send(new ClientboundSetTitlesAnimationPacket(5, 45, 10));
player.connection.send(new ClientboundSetTitleTextPacket(Component.translatable("decree.antarchy.violated")
.withStyle(style -> style.withColor(ChatFormatting.DARK_PURPLE).withBold(true))));
player.connection.send(new ClientboundSetSubtitleTextPacket(Component.translatable("decree.antarchy.violated.subtitle")
.withStyle(style -> style.withColor(ChatFormatting.LIGHT_PURPLE))));
}
private void startRoyalJudgmentBarrage(LivingEntity target) {
if (!(this.level() instanceof ServerLevel level)) {
return;
}
this.beginRoyalAttack("royal_judgment", RoyalAttackLane.HAZARD, 80,
20, 9, 12, new com.craisinlord.antarchy.content.entity.royal.attack.RoyalAttackScheduler.Action() {
@Override
public void onStart() {
for (RoyalHead.Slot slot : RoyalHead.Slot.values()) {
KingEntity.this.triggerAnim(slot.controllerName(), "shoot");
}
level.sendParticles(ParticleTypes.WITCH,
KingEntity.this.getX(), KingEntity.this.getY() + KingEntity.this.getBbHeight() * 0.7D,
KingEntity.this.getZ(), 70, 4.0D, 3.0D, 4.0D, 0.12D);
}
@Override
public void onActive(int elapsedTicks) {
if (elapsedTicks % 4 == 0 && target.isAlive() && target.level() == level) {
KingEntity.this.fireRoyalJudgmentWave(level, target);
}
}
});
}
private void fireRoyalJudgmentWave(ServerLevel level, LivingEntity target) {
Vec3 predicted = target.getEyePosition().add(target.getDeltaMovement().scale(4.0D));
for (RoyalHead.Slot slot : RoyalHead.Slot.values()) {
RoyalHead head = this.royalHead(slot);
Vec3 origin = this.headAnchor(head);
Vec3 direction = predicted.subtract(origin).normalize();
RoyalBoltEntity bolt = new RoyalBoltEntity(AntarchyObjects.ROYAL_BOLT.get(), level);
bolt.setOwner(this);
bolt.setElement(RoyalBeamElement.QUEEN_PURPLE);
bolt.setPos(origin.x, origin.y, origin.z);
bolt.shoot(direction.x, direction.y, direction.z, 1.55F, 1.0F);
level.addFreshEntity(bolt);
}
this.playRoyalSound(AntarchySoundEvents.KING_BEAM_SHOOT.get(), 1.15F);
} }
public boolean blocksHealing() { public boolean blocksHealing() {
@@ -1200,6 +1533,17 @@ public class KingEntity extends RoyalBossEntity {
this.lastPlayerDamageTime.put(attacker.getUUID(), this.level().getGameTime()); this.lastPlayerDamageTime.put(attacker.getUUID(), this.level().getGameTime());
boolean projectile = source.getDirectEntity() instanceof Projectile; boolean projectile = source.getDirectEntity() instanceof Projectile;
this.bumpBehavior(projectile ? Behavior.RANGED : Behavior.HUGGING, 2); this.bumpBehavior(projectile ? Behavior.RANGED : Behavior.HUGGING, 2);
if (projectile) {
this.projectilePressure = Math.min(PROJECTILE_PRESSURE_MAX,
this.projectilePressure + PROJECTILE_PRESSURE_PER_HIT);
if (this.isRoyalFlying() && !(this.activeDecree instanceof CloseQuartersDecree)) {
if (this.projectilePressure >= 40) {
amount *= 0.55F;
} else if (this.projectilePressure >= 20) {
amount *= 0.75F;
}
}
}
if (this.activeDecree instanceof CloseQuartersDecree && projectile) { if (this.activeDecree instanceof CloseQuartersDecree && projectile) {
this.failActiveDecree(attacker); this.failActiveDecree(attacker);
} else if (this.activeDecree instanceof ComeNoCloserDecree && !projectile) { } else if (this.activeDecree instanceof ComeNoCloserDecree && !projectile) {
@@ -284,6 +284,11 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
return 0.35D; return 0.35D;
} }
/** Lets a boss provide a bespoke air/ground cadence without changing the other royal encounter. */
protected boolean managesOwnCombatLocomotion() {
return false;
}
protected boolean shouldClearObstruction() { protected boolean shouldClearObstruction() {
return true; return true;
} }
@@ -799,7 +804,7 @@ public abstract class RoyalBossEntity extends Monster implements GeoEntity, Mult
} }
private void tickCombatLocomotionMode(LivingEntity target) { private void tickCombatLocomotionMode(LivingEntity target) {
if (!this.isFlyingBoss()) { if (!this.isFlyingBoss() || this.managesOwnCombatLocomotion()) {
return; return;
} }
boolean inverted = AntarchyGravityApi.isGravityInverted(this); boolean inverted = AntarchyGravityApi.isGravityInverted(this);
@@ -4,7 +4,13 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
public final class CloseQuartersDecree implements RoyalDecree { public final class CloseQuartersDecree implements RoyalDecree {
public String translationKey() { return "decree.antarchy.close_quarters"; } public String translationKey() { return "decree.antarchy.close_quarters"; }
public void apply(ServerLevel level, KingEntity king, LivingEntity target) { } public void apply(ServerLevel level, KingEntity king, LivingEntity target) {
king.requestCloseQuartersAssault(target);
}
@Override
public Evaluation evaluate(ServerLevel level, KingEntity king, LivingEntity target) {
return king.evaluateCloseQuarters(target);
}
@Override @Override
public int contextWeight(KingEntity king, LivingEntity target) { public int contextWeight(KingEntity king, LivingEntity target) {
return 4 + king.behaviorScore(KingEntity.Behavior.RANGED); return 4 + king.behaviorScore(KingEntity.Behavior.RANGED);
@@ -23,6 +23,7 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.gameevent.GameEvent;
@@ -104,7 +105,7 @@ public final class AttitudeAdjusterSlamManager {
if (player.onGround() || player.isInWaterOrBubble() || player.isInLava() || player.isFallFlying() || player.getAbilities().flying || PLAYER_SLAMS.containsKey(player.getUUID())) { if (player.onGround() || player.isInWaterOrBubble() || player.isInLava() || player.isFallFlying() || player.getAbilities().flying || PLAYER_SLAMS.containsKey(player.getUUID())) {
return false; return false;
} }
PLAYER_SLAMS.put(player.getUUID(), new PlayerSlamState(player.getUUID(), player.serverLevel().dimension().location().toString(), player.serverLevel().getGameTime() + SLAM_TIMEOUT_TICKS, player.fallDistance)); PLAYER_SLAMS.put(player.getUUID(), new PlayerSlamState(player.getUUID(), hand, player.serverLevel().dimension().location().toString(), player.serverLevel().getGameTime() + SLAM_TIMEOUT_TICKS, player.fallDistance));
AntarchyGravityDirection gravityDirection = AntarchyGravityRotationUtil.getGravityDownDirection(player) == Direction.UP ? AntarchyGravityDirection.UP : AntarchyGravityDirection.DOWN; AntarchyGravityDirection gravityDirection = AntarchyGravityRotationUtil.getGravityDownDirection(player) == Direction.UP ? AntarchyGravityDirection.UP : AntarchyGravityDirection.DOWN;
Vec3 motion = player.getDeltaMovement(); Vec3 motion = player.getDeltaMovement();
Vec3 localMotion = AntarchyGravityRotationUtil.vecWorldToPlayer(motion, gravityDirection); Vec3 localMotion = AntarchyGravityRotationUtil.vecWorldToPlayer(motion, gravityDirection);
@@ -194,7 +195,8 @@ public final class AttitudeAdjusterSlamManager {
if (AntarchySettings.attitudeAdjusterBreaksBlocks()) { if (AntarchySettings.attitudeAdjusterBreaksBlocks()) {
breakBlocks(level, player, groundPos, gravityDown); breakBlocks(level, player, groundPos, gravityDown);
} }
if (player.getMainHandItem().getItem() instanceof AttitudeAdjusterItem item) { ItemStack slamStack = player.getItemInHand(state.hand);
if (slamStack.getItem() instanceof AttitudeAdjusterItem item) {
player.getCooldowns().addCooldown(item, PLAYER_SLAM_COOLDOWN_TICKS); player.getCooldowns().addCooldown(item, PLAYER_SLAM_COOLDOWN_TICKS);
} }
iterator.remove(); iterator.remove();
@@ -319,12 +321,14 @@ public final class AttitudeAdjusterSlamManager {
private static final class PlayerSlamState { private static final class PlayerSlamState {
private final UUID playerId; private final UUID playerId;
private final net.minecraft.world.InteractionHand hand;
private final String dimensionId; private final String dimensionId;
private final long expiresAt; private final long expiresAt;
private final float startFallDistance; private final float startFallDistance;
private PlayerSlamState(UUID playerId, String dimensionId, long expiresAt, float startFallDistance) { private PlayerSlamState(UUID playerId, net.minecraft.world.InteractionHand hand, String dimensionId, long expiresAt, float startFallDistance) {
this.playerId = playerId; this.playerId = playerId;
this.hand = hand;
this.dimensionId = dimensionId; this.dimensionId = dimensionId;
this.expiresAt = expiresAt; this.expiresAt = expiresAt;
this.startFallDistance = startFallDistance; this.startFallDistance = startFallDistance;
@@ -6,6 +6,9 @@ import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel; import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel;
import com.craisinlord.antarchy.content.client.renderer.AnimatedHeldItemRenderer; import com.craisinlord.antarchy.content.client.renderer.AnimatedHeldItemRenderer;
import com.craisinlord.antarchy.content.entity.OctopusBombEntity; import com.craisinlord.antarchy.content.entity.OctopusBombEntity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
@@ -161,15 +164,12 @@ public class RpoLauncherItem extends ProjectileWeaponItem implements GeoItem {
} }
float yaw = player.getYRot() + yawOffset; float yaw = player.getYRot() + yawOffset;
Vec3 direction = Vec3.directionFromRotation(new Vec2(player.getXRot(), yaw)); Vec3 localDirection = Vec3.directionFromRotation(new Vec2(player.getXRot(), yaw));
projectileBomb.moveTo( AntarchyGravityDirection gravity = AntarchyGravityApi.getGravityDirection(player);
player.getX(), Vec3 direction = AntarchyGravityRotationUtil.vecPlayerToWorld(localDirection, gravity).normalize();
player.getEyeY() + 0.15D, Vec3 spawn = player.getEyePosition().add(direction.scale(0.55D));
player.getZ(), projectileBomb.moveTo(spawn.x, spawn.y, spawn.z, yaw, player.getXRot());
yaw, projectileBomb.launchAsExplosiveProjectile(player, direction.scale(AntarchySettings.rpoLauncherLaunchVelocity()).add(AntarchyGravityApi.deltaMovement(player)));
player.getXRot()
);
projectileBomb.launchAsExplosiveProjectile(player, direction.scale(AntarchySettings.rpoLauncherLaunchVelocity()).add(player.getDeltaMovement()));
level.addFreshEntity(projectileBomb); level.addFreshEntity(projectileBomb);
} }
@@ -5,6 +5,9 @@ import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchySoundEvents; import com.craisinlord.antarchy.content.AntarchySoundEvents;
import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel; import com.craisinlord.antarchy.content.client.model.ResourceBackedGeoItemModel;
import com.craisinlord.antarchy.content.entity.MissileSquidEntity; import com.craisinlord.antarchy.content.entity.MissileSquidEntity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityDirection;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityRotationUtil;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Predicate; import java.util.function.Predicate;
import net.minecraft.core.component.DataComponents; import net.minecraft.core.component.DataComponents;
@@ -162,15 +165,12 @@ public class SquidzookaItem extends ProjectileWeaponItem implements GeoItem {
} }
float yaw = player.getYRot() + yawOffset; float yaw = player.getYRot() + yawOffset;
Vec3 direction = Vec3.directionFromRotation(new Vec2(player.getXRot(), yaw)); Vec3 localDirection = Vec3.directionFromRotation(new Vec2(player.getXRot(), yaw));
projectileSquid.moveTo( AntarchyGravityDirection gravity = AntarchyGravityApi.getGravityDirection(player);
player.getX(), Vec3 direction = AntarchyGravityRotationUtil.vecPlayerToWorld(localDirection, gravity).normalize();
player.getEyeY() - 0.2D, Vec3 spawn = player.getEyePosition().add(direction.scale(0.45D));
player.getZ(), projectileSquid.moveTo(spawn.x, spawn.y, spawn.z, yaw, player.getXRot());
yaw, projectileSquid.launchAsProjectile(player, direction.scale(AntarchySettings.squidzookaLaunchVelocity()).add(AntarchyGravityApi.deltaMovement(player)));
player.getXRot()
);
projectileSquid.launchAsProjectile(player, direction.scale(AntarchySettings.squidzookaLaunchVelocity()).add(player.getDeltaMovement()));
level.addFreshEntity(projectileSquid); level.addFreshEntity(projectileSquid);
} }
@@ -147,14 +147,42 @@ public final class KingsTreeGridFeature extends Feature<NoneFeatureConfiguration
// Start near the lower trunk so players on the ground can reliably engage the King. // Start near the lower trunk so players on the ground can reliably engage the King.
// The patrol bounds remain unchanged, allowing him to retreat upward through the tree. // The patrol bounds remain unchanged, allowing him to retreat upward through the tree.
double spawnY = minimumY + 48.0D; double spawnY = minimumY + 48.0D;
// Start just outside the central trunk, inside the tree's authored footprint. Vec3 spawn = findSafeKingSpawn(serverLevel, king, centerX, centerZ, spawnY);
king.moveTo(centerX + 48.5D, spawnY, centerZ + 0.5D, 90.0F, 0.0F); king.moveTo(spawn.x, spawn.y, spawn.z,
(float) (Math.atan2(centerZ + 0.5D - spawn.z, centerX + 0.5D - spawn.x)
* 180.0D / Math.PI) - 90.0F,
0.0F);
king.setTreePatrolHome(treeCenter, minimumY, maximumY, 0.0D); king.setTreePatrolHome(treeCenter, minimumY, maximumY, 0.0D);
king.setPersistenceRequired(); king.setPersistenceRequired();
serverLevel.addFreshEntity(king); serverLevel.addFreshEntity(king);
} }
} }
private static Vec3 findSafeKingSpawn(ServerLevel level, KingEntity king,
int centerX, int centerZ, double spawnY) {
double[] radii = {96.0D, 80.0D, 64.0D};
double[] heightOffsets = {0.0D, 18.0D, -12.0D, 32.0D};
for (double radius : radii) {
for (int angleIndex = 0; angleIndex < 16; angleIndex++) {
double angle = angleIndex * Math.PI * 2.0D / 16.0D;
double x = centerX + 0.5D + Math.cos(angle) * radius;
double z = centerZ + 0.5D + Math.sin(angle) * radius;
for (double heightOffset : heightOffsets) {
Vec3 candidate = new Vec3(x, spawnY + heightOffset, z);
BlockPos blockPos = BlockPos.containing(candidate);
if (!level.hasChunksAt(blockPos.offset(-8, -8, -8), blockPos.offset(8, 16, 8))) {
continue;
}
king.moveTo(candidate.x, candidate.y, candidate.z, 0.0F, 0.0F);
if (level.noCollision(king, king.getBoundingBox())) {
return candidate;
}
}
}
}
return new Vec3(centerX + 64.5D, spawnY + 32.0D, centerZ + 0.5D);
}
private static ResourceLocation tileLocation(int tileX, int tileZ) { private static ResourceLocation tileLocation(int tileX, int tileZ) {
return ResourceLocation.fromNamespaceAndPath( return ResourceLocation.fromNamespaceAndPath(
Antarchy.MODID, Antarchy.MODID,
@@ -1,5 +1,6 @@
package com.craisinlord.antarchy.mixins.gravity; package com.craisinlord.antarchy.mixins.gravity;
import com.craisinlord.antarchy.content.gravity.AntarchyGravityApi;
import com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager; import com.craisinlord.antarchy.content.worldgen.thoraxis.ThoraxisUndersideManager;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.entity.projectile.Projectile;
@@ -18,8 +19,15 @@ public abstract class EntityProjectileGravityMixin {
@Inject(method = "applyGravity", at = @At("HEAD"), cancellable = true) @Inject(method = "applyGravity", at = @At("HEAD"), cancellable = true)
private void antarchy$applyProjectileGravityUpward(CallbackInfo ci) { private void antarchy$applyProjectileGravityUpward(CallbackInfo ci) {
Entity self = (Entity) (Object) this; Entity self = (Entity) (Object) this;
if (!(self instanceof Projectile projectile) if (!(self instanceof Projectile projectile)) {
|| !ThoraxisUndersideManager.isInUnderside(projectile)) { return;
}
boolean inverted = AntarchyGravityApi.isGravityInverted(projectile);
if (!inverted && projectile.getOwner() != null) {
inverted = AntarchyGravityApi.isGravityInverted(projectile.getOwner());
}
if (!inverted && !ThoraxisUndersideManager.isInUnderside(projectile)) {
return; return;
} }
@@ -57,7 +57,7 @@ public abstract class ProjectileGravityMixin {
@Local(argsOnly = true) Entity shooter @Local(argsOnly = true) Entity shooter
) { ) {
Vec3 direction = new Vec3(x, y, z); Vec3 direction = new Vec3(x, y, z);
if (ThoraxisUndersideManager.shouldInvertInUnderside(shooter)) { if (AntarchyGravityApi.isGravityInverted(shooter)) {
direction = AntarchyGravityRotationUtil.vecPlayerToWorld( direction = AntarchyGravityRotationUtil.vecPlayerToWorld(
direction, direction,
AntarchyGravityApi.getGravityDirection(shooter) AntarchyGravityApi.getGravityDirection(shooter)
@@ -905,6 +905,7 @@
"tooltip.antarchy.lucid_pearl": "Throws an inverted-gravity projectile.", "tooltip.antarchy.lucid_pearl": "Throws an inverted-gravity projectile.",
"tooltip.antarchy.lucid_pearl.detail": "Teleports you to where it lands and applies Inverted.", "tooltip.antarchy.lucid_pearl.detail": "Teleports you to where it lands and applies Inverted.",
"subtitles.antarchy.squidzooka_fire": "Squidzooka fires", "subtitles.antarchy.squidzooka_fire": "Squidzooka fires",
"subtitles.antarchy.undertrial_detect_player": "Undertrial spawner detects player",
"subtitles.antarchy.size_ray_charge": "Size Ray charges", "subtitles.antarchy.size_ray_charge": "Size Ray charges",
"subtitles.antarchy.size_ray_fire": "Size Ray fires", "subtitles.antarchy.size_ray_fire": "Size Ray fires",
"subtitles.antarchy.ant_ambient": "Ants chirp", "subtitles.antarchy.ant_ambient": "Ants chirp",
@@ -1418,7 +1419,9 @@
,"decree.antarchy.kneel": "KNEEL" ,"decree.antarchy.kneel": "KNEEL"
,"decree.antarchy.kneel.subtitle": "Crouch within five seconds." ,"decree.antarchy.kneel.subtitle": "Crouch within five seconds."
,"decree.antarchy.close_quarters": "CLOSE QUARTERS" ,"decree.antarchy.close_quarters": "CLOSE QUARTERS"
,"decree.antarchy.close_quarters.subtitle": "Projectiles are forbidden." ,"decree.antarchy.close_quarters.subtitle": "Enter the royal circle. Projectiles are forbidden."
,"decree.antarchy.violated": "DECREE VIOLATED"
,"decree.antarchy.violated.subtitle": "Face the King's judgment."
,"decree.antarchy.come_no_closer": "COME NO CLOSER" ,"decree.antarchy.come_no_closer": "COME NO CLOSER"
,"decree.antarchy.come_no_closer.subtitle": "Keep out of the King's inner radius." ,"decree.antarchy.come_no_closer.subtitle": "Keep out of the King's inner radius."
,"decree.antarchy.fight_me_coward": "FIGHT ME, COWARD!" ,"decree.antarchy.fight_me_coward": "FIGHT ME, COWARD!"
@@ -17,6 +17,18 @@
{ "name": "antarchy:thoraxis_lucid_pools_additions", "type": "event" } { "name": "antarchy:thoraxis_lucid_pools_additions", "type": "event" }
] ]
}, },
"undertrial_detect_player1": {
"subtitle": "subtitles.antarchy.undertrial_detect_player",
"sounds": [
{ "name": "antarchy:block/undertrial/undertrial_detect_player1" }
]
},
"undertrial_detect_player2": {
"subtitle": "subtitles.antarchy.undertrial_detect_player",
"sounds": [
{ "name": "antarchy:block/undertrial/undertrial_detect_player2" }
]
},
"squidzooka_fire": { "squidzooka_fire": {
"subtitle": "subtitles.antarchy.squidzooka_fire", "subtitle": "subtitles.antarchy.squidzooka_fire",
"sounds": [ "sounds": [
@@ -1106,10 +1118,6 @@
"name": "antarchy:inversion_layer", "name": "antarchy:inversion_layer",
"type": "event", "type": "event",
"stream": true "stream": true
},
{
"name": "antarchy:music/game/thoraxis/assimilation",
"stream": true
} }
] ]
}, },
@@ -530,6 +530,8 @@ public final class AntarchyFabricSounds {
public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_PLACE = registerSoundEvent("antimetal_place"); public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_PLACE = registerSoundEvent("antimetal_place");
public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_STEP = registerSoundEvent("antimetal_step"); public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_STEP = registerSoundEvent("antimetal_step");
public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_SCAFFOLD = registerSoundEvent("antimetal_scaffold"); public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_SCAFFOLD = registerSoundEvent("antimetal_scaffold");
public static final DeferredHolder<SoundEvent, SoundEvent> UNDERTRIAL_DETECT_PLAYER1 = registerSoundEvent("undertrial_detect_player1");
public static final DeferredHolder<SoundEvent, SoundEvent> UNDERTRIAL_DETECT_PLAYER2 = registerSoundEvent("undertrial_detect_player2");
public static final DeferredHolder<SoundEvent, SoundEvent> KING_IDLE = registerSoundEvent("king_idle"); public static final DeferredHolder<SoundEvent, SoundEvent> KING_IDLE = registerSoundEvent("king_idle");
public static final DeferredHolder<SoundEvent, SoundEvent> KING_WALK = registerSoundEvent("king_walk"); public static final DeferredHolder<SoundEvent, SoundEvent> KING_WALK = registerSoundEvent("king_walk");
@@ -676,7 +676,7 @@ public final class AntarchyMobsConfig {
KING_BEAM_TRACKING = b.defineInRange("kingBeamTracking", 0.1D, 0.0D, 1.0D); 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_RADIUS = b.defineInRange("kingBeamTerrainRadius", 5.0D, 0.0D, 32.0D);
KING_BEAM_TERRAIN_CAP = b.defineInRange("kingBeamTerrainCap", 192, 0, 4096); KING_BEAM_TERRAIN_CAP = b.defineInRange("kingBeamTerrainCap", 192, 0, 4096);
ROYAL_DECREE_COOLDOWN_TICKS = b.comment("Cooldown in ticks between the end of one King decree and the next.").defineInRange("royalDecreeCooldownTicks", 1200, 1, 72000); ROYAL_DECREE_COOLDOWN_TICKS = b.comment("Cooldown in ticks between the end of one King decree and the next.").defineInRange("royalDecreeCooldownTicks", 700, 1, 72000);
KING_ROYAL_MUSTER_COOLDOWN_TICKS = b.comment("Cooldown in ticks between King's command pulses.").defineInRange("kingRoyalMusterCooldownTicks", 500, 1, 72000); KING_ROYAL_MUSTER_COOLDOWN_TICKS = b.comment("Cooldown in ticks between King's command pulses.").defineInRange("kingRoyalMusterCooldownTicks", 500, 1, 72000);
KING_ROYAL_MUSTER_WINDUP_TICKS = b.comment("Warning time before the King commands nearby hostile mobs.").defineInRange("kingRoyalMusterWindupTicks", 30, 0, 1200); KING_ROYAL_MUSTER_WINDUP_TICKS = b.comment("Warning time before the King commands nearby hostile mobs.").defineInRange("kingRoyalMusterWindupTicks", 30, 0, 1200);
KING_ROYAL_MUSTER_DURATION_TICKS = b.comment("Duration of Commanded applied by the King's muster.").defineInRange("kingRoyalMusterDurationTicks", 600, 1, 72000); KING_ROYAL_MUSTER_DURATION_TICKS = b.comment("Duration of Commanded applied by the King's muster.").defineInRange("kingRoyalMusterDurationTicks", 600, 1, 72000);
@@ -213,6 +213,8 @@ public final class AntarchyNeoforgeSounds {
public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_PLACE = registerSoundEvent("antimetal_place"); public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_PLACE = registerSoundEvent("antimetal_place");
public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_STEP = registerSoundEvent("antimetal_step"); public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_STEP = registerSoundEvent("antimetal_step");
public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_SCAFFOLD = registerSoundEvent("antimetal_scaffold"); public static final DeferredHolder<SoundEvent, SoundEvent> ANTIMETAL_SCAFFOLD = registerSoundEvent("antimetal_scaffold");
public static final DeferredHolder<SoundEvent, SoundEvent> UNDERTRIAL_DETECT_PLAYER1 = registerSoundEvent("undertrial_detect_player1");
public static final DeferredHolder<SoundEvent, SoundEvent> UNDERTRIAL_DETECT_PLAYER2 = registerSoundEvent("undertrial_detect_player2");
public static final DeferredHolder<SoundEvent, SoundEvent> KING_IDLE = registerSoundEvent("king_idle"); public static final DeferredHolder<SoundEvent, SoundEvent> KING_IDLE = registerSoundEvent("king_idle");
public static final DeferredHolder<SoundEvent, SoundEvent> KING_WALK = registerSoundEvent("king_walk"); public static final DeferredHolder<SoundEvent, SoundEvent> KING_WALK = registerSoundEvent("king_walk");