优化弹射物穿透

This commit is contained in:
Atsuishio 2025-06-18 16:52:28 +08:00 committed by Light_Quanta
parent 7db75c394b
commit f293eeb09f
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
18 changed files with 242 additions and 362 deletions

View file

@ -26,6 +26,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.level.entity.EntityTypeTest;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.event.EventHooks; import net.neoforged.neoforge.event.EventHooks;
import net.neoforged.neoforge.items.ItemHandlerHelper; import net.neoforged.neoforge.items.ItemHandlerHelper;
@ -225,6 +226,15 @@ public class Tm62Entity extends Entity implements GeoEntity, OwnableEntity {
if (trigger) { if (trigger) {
triggerExplode(); triggerExplode();
if (this.level() instanceof ServerLevel) {
AABB aabb = new AABB(position(), position()).inflate(2);
BlockPos.betweenClosedStream(aabb).forEach((blockPos) -> {
float hard = this.level().getBlockState(blockPos).getBlock().defaultDestroyTime();
if (ExplosionConfig.EXPLOSION_DESTROY.get() && hard != -1) {
this.level().destroyBlock(blockPos, true);
}
});
}
} }
} }
} }

View file

@ -29,7 +29,6 @@ import net.minecraft.world.entity.projectile.ThrownPotion;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@ -54,15 +53,17 @@ public class Agm65Entity extends FastThrowableProjectile implements GeoEntity, E
private float explosionDamage = ExplosionConfig.AGM_65_EXPLOSION_DAMAGE.get(); private float explosionDamage = ExplosionConfig.AGM_65_EXPLOSION_DAMAGE.get();
private float explosionRadius = ExplosionConfig.AGM_65_EXPLOSION_RADIUS.get().floatValue(); private float explosionRadius = ExplosionConfig.AGM_65_EXPLOSION_RADIUS.get().floatValue();
private boolean distracted = false; private boolean distracted = false;
private int durability = 100; private int durability = 50;
public Agm65Entity(EntityType<? extends Agm65Entity> type, Level world) { public Agm65Entity(EntityType<? extends Agm65Entity> type, Level world) {
super(type, world); super(type, world);
this.noCulling = true; this.noCulling = true;
this.durability = 25;
} }
public Agm65Entity(LivingEntity entity, Level level) { public Agm65Entity(LivingEntity entity, Level level) {
super(ModEntities.AGM_65.get(), entity, level); super(ModEntities.AGM_65.get(), entity, level);
this.durability = 25;
} }
public void setTargetUuid(String uuid) { public void setTargetUuid(String uuid) {
@ -163,12 +164,7 @@ public class Agm65Entity extends FastThrowableProjectile implements GeoEntity, E
entity.invulnerableTime = 0; entity.invulnerableTime = 0;
} }
for (int i = 0; i < 5; i++) { causeExplode(result.getLocation());
causeExplode(result.getLocation().add(getDeltaMovement().normalize().scale(i)), this.explosionRadius * 0.5f, false);
}
causeExplode(result.getLocation(), this.explosionRadius, true);
this.discard();
} }
} }
@ -176,42 +172,20 @@ public class Agm65Entity extends FastThrowableProjectile implements GeoEntity, E
public void onHitBlock(@NotNull BlockHitResult blockHitResult) { public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos(); BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime(); float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) {
if (hardness == -1) {
this.discard();
causeExplode(blockHitResult.getLocation(), this.explosionRadius, true);
return;
} else {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) { if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true); this.level().destroyBlock(resultPos, true);
} }
} }
if (!ExplosionConfig.EXPLOSION_DESTROY.get()) {
causeExplode(blockHitResult.getLocation(), this.explosionRadius, true); causeExplode(blockHitResult.getLocation());
this.discard();
for (int i = 0; i < 8; i++) {
Vec3 hitPos = blockHitResult.getLocation().add(getDeltaMovement().normalize().scale(i));
AABB aabb = new AABB(hitPos, hitPos).inflate(0.25);
if (durability > 0) {
BlockPos.betweenClosedStream(aabb).forEach((pos) -> {
float hard = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
durability -= (int) hard;
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(pos, true);
}
causeExplode(hitPos, this.explosionRadius * 0.5f, false);
});
}
}
if (durability <= 0) {
discard();
} }
} }
} }
private void causeExplode(Vec3 vec3, float radius, boolean isHuge) { private void causeExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this, CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
this, this,
@ -220,17 +194,18 @@ public class Agm65Entity extends FastThrowableProjectile implements GeoEntity, E
vec3.x, vec3.x,
vec3.y, vec3.y,
vec3.z, vec3.z,
radius, explosionRadius,
ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP, true). ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP, true).
setDamageMultiplier(1); setDamageMultiplier(1);
explosion.explode(); explosion.explode();
EventHooks.onExplosionStart(this.level(), explosion); EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
if (isHuge) { if (explosionRadius > 9) {
ParticleTool.spawnHugeExplosionParticles(this.level(), vec3); ParticleTool.spawnHugeExplosionParticles(this.level(), vec3);
} else { } else {
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3); ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
} }
discard();
} }
@Override @Override
@ -294,6 +269,13 @@ public class Agm65Entity extends FastThrowableProjectile implements GeoEntity, E
float f = (float) Mth.clamp(1 - 0.005 * getDeltaMovement().length(), 0.001, 1); float f = (float) Mth.clamp(1 - 0.005 * getDeltaMovement().length(), 0.001, 1);
this.setDeltaMovement(this.getDeltaMovement().multiply(f, f, f)); this.setDeltaMovement(this.getDeltaMovement().multiply(f, f, f));
destroyBlock();
}
@Override
public void destroy(Vec3 pos) {
causeExplode(pos);
} }
@Override @Override

