alpha mantis boss, mantis spin fix, overworld mantis spawns, elythia turtle fix

This commit is contained in:
craisinlord committed 2026-07-05 23:23:48 -05:00
1 parent cab314d30e
commit ee4f09c094
24 files changed
+509 -5

No files matched your search

@@ -100,6 +100,12 @@ public final class AntarchySettings {
private static double mantisMovementSpeed = 0.42D;
private static double mantisFlyingSpeed = 0.77D;
private static boolean mantisIgnoreLightLevel = false;
private static double alphaMantisHealth = 500.0D;
private static double alphaMantisAttackDamage = 18.0D;
private static double alphaMantisMovementSpeed = 0.42D;
private static double alphaMantisFlyingSpeed = 0.77D;
private static int alphaMantisSummonIntervalTicks = 300;
private static int alphaMantisMaxMinions = 4;
private static double krakenProjectileDamageTakenMultiplier = 0.5D;
private static boolean krakenSquidSpawnEnabled = true;
private static boolean krakenMassSpawnEnabled = true;
@@ -789,6 +795,30 @@ public final class AntarchySettings {
mantisIgnoreLightLevel = value;
}
public static double alphaMantisHealth() {
return alphaMantisHealth;
}
public static double alphaMantisAttackDamage() {
return alphaMantisAttackDamage;
}
public static double alphaMantisMovementSpeed() {
return alphaMantisMovementSpeed;
}
public static double alphaMantisFlyingSpeed() {
return alphaMantisFlyingSpeed;
}
public static int alphaMantisSummonIntervalTicks() {
return alphaMantisSummonIntervalTicks;
}
public static int alphaMantisMaxMinions() {
return alphaMantisMaxMinions;
}
public static double waspHealth() {
return waspHealth;
}
@@ -1193,6 +1223,30 @@ public final class AntarchySettings {
mantisFlyingSpeed = value;
}
public static void setAlphaMantisHealth(double value) {
alphaMantisHealth = value;
}
public static void setAlphaMantisAttackDamage(double value) {
alphaMantisAttackDamage = value;
}
public static void setAlphaMantisMovementSpeed(double value) {
alphaMantisMovementSpeed = value;
}
public static void setAlphaMantisFlyingSpeed(double value) {
alphaMantisFlyingSpeed = value;
}
public static void setAlphaMantisSummonIntervalTicks(int value) {
alphaMantisSummonIntervalTicks = value;
}
public static void setAlphaMantisMaxMinions(int value) {
alphaMantisMaxMinions = value;
}
public static void setKrakenProjectileDamageTakenMultiplier(double value) {
krakenProjectileDamageTakenMultiplier = value;
}
@@ -0,0 +1,23 @@
package com.craisinlord.antarchy.content.client.model;
import com.craisinlord.antarchy.Antarchy;
import com.craisinlord.antarchy.content.entity.AlphaMantisEntity;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.model.GeoModel;
public class AlphaMantisModel extends GeoModel<AlphaMantisEntity> {
@Override
public ResourceLocation getModelResource(AlphaMantisEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "geo/mantis.geo.json");
}
@Override
public ResourceLocation getTextureResource(AlphaMantisEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "textures/entity/mantis_alpha.png");
}
@Override
public ResourceLocation getAnimationResource(AlphaMantisEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(Antarchy.MODID, "animations/mantis.animation.json");
}
}
@@ -0,0 +1,15 @@
package com.craisinlord.antarchy.content.client.renderer;
import com.craisinlord.antarchy.content.client.model.AlphaMantisModel;
import com.craisinlord.antarchy.content.entity.AlphaMantisEntity;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import software.bernie.geckolib.renderer.GeoEntityRenderer;
public class AlphaMantisRenderer extends GeoEntityRenderer<AlphaMantisEntity> {
public AlphaMantisRenderer(EntityRendererProvider.Context context) {
super(context, new AlphaMantisModel());
this.shadowRadius = 1.5F;
// Mantis renders at 1.25x; the alpha is 1.5x bigger overall
this.withScale(1.875F);
}
}
@@ -0,0 +1,184 @@
package com.craisinlord.antarchy.content.entity;
import com.craisinlord.antarchy.config.AntarchySettings;
import com.craisinlord.antarchy.content.AntarchyObjects;
import com.craisinlord.antarchy.content.AntarchyTags;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.RandomSource;
import net.minecraft.world.BossEvent;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.Nullable;
public class AlphaMantisEntity extends MantisEntity {
private final ServerBossEvent bossEvent =
new ServerBossEvent(Component.translatable("entity.antarchy.alpha_mantis"), BossEvent.BossBarColor.GREEN, BossEvent.BossBarOverlay.PROGRESS);
private int summonCooldownTicks;
public AlphaMantisEntity(EntityType<? extends AlphaMantisEntity> entityType, Level level) {
super(entityType, level);
this.xpReward = 60;
this.summonCooldownTicks = AntarchySettings.alphaMantisSummonIntervalTicks() / 2;
}
public static AttributeSupplier.Builder createAttributes() {
return Mob.createMobAttributes()
.add(Attributes.MAX_HEALTH, AntarchySettings.alphaMantisHealth())
.add(Attributes.ATTACK_DAMAGE, AntarchySettings.alphaMantisAttackDamage())
.add(Attributes.MOVEMENT_SPEED, AntarchySettings.alphaMantisMovementSpeed())
.add(Attributes.FLYING_SPEED, AntarchySettings.alphaMantisFlyingSpeed())
.add(Attributes.FOLLOW_RANGE, 48.0D)
.add(Attributes.ARMOR, 8.0D)
.add(Attributes.KNOCKBACK_RESISTANCE, 0.8D);
}
public static boolean checkAlphaMantisSpawnRules(EntityType<AlphaMantisEntity> entityType, ServerLevelAccessor level, MobSpawnType spawnReason, BlockPos pos, RandomSource random) {
if (spawnReason == MobSpawnType.SPAWN_EGG || spawnReason == MobSpawnType.SPAWNER || spawnReason == MobSpawnType.COMMAND) {
return true;
}
if (level.getDifficulty() == Difficulty.PEACEFUL) {
return false;
}
if (spawnReason != MobSpawnType.NATURAL) {
return false;
}
boolean atSurface = level.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, pos).getY() <= pos.getY();
boolean posOpen = level.isEmptyBlock(pos) && level.isEmptyBlock(pos.above()) && level.getFluidState(pos).isEmpty();
boolean onSolidGround = level.getBlockState(pos.below()).isFaceSturdy(level, pos.below(), Direction.UP)
&& !(level.getBlockState(pos.below()).getBlock() instanceof LeavesBlock);
if (!posOpen || !onSolidGround || !atSurface) {
return false;
}
// Only one alpha at a time in the area
if (!level.getLevel().getEntitiesOfClass(AlphaMantisEntity.class, new AABB(pos).inflate(128.0D), Entity::isAlive).isEmpty()) {
return false;
}
boolean ignoreLightLevel = AntarchySettings.mantisIgnoreLightLevel();
// Daytime overworld spawns can't pass the vanilla darkness check, so no light gate here
if (level.getLevel().isDay() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_OVERWORLD_SPAWN_BIOMES)) {
return level.canSeeSky(pos);
}
if (level.getLevel().isNight() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_SPAWN_BIOMES)) {
return ignoreLightLevel || Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random);
}
return false;
}
@Override
public void tick() {
super.tick();
if (this.level().isClientSide) {
return;
}
if (this.isDeadOrDying()) {
this.bossEvent.setProgress(0.0F);
return;
}
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
this.tickMinionSummon();
}
private void tickMinionSummon() {
LivingEntity target = this.getTarget();
if (target == null || !target.isAlive()) {
return;
}
if (this.summonCooldownTicks > 0) {
this.summonCooldownTicks--;
return;
}
this.summonCooldownTicks = AntarchySettings.alphaMantisSummonIntervalTicks();
if (!(this.level() instanceof ServerLevel serverLevel)) {
return;
}
int nearbyMinions = serverLevel.getEntitiesOfClass(
MantisEntity.class,
this.getBoundingBox().inflate(32.0D),
mantis -> mantis.isAlive() && !(mantis instanceof AlphaMantisEntity)
).size();
int maxMinions = AntarchySettings.alphaMantisMaxMinions();
if (nearbyMinions >= maxMinions) {
return;
}
int toSummon = Math.min(1 + this.random.nextInt(2), maxMinions - nearbyMinions);
for (int i = 0; i < toSummon; i++) {
MantisEntity minion = AntarchyObjects.MANTIS.get().create(serverLevel);
if (minion == null) {
continue;
}
double angle = this.random.nextDouble() * Math.PI * 2.0D;
double distance = 3.0D + this.random.nextDouble() * 3.0D;
minion.moveTo(
this.getX() + Math.cos(angle) * distance,
this.getY() + 0.5D,
this.getZ() + Math.sin(angle) * distance,
this.random.nextFloat() * 360.0F,
0.0F
);
minion.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(minion.blockPosition()), MobSpawnType.MOB_SUMMONED, null);
minion.setTarget(target);
serverLevel.addFreshEntity(minion);
}
this.playSound(com.craisinlord.antarchy.content.AntarchySoundEvents.MANTIS_AMBIENT.get(), 2.0F, 0.6F);
}
@Override
public void setTarget(@Nullable LivingEntity target) {
super.setTarget(target);
// A boss that despawns mid-fight is no boss — stay loaded once engaged
if (target != null) {
this.setPersistenceRequired();
}
}
@Override
public void startSeenByPlayer(ServerPlayer player) {
super.startSeenByPlayer(player);
this.bossEvent.addPlayer(player);
}
@Override
public void stopSeenByPlayer(ServerPlayer player) {
super.stopSeenByPlayer(player);
this.bossEvent.removePlayer(player);
}
@Override
public void setCustomName(@Nullable Component name) {
super.setCustomName(name);
this.bossEvent.setName(this.getDisplayName());
}
}
@@ -71,6 +71,7 @@ public class MantisEntity extends Monster implements GeoEntity {
public MantisEntity(EntityType<? extends MantisEntity> entityType, Level level) {
super(entityType, level);
this.lookControl = new SteadyLookControl(this);
this.setNoGravity(false);
this.setPathfindingMalus(PathType.WATER, -1.0F);
this.setPathfindingMalus(PathType.WATER_BORDER, 16.0F);
@@ -117,8 +118,9 @@ public class MantisEntity extends Monster implements GeoEntity {
boolean ignoreLightLevel = AntarchySettings.mantisIgnoreLightLevel();
// Daytime overworld spawns can't pass the vanilla darkness check, so no light gate here
if (level.getLevel().isDay() && level.getBiome(pos).is(AntarchyTags.Biomes.MANTIS_OVERWORLD_SPAWN_BIOMES)) {
return atSurface && level.canSeeSky(pos) && (ignoreLightLevel || Monster.checkMonsterSpawnRules(entityType, level, spawnReason, pos, random));
return atSurface && level.canSeeSky(pos);
}
// Elythia meadow (and any future mantis_spawn_biomes): nighttime, no sky-access requirement
@@ -206,6 +208,14 @@ public class MantisEntity extends Monster implements GeoEntity {
LivingEntity target = this.getTarget();
if (target != null && target.isAlive()) {
this.getLookControl().setLookAt(target, 30.0F, 30.0F);
// If the target is horizontally inside our (wide) footprint, walking toward
// it only makes us pivot in place — hold position, attack reach covers it
double dx = target.getX() - this.getX();
double dz = target.getZ() - this.getZ();
double halfWidth = this.getBbWidth() * 0.5D;
if (!this.isFlyingNow() && dx * dx + dz * dz < halfWidth * halfWidth) {
this.getNavigation().stop();
}
} else if (this.flyBurstTicks <= 0 && this.flyCooldownTicks <= 0 && this.onGround() && this.random.nextInt(180) == 0) {
this.startFlightBurst();
}
@@ -320,6 +330,31 @@ public class MantisEntity extends Monster implements GeoEntity {
return this.flyBurstTicks > 0;
}
/**
* The mantis hitbox is several blocks wide, so a melee-range target is often
* horizontally inside the footprint. The yaw from body center to such a target
* flips wildly as the target moves past the center, which made the mantis spin
* instead of facing the player — hold the current heading in that case.
*/
private static class SteadyLookControl extends net.minecraft.world.entity.ai.control.LookControl {
SteadyLookControl(Mob mob) {
super(mob);
}
@Override
public void tick() {
if (this.lookAtCooldown > 0) {
double dx = this.wantedX - this.mob.getX();
double dz = this.wantedZ - this.mob.getZ();
double halfWidth = this.mob.getBbWidth() * 0.5D;
if (dx * dx + dz * dz < halfWidth * halfWidth) {
return;
}
}
super.tick();
}
}
private void tickDebugLog() {
if (++this.debugLogTicks < 100) {
return;
@@ -378,7 +378,7 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
player.fallDistance = 0.0F;
player.getCooldowns().addCooldown(this, TORETERROR_COOLDOWN_TICKS);
player.awardStat(Stats.ITEM_USED.get(this));
level.playSound(null, player.blockPosition(), SoundEvents.GENERIC_EXPLODE.value(), SoundSource.PLAYERS, 1.0F, 0.6F);
level.playSound(null, player.blockPosition(), AntarchySoundEvents.TORETERROR_JUMP_UP.get(), SoundSource.PLAYERS, 1.2F, 0.9F);
}
private void applyToreterrorLanding(ServerLevel level, ServerPlayer player) {
@@ -394,7 +394,7 @@ public class BigBerthaItem extends SwordItem implements GeoItem {
victim.push(normalized.x * 2.5D, 0.6D, normalized.z * 2.5D);
victim.hurtMarked = true;
}
level.playSound(null, player.blockPosition(), SoundEvents.GENERIC_EXPLODE.value(), SoundSource.PLAYERS, 1.5F, 0.75F);
level.playSound(null, player.blockPosition(), AntarchySoundEvents.TORETERROR_JUMP_LAND.get(), SoundSource.PLAYERS, 1.2F, 0.9F);
level.sendParticles(ParticleTypes.EXPLOSION, player.getX(), player.getY() + 0.5D, player.getZ(), 4, 1.5D, 0.3D, 1.5D, 0.0D);
level.sendParticles(ParticleTypes.SPLASH, player.getX(), player.getY() + 0.5D, player.getZ(), 60, 3.0D, 0.5D, 3.0D, 0.2D);
level.sendParticles(ParticleTypes.CRIT, player.getX(), player.getY() + 0.5D, player.getZ(), 20, 2.0D, 0.5D, 2.0D, 0.1D);
@@ -165,6 +165,7 @@
"entity.antarchy.moleworm": "Moleworm",
"entity.antarchy.molevore": "Molevore",
"entity.antarchy.mantis": "Mantis",
"entity.antarchy.alpha_mantis": "Alpha Mantis",
"entity.antarchy.triffid": "Triffid",
"entity.antarchy.toreterror": "Toreterror",
"entity.antarchy.water_bomb": "Water Bomb",
@@ -400,6 +401,7 @@
"item.antarchy.molevore_spawn_egg": "Molevore Spawn Egg",
"item.antarchy.reverie_spawn_egg": "Reverie Spawn Egg",
"item.antarchy.mantis_spawn_egg": "Mantis Spawn Egg",
"item.antarchy.alpha_mantis_spawn_egg": "Alpha Mantis Spawn Egg",
"biome.antarchy.moleworm_caves": "Moleworm Caves",
"biome.antarchy.butterfly_fields": "Butterfly Fields",
"biome.antarchy.torchflower_fields": "Torchflower Fields",
@@ -0,0 +1,3 @@
{
"parent": "minecraft:item/template_spawn_egg"
}
@@ -0,0 +1,90 @@
{
"type": "minecraft:entity",
"pools": [
{
"rolls": 1.0,
"entries": [
{
"type": "minecraft:item",
"name": "antarchy:mantis_claw"
}
],
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 3.0,
"max": 4.0
}
},
{
"function": "minecraft:enchanted_count_increase",
"enchantment": "minecraft:looting",
"count": {
"type": "minecraft:uniform",
"min": 0.0,
"max": 2.0
}
}
]
},
{
"rolls": 1.0,
"entries": [
{
"type": "minecraft:item",
"name": "antarchy:uranium_nugget"
}
],
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 2.0,
"max": 4.0
}
},
{
"function": "minecraft:enchanted_count_increase",
"enchantment": "minecraft:looting",
"count": {
"type": "minecraft:uniform",
"min": 0.0,
"max": 2.0
}
}
]
},
{
"rolls": 1.0,
"entries": [
{
"type": "minecraft:item",
"name": "antarchy:titanium_nugget"
}
],
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:uniform",
"min": 2.0,
"max": 4.0
}
},
{
"function": "minecraft:enchanted_count_increase",
"enchantment": "minecraft:looting",
"count": {
"type": "minecraft:uniform",
"min": 0.0,
"max": 2.0
}
}
]
}
],
"random_sequence": "antarchy:entities/alpha_mantis"
}
@@ -121,6 +121,12 @@
"weight": 20,
"minCount": 1,
"maxCount": 1
},
{
"type": "antarchy:alpha_mantis",
"weight": 1,
"minCount": 1,
"maxCount": 1
}
],
"axolotls": [],
@@ -69,7 +69,6 @@
"axolotls": [],
"underground_water_creature": [],
"water_creature": [
{ "type": "minecraft:turtle", "weight": 5, "minCount": 1, "maxCount": 2 },
{ "type": "antarchy:octopus_bomb", "weight": 4, "minCount": 1, "maxCount": 2 }],
"water_ambient": [
{ "type": "antarchy:cheep", "weight": 10, "minCount": 3, "maxCount": 6 },
@@ -8,6 +8,7 @@
"antarchy:brutalfly",
"antarchy:bed_bug",
"antarchy:mantis",
"antarchy:alpha_mantis",
"antarchy:jumpy_bug",
"antarchy:spit_bug",
"antarchy:stink_bug",