添加1130拦截危险弹射物的功能

This commit is contained in:
Atsuishio 2025-04-29 22:47:39 +08:00 committed by Light_Quanta
parent 9b1b2e2f23
commit 50fcda269e
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
6 changed files with 223 additions and 9 deletions

View file

@ -80,6 +80,12 @@ public class BocekItemModel extends GeoModel<BocekItem> {
wingControl(wing1Root, m); wingControl(wing1Root, m);
wingControl(wing2Root, m); wingControl(wing2Root, m);
GeoBone shake = getAnimationProcessor().getBone("shake");
shake.setPosX((float) (shake.getPosX() * pp));
shake.setPosY((float) (shake.getPosY() * pp));
shake.setPosZ((float) (shake.getPosZ() * pp));
rightHand.setPosZ(rightHandPosZ); rightHand.setPosZ(rightHandPosZ);
CrossHairOverlay.gunRot = shen.getRotZ(); CrossHairOverlay.gunRot = shen.getRotZ();

View file

@ -7,6 +7,7 @@ import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.network.message.receive.ClientIndicatorMessage; import com.atsuishio.superbwarfare.network.message.receive.ClientIndicatorMessage;
import com.atsuishio.superbwarfare.tools.CustomExplosion; import com.atsuishio.superbwarfare.tools.CustomExplosion;
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
import com.atsuishio.superbwarfare.tools.ParticleTool; import com.atsuishio.superbwarfare.tools.ParticleTool;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.particles.ParticleTypes;
@ -16,13 +17,16 @@ import net.minecraft.sounds.SoundSource;
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;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
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.level.block.BellBlock; import net.minecraft.world.level.block.BellBlock;
import net.minecraft.world.level.block.state.BlockState; 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.HitResult;
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.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
@ -32,11 +36,16 @@ import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.animation.AnimatableManager; import software.bernie.geckolib.animation.AnimatableManager;
import software.bernie.geckolib.util.GeckoLibUtil; import software.bernie.geckolib.util.GeckoLibUtil;
import java.util.Comparator;
import java.util.List;
import java.util.stream.StreamSupport;
public class SmallCannonShellEntity extends FastThrowableProjectile implements GeoEntity { public class SmallCannonShellEntity extends FastThrowableProjectile implements GeoEntity {
private float damage = 40.0f; private float damage = 40.0f;
private float explosionDamage = 80f; private float explosionDamage = 80f;
private float explosionRadius = 5f; private float explosionRadius = 5f;
private boolean antiAir = false;
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
public SmallCannonShellEntity(EntityType<? extends SmallCannonShellEntity> type, Level world) { public SmallCannonShellEntity(EntityType<? extends SmallCannonShellEntity> type, Level world) {
@ -44,11 +53,12 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
this.noCulling = true; this.noCulling = true;
} }
public SmallCannonShellEntity(LivingEntity entity, Level level, float damage, float explosionDamage, float explosionRadius) { public SmallCannonShellEntity(LivingEntity entity, Level level, float damage, float explosionDamage, float explosionRadius, boolean antiAir) {
super(ModEntities.SMALL_CANNON_SHELL.get(), entity, level); super(ModEntities.SMALL_CANNON_SHELL.get(), entity, level);
this.damage = damage; this.damage = damage;
this.explosionDamage = explosionDamage; this.explosionDamage = explosionDamage;
this.explosionRadius = explosionRadius; this.explosionRadius = explosionRadius;
this.antiAir = antiAir;
} }
@Override @Override
@ -62,7 +72,7 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
} }
@Override @Override
protected void onHitEntity(EntityHitResult result) { protected void onHitEntity(@NotNull EntityHitResult result) {
if (this.level() instanceof ServerLevel) { if (this.level() instanceof ServerLevel) {
Entity entity = result.getEntity(); Entity entity = result.getEntity();
if (this.getOwner() instanceof LivingEntity living) { if (this.getOwner() instanceof LivingEntity living) {
@ -117,6 +127,24 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
ParticleTool.spawnSmallExplosionParticles(this.level(), vec3); ParticleTool.spawnSmallExplosionParticles(this.level(), vec3);
} }
private void causeAirExplode(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,
ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).
setDamageMultiplier(1.25f);
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();
@ -130,6 +158,10 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
this.setDeltaMovement(0, 0, 0); this.setDeltaMovement(0, 0, 0);
} }
if (antiAir) {
findEntityOnPath();
}
if (this.tickCount > 200 || this.isInWater()) { if (this.tickCount > 200 || this.isInWater()) {
if (this.level() instanceof ServerLevel && !onGround()) { if (this.level() instanceof ServerLevel && !onGround()) {
causeExplode(position()); causeExplode(position());
@ -138,6 +170,36 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G
} }
} }
public void findEntityOnPath() {
List<Entity> entities = this.level()
.getEntities(this,
this.getBoundingBox()
.expandTowards(this.getDeltaMovement())
.inflate(0.1)
);
for (Entity entity : entities) {
Entity target = StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
.filter(e -> {
if (e == entity && e instanceof Projectile && !(e instanceof ProjectileEntity || e instanceof SmallCannonShellEntity)) {
return checkNoClip(e);
}
return false;
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
if (target != null) {
target.discard();
causeAirExplode(target.position());
}
}
}
public boolean checkNoClip(Entity target) {
return level().clip(new ClipContext(this.getEyePosition(), target.getEyePosition(),
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() != HitResult.Type.BLOCK;
}
@Override @Override
public void registerControllers(AnimatableManager.ControllerRegistrar data) { public void registerControllers(AnimatableManager.ControllerRegistrar data) {
} }

View file

@ -5,6 +5,8 @@ import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.entity.TargetEntity; import com.atsuishio.superbwarfare.entity.TargetEntity;
import com.atsuishio.superbwarfare.entity.projectile.GunGrenadeEntity; import com.atsuishio.superbwarfare.entity.projectile.GunGrenadeEntity;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity;
import com.atsuishio.superbwarfare.entity.projectile.SmallCannonShellEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.CannonEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.CannonEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.ThirdPersonCameraPosition; import com.atsuishio.superbwarfare.entity.vehicle.base.ThirdPersonCameraPosition;
@ -35,10 +37,12 @@ import net.minecraft.world.damagesource.DamageTypes;
import net.minecraft.world.entity.*; import net.minecraft.world.entity.*;
import net.minecraft.world.entity.monster.Enemy; import net.minecraft.world.entity.monster.Enemy;
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.item.ItemStack; import net.minecraft.world.item.ItemStack;
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.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.neoforged.neoforge.event.EventHooks; import net.neoforged.neoforge.event.EventHooks;
@ -53,6 +57,7 @@ import software.bernie.geckolib.animation.AnimatableManager;
import software.bernie.geckolib.util.GeckoLibUtil; import software.bernie.geckolib.util.GeckoLibUtil;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@ -94,6 +99,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
.damage(VehicleConfig.HPJ11_DAMAGE.get().floatValue()) .damage(VehicleConfig.HPJ11_DAMAGE.get().floatValue())
.explosionDamage(VehicleConfig.HPJ11_EXPLOSION_DAMAGE.get().floatValue()) .explosionDamage(VehicleConfig.HPJ11_EXPLOSION_DAMAGE.get().floatValue())
.explosionRadius(VehicleConfig.HPJ11_EXPLOSION_RADIUS.get().floatValue()) .explosionRadius(VehicleConfig.HPJ11_EXPLOSION_RADIUS.get().floatValue())
.antiAir(true)
.icon(Mod.loc("textures/screens/vehicle_weapon/cannon_30mm.png")) .icon(Mod.loc("textures/screens/vehicle_weapon/cannon_30mm.png"))
} }
}; };
@ -251,7 +257,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
Vector4f worldPosition = transformPosition(transform, 0f, 0.4f, 0); Vector4f worldPosition = transformPosition(transform, 0f, 0.4f, 0);
Vec3 barrelRootPos = new Vec3(worldPosition.x, worldPosition.y, worldPosition.z); Vec3 barrelRootPos = new Vec3(worldPosition.x, worldPosition.y, worldPosition.z);
if (entityData.get(TARGET_UUID).equals("none") && tickCount % 10 == 0) { if (entityData.get(TARGET_UUID).equals("none") && tickCount % 2 == 0) {
Entity naerestEntity = seekNearLivingEntity(barrelRootPos,-32.5,90,3,128); Entity naerestEntity = seekNearLivingEntity(barrelRootPos,-32.5,90,3,128);
if (naerestEntity != null) { if (naerestEntity != null) {
entityData.set(TARGET_UUID, naerestEntity.getStringUUID()); entityData.set(TARGET_UUID, naerestEntity.getStringUUID());
@ -269,6 +275,10 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
this.entityData.set(TARGET_UUID, "none"); this.entityData.set(TARGET_UUID, "none");
return; return;
} }
if ((target instanceof Projectile && VectorTool.calculateAngle(target.getDeltaMovement().normalize(), target.position().vectorTo(this.position()).normalize()) > 60) || target.onGround()) {
this.entityData.set(TARGET_UUID, "none");
return;
}
Vec3 targetPos = new Vec3(target.getX(), target.getY() + target.getBbHeight() / 2, target.getZ()).add(target.getDeltaMovement().scale(2.5)); Vec3 targetPos = new Vec3(target.getX(), target.getY() + target.getBbHeight() / 2, target.getZ()).add(target.getDeltaMovement().scale(2.5));
Vec3 targetVec = barrelRootPos.vectorTo(targetPos).normalize(); Vec3 targetVec = barrelRootPos.vectorTo(targetPos).normalize();
@ -288,6 +298,9 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
if (VectorTool.calculateAngle(getViewVector(1), targetVec) < 3) { if (VectorTool.calculateAngle(getViewVector(1), targetVec) < 3) {
if (checkNoClip(target) && entityData.get(AMMO) > 0) { if (checkNoClip(target) && entityData.get(AMMO) > 0) {
vehicleShoot(player, 0); vehicleShoot(player, 0);
findEntityOnPath(barrelRootPos, targetVec);
} else { } else {
changeTargetTimer++; changeTargetTimer++;
} }
@ -307,6 +320,47 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
} }
} }
public void findEntityOnPath(Vec3 pos, Vec3 toVec) {
List<Entity> entities = this.level()
.getEntities(this,
new AABB(pos, pos)
.expandTowards(toVec.scale(50))
.inflate(0.125)
);
for (Entity entity : entities) {
Entity target = StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
.filter(e -> {
if (e == entity && e instanceof Projectile && !(e instanceof ProjectileEntity || e instanceof SmallCannonShellEntity)) {
return checkNoClip(e);
}
return false;
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
if (target != null) {
target.discard();
causeAirExplode(target.position());
}
}
}
private void causeAirExplode(Vec3 vec3) {
CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
this,
this.getOwner()),
VehicleConfig.HPJ11_EXPLOSION_DAMAGE.get().floatValue(),
vec3.x,
vec3.y,
vec3.z,
VehicleConfig.HPJ11_EXPLOSION_RADIUS.get().floatValue(),
ExplosionConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).
setDamageMultiplier(1.25f);
explosion.explode();
EventHooks.onExplosionStart(this.level(), explosion);
explosion.finalizeExplosion(false);
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
}
public Entity seekNearLivingEntity(Vec3 pos, double minAngle, double maxAngle, double minRange, double seekRange) { public Entity seekNearLivingEntity(Vec3 pos, double minAngle, double maxAngle, double minRange, double seekRange) {
return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false) return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
.filter(e -> { .filter(e -> {
@ -314,9 +368,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
if (e.distanceTo(this) > minRange if (e.distanceTo(this) > minRange
&& e.distanceTo(this) <= seekRange && e.distanceTo(this) <= seekRange
&& canAim(pos, e, minAngle, maxAngle) && canAim(pos, e, minAngle, maxAngle)
&& e instanceof LivingEntity living && ((e instanceof LivingEntity living && living instanceof Enemy && living.getHealth() > 0) || e == seekThreateningEntity())
&& living instanceof Enemy
&& living.getHealth() > 0
&& smokeFilter(e)) { && smokeFilter(e)) {
return checkNoClip(e); return checkNoClip(e);
} }
@ -324,7 +376,15 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null); }).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
} }
public Entity seekThreateningEntity() {
return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
.filter(e -> {
if (!e.onGround() && e instanceof Projectile && e.getDeltaMovement().length() < 20 && VectorTool.calculateAngle(e.getDeltaMovement().normalize(), e.position().vectorTo(this.position()).normalize()) < 30) {
return checkNoClip(e);
}
return false;
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
}
public boolean checkNoClip(Entity target) { public boolean checkNoClip(Entity target) {
return level().clip(new ClipContext(this.getEyePosition(), target.getEyePosition(), return level().clip(new ClipContext(this.getEyePosition(), target.getEyePosition(),

View file

@ -6,6 +6,7 @@ import net.minecraft.world.entity.LivingEntity;
public class SmallCannonShellWeapon extends VehicleWeapon { public class SmallCannonShellWeapon extends VehicleWeapon {
public float damage = 40, explosionDamage = 80, explosionRadius = 5; public float damage = 40, explosionDamage = 80, explosionRadius = 5;
public boolean antiAir = false;
public SmallCannonShellWeapon damage(float damage) { public SmallCannonShellWeapon damage(float damage) {
this.damage = damage; this.damage = damage;
@ -22,7 +23,12 @@ public class SmallCannonShellWeapon extends VehicleWeapon {
return this; return this;
} }
public SmallCannonShellWeapon antiAir(boolean antiAir) {
this.antiAir = antiAir;
return this;
}
public SmallCannonShellEntity create(LivingEntity entity) { public SmallCannonShellEntity create(LivingEntity entity) {
return new SmallCannonShellEntity(entity, entity.level(), damage, explosionDamage, explosionRadius); return new SmallCannonShellEntity(entity, entity.level(), damage, explosionDamage, explosionRadius, antiAir);
} }
} }

View file

@ -125,6 +125,62 @@
"lerp_mode": "catmullrom" "lerp_mode": "catmullrom"
} }
} }
},
"shake": {
"position": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.1333": {
"post": [-0.015, 0.015, 0.01],
"lerp_mode": "catmullrom"
},
"0.2917": {
"post": [0.015, 0, -0.002],
"lerp_mode": "catmullrom"
},
"0.475": {
"post": [-0.015, 0.015, 0.01],
"lerp_mode": "catmullrom"
},
"0.625": {
"post": [-0.015, -0.014, 0.001],
"lerp_mode": "catmullrom"
},
"0.7583": {
"post": [0.015, 0, -0.002],
"lerp_mode": "catmullrom"
},
"0.925": {
"post": [-0.015, 0.015, 0.01],
"lerp_mode": "catmullrom"
},
"1.0917": {
"post": [-0.015, -0.014, 0.001],
"lerp_mode": "catmullrom"
},
"1.2917": {
"post": [-0.015, 0.015, 0.01],
"lerp_mode": "catmullrom"
},
"1.4583": {
"post": [0.015, 0, -0.002],
"lerp_mode": "catmullrom"
},
"1.575": {
"post": [-0.015, -0.014, 0.001],
"lerp_mode": "catmullrom"
},
"1.725": {
"post": [0.015, 0, -0.002],
"lerp_mode": "catmullrom"
},
"1.8667": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
} }
} }
}, },
@ -680,6 +736,25 @@
"lerp_mode": "catmullrom" "lerp_mode": "catmullrom"
} }
} }
},
"bone122": {
"rotation": [0, 0, 0]
},
"bone123": {
"rotation": [0, 0, 0]
},
"D_ring": {
"position": [0, 0, 0]
},
"xian1": {
"rotation": [0, 0, 0],
"position": [0, 0, 0],
"scale": 1
},
"xian2": {
"rotation": [0, 0, 0],
"position": [0, 0, 0],
"scale": 1
} }
} }
}, },

View file

@ -20,10 +20,15 @@
"pivot": [0, 0, 0] "pivot": [0, 0, 0]
}, },
{ {
"name": "move", "name": "shake",
"parent": "root", "parent": "root",
"pivot": [0, 0, 0] "pivot": [0, 0, 0]
}, },
{
"name": "move",
"parent": "shake",
"pivot": [0, 0, 0]
},
{ {
"name": "shen", "name": "shen",
"parent": "move", "parent": "move",