View file

@ -414,13 +414,12 @@ public class C4Entity extends Entity implements GeoEntity, OwnableEntity {
} }
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
AABB aabb = new AABB(pos, pos).inflate(3); AABB aabb = new AABB(pos, pos).inflate(2);
BlockPos.betweenClosedStream(aabb).forEach((blockPos) -> { BlockPos.betweenClosedStream(aabb).forEach((blockPos) -> {
float hard = this.level().getBlockState(blockPos).getBlock().defaultDestroyTime(); float hard = this.level().getBlockState(blockPos).getBlock().defaultDestroyTime();
if (ExplosionConfig.EXPLOSION_DESTROY.get() && hard != -1 && new Vec3(blockPos.getX(), blockPos.getY(), blockPos.getZ()).distanceTo(position()) < 2) { if (ExplosionConfig.EXPLOSION_DESTROY.get() && hard != -1) {
this.level().destroyBlock(blockPos, true); this.level().destroyBlock(blockPos, true);
} }
}); });
} }

View file

@ -25,7 +25,7 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@ -37,6 +37,7 @@ import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.animation.*; import software.bernie.geckolib.animation.*;
import software.bernie.geckolib.util.GeckoLibUtil; import software.bernie.geckolib.util.GeckoLibUtil;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -49,7 +50,6 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
private float explosionDamage = 0; private float explosionDamage = 0;
private float fireProbability = 0; private float fireProbability = 0;
private int fireTime = 0; private int fireTime = 0;
private int durability = 40;
public Set<Long> loadedChunks = new HashSet<>(); public Set<Long> loadedChunks = new HashSet<>();
private float gravity = 0.1f; private float gravity = 0.1f;
@ -73,6 +73,12 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
return this; return this;
} }
@Override
@ParametersAreNonnullByDefault
public boolean isColliding(BlockPos pPos, BlockState pState) {
return true;
}
@Override @Override
public void addAdditionalSaveData(@NotNull CompoundTag pCompound) { public void addAdditionalSaveData(@NotNull CompoundTag pCompound) {
super.addAdditionalSaveData(pCompound); super.addAdditionalSaveData(pCompound);
@ -140,6 +146,23 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
return true; return true;
} }
@Override
public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true);
}
}
if (!ExplosionConfig.EXPLOSION_DESTROY.get()) {
causeExplode(blockHitResult.getLocation());
this.discard();
}
}
}
@Override @Override
public void onHitEntity(@NotNull EntityHitResult entityHitResult) { public void onHitEntity(@NotNull EntityHitResult entityHitResult) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
@ -161,7 +184,7 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
} }
ParticleTool.cannonHitParticles(this.level(), this.position(), this); ParticleTool.cannonHitParticles(this.level(), this.position(), this);
causeExplode(entityHitResult.getLocation(), this.radius, true); causeExplode(entityHitResult.getLocation());
if (entity instanceof VehicleEntity) { if (entity instanceof VehicleEntity) {
this.discard(); this.discard();
} }
@ -169,45 +192,6 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
} }
} }
@Override
public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness == -1) {
this.discard();
causeExplode(blockHitResult.getLocation(), this.radius, true);
return;
} else {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true);
}
}
causeExplode(blockHitResult.getLocation(), this.radius, true);
for (int i = 0; i < 5; i++) {
Vec3 hitPos = blockHitResult.getLocation().add(getDeltaMovement().normalize().scale(i));
AABB aabb = new AABB(hitPos, hitPos).inflate(0.25);
if (durability > 0) {
BlockPos.betweenClosedStream(aabb).forEach((pos) -> {
float hard = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
durability -= (int) hard;
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(pos, true);
}
causeExplode(hitPos, this.radius * 0.5f, false);
});
}
}
if (durability <= 0) {
discard();
}
}
}
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
@ -218,9 +202,12 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
// 更新需要加载的区块 // 更新需要加载的区块
ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks); ChunkLoadTool.updateLoadedChunks(serverLevel, this, this.loadedChunks);
} }
destroyBlock();
if (this.tickCount > 600 || this.isInWater()) { if (this.tickCount > 600 || this.isInWater()) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
causeExplode(position(), this.radius, true); causeExplode(position());
} }
this.discard(); this.discard();
} }
@ -233,7 +220,12 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
} }
} }
private void causeExplode(Vec3 vec3, float radius, boolean isHuge) { @Override
public void destroy(Vec3 pos) {
causeExplode(pos);
}
private void causeExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this, CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
this, this,
@ -248,11 +240,12 @@ public class CannonShellEntity extends FastThrowableProjectile implements GeoEnt
explosion.explode(); explosion.explode();
EventHooks.onExplosionStart(this.level(), explosion); EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
if (isHuge) { if (radius > 9) {
ParticleTool.spawnHugeExplosionParticles(this.level(), vec3); ParticleTool.spawnHugeExplosionParticles(this.level(), vec3);
} else { } else {
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3); ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
} }
discard();
} }
private PlayState movementPredicate(AnimationState<CannonShellEntity> event) { private PlayState movementPredicate(AnimationState<CannonShellEntity> event) {

View file

@ -1,21 +1,29 @@
package com.atsuishio.superbwarfare.entity.projectile; package com.atsuishio.superbwarfare.entity.projectile;
import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
import com.atsuishio.superbwarfare.network.message.receive.ClientMotionSyncMessage; import com.atsuishio.superbwarfare.network.message.receive.ClientMotionSyncMessage;
import net.minecraft.core.BlockPos;
import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.ThrowableItemProjectile; import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.entity.IEntityWithComplexSpawn; import net.neoforged.neoforge.entity.IEntityWithComplexSpawn;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import static com.atsuishio.superbwarfare.tools.TraceTool.getBlocksAlongRay;
public abstract class FastThrowableProjectile extends ThrowableItemProjectile implements CustomSyncMotionEntity, IEntityWithComplexSpawn { public abstract class FastThrowableProjectile extends ThrowableItemProjectile implements CustomSyncMotionEntity, IEntityWithComplexSpawn {
public static Consumer<FastThrowableProjectile> flySound = projectile -> { public static Consumer<FastThrowableProjectile> flySound = projectile -> {
@ -23,6 +31,8 @@ public abstract class FastThrowableProjectile extends ThrowableItemProjectile im
public static Consumer<FastThrowableProjectile> nearFlySound = projectile -> { public static Consumer<FastThrowableProjectile> nearFlySound = projectile -> {
}; };
public int durability = 50;
private boolean isFastMoving = false; private boolean isFastMoving = false;
public FastThrowableProjectile(EntityType<? extends ThrowableItemProjectile> pEntityType, Level pLevel) { public FastThrowableProjectile(EntityType<? extends ThrowableItemProjectile> pEntityType, Level pLevel) {
@ -69,6 +79,35 @@ public abstract class FastThrowableProjectile extends ThrowableItemProjectile im
this.syncMotion(); this.syncMotion();
} }
public void destroyBlock() {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
Vec3 posO = new Vec3(xo, yo, zo);
List<BlockPos> blockList = getBlocksAlongRay(posO, getDeltaMovement(), getDeltaMovement().length());
for (BlockPos pos : blockList) {
BlockState blockState = level().getBlockState(pos);
if (!blockState.is(Blocks.AIR)) {
float hardness = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
double resistance = 1 - Mth.clamp(hardness / 100, 0, 0.8);
setDeltaMovement(getDeltaMovement().multiply(resistance, resistance, resistance));
durability -= 10 + (int) (0.5 * hardness);
if (hardness <= durability && hardness != -1) {
this.level().destroyBlock(pos, true);
}
if (hardness == -1 || hardness > durability || durability <= 0) {
destroy(pos.getCenter());
break;
}
}
}
}
}
public void destroy(Vec3 pos) {
}
@Override @Override
public void syncMotion() { public void syncMotion() {
if (this.level().isClientSide) return; if (this.level().isClientSide) return;

View file

@ -1,6 +1,5 @@
package com.atsuishio.superbwarfare.entity.projectile; package com.atsuishio.superbwarfare.entity.projectile;
import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModEntities; import com.atsuishio.superbwarfare.init.ModEntities;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
@ -156,15 +155,6 @@ public class GunGrenadeEntity extends FastThrowableProjectile implements GeoEnti
BlockPos resultPos = blockHitResult.getBlockPos(); BlockPos resultPos = blockHitResult.getBlockPos();
BlockState state = this.level().getBlockState(resultPos); BlockState state = this.level().getBlockState(resultPos);
if (this.level() instanceof ServerLevel) {
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true);
}
}
}
if (state.getBlock() instanceof BellBlock bell) { if (state.getBlock() instanceof BellBlock bell) {
bell.attemptToRing(this.level(), resultPos, blockHitResult.getDirection()); bell.attemptToRing(this.level(), resultPos, blockHitResult.getDirection());
} }

View file

@ -23,7 +23,6 @@ import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@ -44,8 +43,6 @@ public class HeliRocketEntity extends FastThrowableProjectile implements GeoEnti
private float explosionDamage = 60f; private float explosionDamage = 60f;
private float explosionRadius = 5f; private float explosionRadius = 5f;
private int durability = 50;
public HeliRocketEntity(EntityType<? extends HeliRocketEntity> type, Level world) { public HeliRocketEntity(EntityType<? extends HeliRocketEntity> type, Level world) {
super(type, world); super(type, world);
this.noCulling = true; this.noCulling = true;
@ -54,6 +51,7 @@ public class HeliRocketEntity extends FastThrowableProjectile implements GeoEnti
public HeliRocketEntity(EntityType<? extends ThrowableItemProjectile> pEntityType, double pX, double pY, double pZ, Level pLevel) { public HeliRocketEntity(EntityType<? extends ThrowableItemProjectile> pEntityType, double pX, double pY, double pZ, Level pLevel) {
super(pEntityType, pX, pY, pZ, pLevel); super(pEntityType, pX, pY, pZ, pLevel);
this.noCulling = true; this.noCulling = true;
this.durability = 20;
} }
public HeliRocketEntity(LivingEntity entity, Level level, float damage, float explosionDamage, float explosionRadius) { public HeliRocketEntity(LivingEntity entity, Level level, float damage, float explosionDamage, float explosionRadius) {
@ -61,6 +59,7 @@ public class HeliRocketEntity extends FastThrowableProjectile implements GeoEnti
this.damage = damage; this.damage = damage;
this.explosionDamage = explosionDamage; this.explosionDamage = explosionDamage;
this.explosionRadius = explosionRadius; this.explosionRadius = explosionRadius;
this.durability = 20;
} }
@Override @Override
@ -117,10 +116,6 @@ public class HeliRocketEntity extends FastThrowableProjectile implements GeoEnti
entity.invulnerableTime = 0; entity.invulnerableTime = 0;
} }
for (int i = 0; i < 3; i++) {
apExplode(result.getLocation().add(getDeltaMovement().normalize().scale(i)));
}
causeExplode(result.getLocation()); causeExplode(result.getLocation());
this.discard(); this.discard();
} }
@ -130,37 +125,15 @@ public class HeliRocketEntity extends FastThrowableProjectile implements GeoEnti
public void onHitBlock(@NotNull BlockHitResult blockHitResult) { public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos(); BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime(); float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) {
if (hardness == -1) {
this.discard();
causeExplode(blockHitResult.getLocation());
return;
} else {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) { if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true); this.level().destroyBlock(resultPos, true);
} }
} }
if (!ExplosionConfig.EXPLOSION_DESTROY.get()) {
causeExplode(blockHitResult.getLocation()); causeExplode(blockHitResult.getLocation());
this.discard();
for (int i = 0; i < 3; i++) {
Vec3 hitPos = blockHitResult.getLocation().add(getDeltaMovement().normalize().scale(i));
AABB aabb = new AABB(hitPos, hitPos).inflate(0.25);
if (durability > 0) {
BlockPos.betweenClosedStream(aabb).forEach((pos) -> {
float hard = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
durability -= (int) hard;
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(pos, true);
}
apExplode(hitPos);
});
}
}
if (durability <= 0) {
discard();
} }
} }
} }
@ -181,25 +154,9 @@ public class HeliRocketEntity extends FastThrowableProjectile implements GeoEnti
EventHooks.onExplosionStart(this.level(), explosion); EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
ParticleTool.spawnHugeExplosionParticles(this.level(), vec3); ParticleTool.spawnHugeExplosionParticles(this.level(), vec3);
discard();
} }
private void apExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
this,
this.getOwner()),
explosionDamage,
vec3.x,
vec3.y,
vec3.z,
explosionRadius * 0.5f,
ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP, true).
setDamageMultiplier(1);
explosion.explode();
EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false);
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
}
@Override @Override
public void tick() { public void tick() {
@ -224,6 +181,12 @@ public class HeliRocketEntity extends FastThrowableProjectile implements GeoEnti
} }
this.discard(); this.discard();
} }
destroyBlock();
}
@Override
public void destroy(Vec3 pos) {
causeExplode(pos);
} }
public static void causeRocketExplode(ThrowableItemProjectile projectile, @Nullable DamageSource source, Entity target, float damage, float radius, float damageMultiplier) { public static void causeRocketExplode(ThrowableItemProjectile projectile, @Nullable DamageSource source, Entity target, float damage, float radius, float damageMultiplier) {

View file

@ -30,7 +30,6 @@ import net.minecraft.world.entity.projectile.ThrownPotion;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@ -60,8 +59,6 @@ public class JavelinMissileEntity extends FastThrowableProjectile implements Geo
private boolean distracted = false; private boolean distracted = false;
private int guideType = 0; private int guideType = 0;
private int durability = 70;
public JavelinMissileEntity(EntityType<? extends JavelinMissileEntity> type, Level world) { public JavelinMissileEntity(EntityType<? extends JavelinMissileEntity> type, Level world) {
super(type, world); super(type, world);
this.noCulling = true; this.noCulling = true;
@ -76,6 +73,7 @@ public class JavelinMissileEntity extends FastThrowableProjectile implements Geo
this.entityData.set(TARGET_X, (float) targetPos.x); this.entityData.set(TARGET_X, (float) targetPos.x);
this.entityData.set(TARGET_Y, (float) targetPos.y); this.entityData.set(TARGET_Y, (float) targetPos.y);
this.entityData.set(TARGET_Z, (float) targetPos.z); this.entityData.set(TARGET_Z, (float) targetPos.z);
this.durability = 35;
} }
public void setMonsterMultiplier(float monsterMultiplier) { public void setMonsterMultiplier(float monsterMultiplier) {
@ -198,50 +196,24 @@ public class JavelinMissileEntity extends FastThrowableProjectile implements Geo
entity.invulnerableTime = 0; entity.invulnerableTime = 0;
} }
for (int i = 0; i < 3; i++) {
apExplode(result.getLocation().add(getDeltaMovement().normalize().scale(i)));
}
causeExplode(result.getLocation()); causeExplode(result.getLocation());
this.discard(); this.discard();
} }
} }
@Override @Override
public void onHitBlock(BlockHitResult blockHitResult) { public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos(); BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime(); float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) {
if (hardness == -1) {
this.discard();
causeExplode(blockHitResult.getLocation());
return;
} else {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) { if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true); this.level().destroyBlock(resultPos, true);
} }
} }
if (!ExplosionConfig.EXPLOSION_DESTROY.get()) {
causeExplode(blockHitResult.getLocation()); causeExplode(blockHitResult.getLocation());
this.discard();
for (int i = 0; i < 3; i++) {
Vec3 hitPos = blockHitResult.getLocation().add(getDeltaMovement().normalize().scale(i));
AABB aabb = new AABB(hitPos, hitPos).inflate(0.25);
if (durability > 0) {
BlockPos.betweenClosedStream(aabb).forEach((pos) -> {
float hard = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
durability -= (int) hard;
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(pos, true);
}
apExplode(hitPos);
});
}
}
if (durability <= 0) {
discard();
} }
} }
} }
@ -262,24 +234,7 @@ public class JavelinMissileEntity extends FastThrowableProjectile implements Geo
EventHooks.onExplosionStart(this.level(), explosion); EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
ParticleTool.spawnHugeExplosionParticles(this.level(), vec3); ParticleTool.spawnHugeExplosionParticles(this.level(), vec3);
} discard();
private void apExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
this,
this.getOwner()),
explosionDamage,
vec3.x,
vec3.y,
vec3.z,
explosionRadius * 0.5f,
ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP, true).
setDamageMultiplier(this.monsterMultiplier);
explosion.explode();
EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false);
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
} }
@Override @Override
@ -400,6 +355,12 @@ public class JavelinMissileEntity extends FastThrowableProjectile implements Geo
} }
this.setDeltaMovement(this.getDeltaMovement().multiply(0.96, 0.96, 0.96)); this.setDeltaMovement(this.getDeltaMovement().multiply(0.96, 0.96, 0.96));
destroyBlock();
}
@Override
public void destroy(Vec3 pos) {
causeExplode(pos);
} }
private PlayState movementPredicate(AnimationState<JavelinMissileEntity> event) { private PlayState movementPredicate(AnimationState<JavelinMissileEntity> event) {

View file

@ -5,7 +5,6 @@ import com.atsuishio.superbwarfare.init.ModEntities;
import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.tools.ProjectileTool; import com.atsuishio.superbwarfare.tools.ProjectileTool;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.EntityDataSerializers;
@ -21,9 +20,7 @@ import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.entity.projectile.ThrownPotion; import net.minecraft.world.entity.projectile.ThrownPotion;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import software.bernie.geckolib.animatable.GeoEntity; import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache; import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
@ -38,6 +35,8 @@ public class Mk82Entity extends FastThrowableProjectile implements GeoEntity, Ex
private float explosionDamage = ExplosionConfig.MK_82_EXPLOSION_DAMAGE.get(); private float explosionDamage = ExplosionConfig.MK_82_EXPLOSION_DAMAGE.get();
private float explosionRadius = ExplosionConfig.MK_82_EXPLOSION_RADIUS.get().floatValue(); private float explosionRadius = ExplosionConfig.MK_82_EXPLOSION_RADIUS.get().floatValue();
public int durability = 1;
public Mk82Entity(EntityType<? extends Mk82Entity> type, Level world) { public Mk82Entity(EntityType<? extends Mk82Entity> type, Level world) {
super(type, world); super(type, world);
this.noCulling = true; this.noCulling = true;
@ -114,24 +113,16 @@ public class Mk82Entity extends FastThrowableProjectile implements GeoEntity, Ex
} }
@Override @Override
public boolean shouldRenderAtSqrDistance(double pDistance) { public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
return true; if (this.level() instanceof ServerLevel) {
ProjectileTool.causeCustomExplode(this, this.explosionDamage, this.explosionRadius, 1.2f);
}
this.discard();
} }
@Override @Override
public void onHitBlock(@NotNull BlockHitResult blockHitResult) { public boolean shouldRenderAtSqrDistance(double pDistance) {
if (this.level() instanceof ServerLevel) { return true;
AABB aabb = new AABB(blockHitResult.getLocation(), blockHitResult.getLocation()).inflate(5);
BlockPos.betweenClosedStream(aabb).forEach((pos) -> {
float hard = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
if (ExplosionConfig.EXPLOSION_DESTROY.get() && hard != -1 && new Vec3(pos.getX(), pos.getY(), pos.getZ()).distanceTo(blockHitResult.getLocation()) < 3) {
this.level().destroyBlock(pos, true);
}
});
ProjectileTool.causeCustomExplode(this, this.explosionDamage, this.explosionRadius, 1.2f);
this.discard();
}
} }
@Override @Override

View file

@ -24,7 +24,6 @@ import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@ -46,31 +45,22 @@ public class RpgRocketEntity extends FastThrowableProjectile implements GeoEntit
private float explosionDamage = 200f; private float explosionDamage = 200f;
private float explosionRadius = 10; private float explosionRadius = 10;
private int durability = 50;
public RpgRocketEntity(EntityType<? extends RpgRocketEntity> type, Level world) { public RpgRocketEntity(EntityType<? extends RpgRocketEntity> type, Level world) {
super(type, world); super(type, world);
this.noCulling = true; this.noCulling = true;
this.durability = 20;
} }
public RpgRocketEntity(EntityType<? extends ThrowableItemProjectile> pEntityType, double pX, double pY, double pZ, Level pLevel) { public RpgRocketEntity(EntityType<? extends ThrowableItemProjectile> pEntityType, double pX, double pY, double pZ, Level pLevel) {
super(pEntityType, pX, pY, pZ, pLevel); super(pEntityType, pX, pY, pZ, pLevel);
this.noCulling = true; this.noCulling = true;
this.durability = 20;
} }
public RpgRocketEntity(LivingEntity entity, Level level) { public RpgRocketEntity(LivingEntity entity, Level level) {
super(ModEntities.RPG_ROCKET.get(), entity, level); super(ModEntities.RPG_ROCKET.get(), entity, level);
} this.durability = 2;
public RpgRocketEntity(LivingEntity entity, Level level, float damage) {
this(entity, level);
this.damage = damage;
}
public RpgRocketEntity(LivingEntity entity, Level level, float damage, float explosionDamage, float explosionRadius) {
this(entity, level, damage);
this.explosionDamage = explosionDamage;
this.explosionRadius = explosionRadius;
} }
@ -126,6 +116,23 @@ public class RpgRocketEntity extends FastThrowableProjectile implements GeoEntit
return true; return true;
} }
@Override
public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true);
}
}
if (!ExplosionConfig.EXPLOSION_DESTROY.get()) {
causeExplode(blockHitResult.getLocation());
this.discard();
}
}
}
@Override @Override
protected void onHitEntity(EntityHitResult result) { protected void onHitEntity(EntityHitResult result) {
float damageMultiplier = 1 + this.monsterMultiplier; float damageMultiplier = 1 + this.monsterMultiplier;
@ -153,54 +160,11 @@ public class RpgRocketEntity extends FastThrowableProjectile implements GeoEntit
entity.invulnerableTime = 0; entity.invulnerableTime = 0;
} }
for (int i = 0; i < 5; i++) {
apExplode(result.getLocation().add(getDeltaMovement().normalize().scale(i)));
}
causeExplode(result.getLocation()); causeExplode(result.getLocation());
this.discard(); this.discard();
} }
} }
@Override
public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness == -1) {
this.discard();
causeExplode(blockHitResult.getLocation());
return;
} else {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true);
}
}
causeExplode(blockHitResult.getLocation());
for (int i = 0; i < 5; i++) {
Vec3 hitPos = blockHitResult.getLocation().add(getDeltaMovement().normalize().scale(i));
AABB aabb = new AABB(hitPos, hitPos).inflate(0.25);
if (durability > 0) {
BlockPos.betweenClosedStream(aabb).forEach((pos) -> {
float hard = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
durability -= (int) hard;
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(pos, true);
}
apExplode(hitPos);
});
}
}
if (durability <= 0) {
discard();
}
}
}
private void causeExplode(Vec3 vec3) { private void causeExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this, CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
@ -217,24 +181,7 @@ public class RpgRocketEntity extends FastThrowableProjectile implements GeoEntit
EventHooks.onExplosionStart(this.level(), explosion); EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
ParticleTool.spawnHugeExplosionParticles(this.level(), vec3); ParticleTool.spawnHugeExplosionParticles(this.level(), vec3);
} discard();
private void apExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
this,
this.getOwner()),
explosionDamage,
vec3.x,
vec3.y,
vec3.z,
explosionRadius * 0.5f,
ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP, true).
setDamageMultiplier(this.monsterMultiplier);
explosion.explode();
EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false);
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
} }
@Override @Override
@ -261,6 +208,12 @@ public class RpgRocketEntity extends FastThrowableProjectile implements GeoEntit
} }
this.discard(); this.discard();
} }
destroyBlock();
}
@Override
public void destroy(Vec3 pos) {
causeExplode(pos);
} }
private PlayState movementPredicate(AnimationState<RpgRocketEntity> event) { private PlayState movementPredicate(AnimationState<RpgRocketEntity> event) {

View file

@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource; import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
@ -62,7 +63,7 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
} }
@Override @Override
public void addAdditionalSaveData(CompoundTag pCompound) { public void addAdditionalSaveData(@NotNull CompoundTag pCompound) {
super.addAdditionalSaveData(pCompound); super.addAdditionalSaveData(pCompound);
pCompound.putFloat("Damage", this.damage); pCompound.putFloat("Damage", this.damage);
pCompound.putFloat("ExplosionDamage", this.explosionDamage); pCompound.putFloat("ExplosionDamage", this.explosionDamage);
@ -70,7 +71,7 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
} }
@Override @Override
public void readAdditionalSaveData(CompoundTag pCompound) { public void readAdditionalSaveData(@NotNull CompoundTag pCompound) {
super.readAdditionalSaveData(pCompound); super.readAdditionalSaveData(pCompound);
if (pCompound.contains("Damage")) { if (pCompound.contains("Damage")) {
this.damage = pCompound.getFloat("Damage"); this.damage = pCompound.getFloat("Damage");
@ -129,7 +130,10 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime(); float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) { if (hardness != -1) {
if (ExplosionConfig.EXPLOSION_DESTROY.get() && this.blockInteraction == null) { if (ExplosionConfig.EXPLOSION_DESTROY.get() && this.blockInteraction == null) {
this.level().destroyBlock(resultPos, true); boolean destroy = Math.random() < Mth.clamp(1 - (hardness / 50), 0.1, 1);
if (destroy) {
this.level().destroyBlock(resultPos, true);
}
} }
} }
} }

View file

@ -31,7 +31,6 @@ import net.minecraft.world.item.Item;
import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@ -52,8 +51,6 @@ public class WgMissileEntity extends FastThrowableProjectile implements GeoEntit
private float explosionDamage = 200f; private float explosionDamage = 200f;
private float explosionRadius = 10f; private float explosionRadius = 10f;
private int durability = 70;
public WgMissileEntity(EntityType<? extends WgMissileEntity> type, Level level) { public WgMissileEntity(EntityType<? extends WgMissileEntity> type, Level level) {
super(type, level); super(type, level);
this.noCulling = true; this.noCulling = true;
@ -64,6 +61,7 @@ public class WgMissileEntity extends FastThrowableProjectile implements GeoEntit
this.damage = damage; this.damage = damage;
this.explosionDamage = explosionDamage; this.explosionDamage = explosionDamage;
this.explosionRadius = explosionRadius; this.explosionRadius = explosionRadius;
this.durability = 25;
} }
@Override @Override
@ -134,6 +132,23 @@ public class WgMissileEntity extends FastThrowableProjectile implements GeoEntit
return true; return true;
} }
@Override
public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness != -1) {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true);
}
}
if (!ExplosionConfig.EXPLOSION_DESTROY.get()) {
causeExplode(blockHitResult.getLocation());
this.discard();
}
}
}
@Override @Override
protected void onHitEntity(EntityHitResult result) { protected void onHitEntity(EntityHitResult result) {
Entity entity = result.getEntity(); Entity entity = result.getEntity();
@ -156,54 +171,11 @@ public class WgMissileEntity extends FastThrowableProjectile implements GeoEntit
entity.invulnerableTime = 0; entity.invulnerableTime = 0;
} }
for (int i = 0; i < 5; i++) {
apExplode(result.getLocation().add(getDeltaMovement().normalize().scale(i)));
}
causeExplode(result.getLocation()); causeExplode(result.getLocation());
this.discard(); this.discard();
} }
} }
@Override
public void onHitBlock(@NotNull BlockHitResult blockHitResult) {
if (this.level() instanceof ServerLevel) {
BlockPos resultPos = blockHitResult.getBlockPos();
float hardness = this.level().getBlockState(resultPos).getBlock().defaultDestroyTime();
if (hardness == -1) {
this.discard();
causeExplode(blockHitResult.getLocation());
return;
} else {
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(resultPos, true);
}
}
causeExplode(blockHitResult.getLocation());
for (int i = 0; i < 5; i++) {
Vec3 hitPos = blockHitResult.getLocation().add(getDeltaMovement().normalize().scale(i));
AABB aabb = new AABB(hitPos, hitPos).inflate(0.25);
if (durability > 0) {
BlockPos.betweenClosedStream(aabb).forEach((pos) -> {
float hard = this.level().getBlockState(pos).getBlock().defaultDestroyTime();
durability -= (int) hard;
if (ExplosionConfig.EXPLOSION_DESTROY.get()) {
this.level().destroyBlock(pos, true);
}
apExplode(hitPos);
});
}
}
if (durability <= 0) {
discard();
}
}
}
private void causeExplode(Vec3 vec3) { private void causeExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this, CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
@ -222,24 +194,6 @@ public class WgMissileEntity extends FastThrowableProjectile implements GeoEntit
ParticleTool.spawnHugeExplosionParticles(this.level(), vec3); ParticleTool.spawnHugeExplosionParticles(this.level(), vec3);
} }
private void apExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
this,
this.getOwner()),
explosionDamage,
vec3.x,
vec3.y,
vec3.z,
explosionRadius * 0.5f,
ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP, true).
setDamageMultiplier(1);
explosion.explode();
EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false);
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
}
@Override @Override
public void tick() { public void tick() {
super.tick(); super.tick();
@ -286,8 +240,14 @@ public class WgMissileEntity extends FastThrowableProjectile implements GeoEntit
} }
this.discard(); this.discard();
} }
destroyBlock();
} }
@Override
public void destroy(Vec3 pos) {
causeExplode(pos);
discard();
}
private PlayState movementPredicate(AnimationState<WgMissileEntity> event) { private PlayState movementPredicate(AnimationState<WgMissileEntity> event) {
return event.setAndContinue(RawAnimation.begin().thenLoop("animation.jvm.idle")); return event.setAndContinue(RawAnimation.begin().thenLoop("animation.jvm.idle"));

View file

@ -92,7 +92,7 @@ public class Mk42Entity extends VehicleEntity implements GeoEntity, CannonEntity
.hitDamage(VehicleConfig.MK42_HE_DAMAGE.get()) .hitDamage(VehicleConfig.MK42_HE_DAMAGE.get())
.explosionDamage(VehicleConfig.MK42_HE_EXPLOSION_DAMAGE.get()) .explosionDamage(VehicleConfig.MK42_HE_EXPLOSION_DAMAGE.get())
.explosionRadius(VehicleConfig.MK42_HE_EXPLOSION_RADIUS.get().floatValue()) .explosionRadius(VehicleConfig.MK42_HE_EXPLOSION_RADIUS.get().floatValue())
.durability(0) .durability(1)
.fireProbability(0.18F) .fireProbability(0.18F)
.fireTime(2) .fireTime(2)
.gravity(shellGravity) .gravity(shellGravity)

View file

@ -84,7 +84,7 @@ public class Mle1934Entity extends VehicleEntity implements GeoEntity, CannonEnt
.hitDamage(VehicleConfig.MLE1934_HE_DAMAGE.get()) .hitDamage(VehicleConfig.MLE1934_HE_DAMAGE.get())
.explosionDamage(VehicleConfig.MLE1934_HE_EXPLOSION_DAMAGE.get()) .explosionDamage(VehicleConfig.MLE1934_HE_EXPLOSION_DAMAGE.get())
.explosionRadius(VehicleConfig.MLE1934_HE_EXPLOSION_RADIUS.get().floatValue()) .explosionRadius(VehicleConfig.MLE1934_HE_EXPLOSION_RADIUS.get().floatValue())
.durability(0) .durability(1)
.fireProbability(0.24F) .fireProbability(0.24F)
.fireTime(5) .fireTime(5)
.gravity(shellGravity) .gravity(shellGravity)

View file

@ -133,7 +133,7 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
.explosionDamage(VehicleConfig.YX_100_HE_CANNON_EXPLOSION_DAMAGE.get()) .explosionDamage(VehicleConfig.YX_100_HE_CANNON_EXPLOSION_DAMAGE.get())
.fireProbability(0.18F) .fireProbability(0.18F)
.fireTime(2) .fireTime(2)
.durability(0) .durability(1)
.velocity(25) .velocity(25)
.gravity(0.1f) .gravity(0.1f)
.sound(ModSounds.INTO_CANNON.get()) .sound(ModSounds.INTO_CANNON.get())

View file

@ -159,7 +159,7 @@ public class JavelinItem extends GunItem {
Entity seekingEntity = SeekTool.seekEntity(player, player.level(), 512, 8); Entity seekingEntity = SeekTool.seekEntity(player, player.level(), 512, 8);
if (seekingEntity.getType().is(ModTags.EntityTypes.DECOY)) { if (seekingEntity != null && seekingEntity.getType().is(ModTags.EntityTypes.DECOY)) {
tag.putInt("SeekTime", 0); tag.putInt("SeekTime", 0);
} }
} }

View file

@ -12,6 +12,9 @@ import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.*; import net.minecraft.world.phys.*;
import java.util.ArrayList;
import java.util.List;
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter; import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
public class TraceTool { public class TraceTool {
@ -175,4 +178,36 @@ public class TraceTool {
Vec3 vec32 = pos.add(vec31.x * pHitDistance, vec31.y * pHitDistance, vec31.z * pHitDistance); Vec3 vec32 = pos.add(vec31.x * pHitDistance, vec31.y * pHitDistance, vec31.z * pHitDistance);
return vehicle.level().clip(new ClipContext(pos, vec32, ClipContext.Block.COLLIDER, ClipContext.Fluid.ANY, vehicle)); return vehicle.level().clip(new ClipContext(pos, vec32, ClipContext.Block.COLLIDER, ClipContext.Fluid.ANY, vehicle));
} }
public static List<BlockPos> getBlocksAlongRay(Vec3 start, Vec3 direction, double maxDistance) {
List<BlockPos> blocks = new ArrayList<>();
// 标准化方向向量
Vec3 normalizedDir = direction.normalize();
Vec3 end = start.add(normalizedDir.scale(maxDistance));
// DDA算法参数
double step = 0.1; // 步长越小精度越高
double distance = 0;
BlockPos lastPos = null;
while (distance <= maxDistance) {
Vec3 currentPos = start.add(normalizedDir.scale(distance));
BlockPos blockPos = new BlockPos(
(int) Math.floor(currentPos.x),
(int) Math.floor(currentPos.y),
(int) Math.floor(currentPos.z)
);
// 避免重复添加同一方块
if (lastPos == null || !lastPos.equals(blockPos)) {
blocks.add(blockPos);
lastPos = blockPos;
}
distance += step;
}
return blocks;
}
} }

View file

@ -6,8 +6,8 @@
"Weight": 10, "Weight": 10,
"EmptyReloadTime": 78, "EmptyReloadTime": 78,
"Damage": 700, "Damage": 700,
"ExplosionDamage": 60, "ExplosionDamage": 120,
"ExplosionRadius": 5, "ExplosionRadius": 9,
"AmmoType": "superbwarfare:javelin_missile", "AmmoType": "superbwarfare:javelin_missile",
"AvailablePerks": [ "AvailablePerks": [
"superbwarfare:powerful_attraction", "superbwarfare:powerful_attraction",