From 50fcda269edbc56e04b60d3c8a9584f29866dd82 Mon Sep 17 00:00:00 2001 From: Atsuishio <842960157@qq.com> Date: Tue, 29 Apr 2025 22:47:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A01130=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E5=8D=B1=E9=99=A9=E5=BC=B9=E5=B0=84=E7=89=A9=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/model/item/BocekItemModel.java | 6 ++ .../projectile/SmallCannonShellEntity.java | 66 +++++++++++++++- .../entity/vehicle/Hpj11Entity.java | 70 +++++++++++++++-- .../weapon/SmallCannonShellWeapon.java | 8 +- .../animations/bocek.animation.json | 75 +++++++++++++++++++ .../assets/superbwarfare/geo/bocek.geo.json | 7 +- 6 files changed, 223 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/item/BocekItemModel.java b/src/main/java/com/atsuishio/superbwarfare/client/model/item/BocekItemModel.java index ddd2ed55c..b4947931f 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/model/item/BocekItemModel.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/item/BocekItemModel.java @@ -80,6 +80,12 @@ public class BocekItemModel extends GeoModel { wingControl(wing1Root, 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); CrossHairOverlay.gunRot = shen.getRotZ(); diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/SmallCannonShellEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/SmallCannonShellEntity.java index ec97eedc3..ae6516a29 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/projectile/SmallCannonShellEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/projectile/SmallCannonShellEntity.java @@ -7,6 +7,7 @@ import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModSounds; import com.atsuishio.superbwarfare.network.message.receive.ClientIndicatorMessage; import com.atsuishio.superbwarfare.tools.CustomExplosion; +import com.atsuishio.superbwarfare.tools.EntityFindUtil; import com.atsuishio.superbwarfare.tools.ParticleTool; import net.minecraft.core.BlockPos; 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.EntityType; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.item.Item; +import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.BellBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.EntityHitResult; +import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.event.EventHooks; 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.util.GeckoLibUtil; +import java.util.Comparator; +import java.util.List; +import java.util.stream.StreamSupport; + public class SmallCannonShellEntity extends FastThrowableProjectile implements GeoEntity { private float damage = 40.0f; private float explosionDamage = 80f; private float explosionRadius = 5f; + private boolean antiAir = false; private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); public SmallCannonShellEntity(EntityType type, Level world) { @@ -44,11 +53,12 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G 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); this.damage = damage; this.explosionDamage = explosionDamage; this.explosionRadius = explosionRadius; + this.antiAir = antiAir; } @Override @@ -62,7 +72,7 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G } @Override - protected void onHitEntity(EntityHitResult result) { + protected void onHitEntity(@NotNull EntityHitResult result) { if (this.level() instanceof ServerLevel) { Entity entity = result.getEntity(); if (this.getOwner() instanceof LivingEntity living) { @@ -117,6 +127,24 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G 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 public void tick() { super.tick(); @@ -130,6 +158,10 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G this.setDeltaMovement(0, 0, 0); } + if (antiAir) { + findEntityOnPath(); + } + if (this.tickCount > 200 || this.isInWater()) { if (this.level() instanceof ServerLevel && !onGround()) { causeExplode(position()); @@ -138,6 +170,36 @@ public class SmallCannonShellEntity extends FastThrowableProjectile implements G } } + public void findEntityOnPath() { + List 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 public void registerControllers(AnimatableManager.ControllerRegistrar data) { } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Hpj11Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Hpj11Entity.java index 5690f8c30..bdce1b5fe 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Hpj11Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Hpj11Entity.java @@ -5,6 +5,8 @@ import com.atsuishio.superbwarfare.config.server.ExplosionConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.entity.TargetEntity; 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.ContainerMobileVehicleEntity; 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.monster.Enemy; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.event.EventHooks; @@ -53,6 +57,7 @@ import software.bernie.geckolib.animation.AnimatableManager; import software.bernie.geckolib.util.GeckoLibUtil; import java.util.Comparator; +import java.util.List; import java.util.Optional; import java.util.UUID; import java.util.stream.StreamSupport; @@ -94,6 +99,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti .damage(VehicleConfig.HPJ11_DAMAGE.get().floatValue()) .explosionDamage(VehicleConfig.HPJ11_EXPLOSION_DAMAGE.get().floatValue()) .explosionRadius(VehicleConfig.HPJ11_EXPLOSION_RADIUS.get().floatValue()) + .antiAir(true) .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); 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); if (naerestEntity != null) { entityData.set(TARGET_UUID, naerestEntity.getStringUUID()); @@ -269,6 +275,10 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti this.entityData.set(TARGET_UUID, "none"); 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 targetVec = barrelRootPos.vectorTo(targetPos).normalize(); @@ -288,6 +298,9 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti if (VectorTool.calculateAngle(getViewVector(1), targetVec) < 3) { if (checkNoClip(target) && entityData.get(AMMO) > 0) { vehicleShoot(player, 0); + + findEntityOnPath(barrelRootPos, targetVec); + } else { changeTargetTimer++; } @@ -307,6 +320,47 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti } } + public void findEntityOnPath(Vec3 pos, Vec3 toVec) { + List 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) { return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false) .filter(e -> { @@ -314,9 +368,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti if (e.distanceTo(this) > minRange && e.distanceTo(this) <= seekRange && canAim(pos, e, minAngle, maxAngle) - && e instanceof LivingEntity living - && living instanceof Enemy - && living.getHealth() > 0 + && ((e instanceof LivingEntity living && living instanceof Enemy && living.getHealth() > 0) || e == seekThreateningEntity()) && smokeFilter(e)) { return checkNoClip(e); } @@ -324,7 +376,15 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti }).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) { return level().clip(new ClipContext(this.getEyePosition(), target.getEyePosition(), diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/weapon/SmallCannonShellWeapon.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/weapon/SmallCannonShellWeapon.java index fa90f3ae0..e1c2fc326 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/weapon/SmallCannonShellWeapon.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/weapon/SmallCannonShellWeapon.java @@ -6,6 +6,7 @@ import net.minecraft.world.entity.LivingEntity; public class SmallCannonShellWeapon extends VehicleWeapon { public float damage = 40, explosionDamage = 80, explosionRadius = 5; + public boolean antiAir = false; public SmallCannonShellWeapon damage(float damage) { this.damage = damage; @@ -22,7 +23,12 @@ public class SmallCannonShellWeapon extends VehicleWeapon { return this; } + public SmallCannonShellWeapon antiAir(boolean antiAir) { + this.antiAir = antiAir; + return this; + } + public SmallCannonShellEntity create(LivingEntity entity) { - return new SmallCannonShellEntity(entity, entity.level(), damage, explosionDamage, explosionRadius); + return new SmallCannonShellEntity(entity, entity.level(), damage, explosionDamage, explosionRadius, antiAir); } } diff --git a/src/main/resources/assets/superbwarfare/animations/bocek.animation.json b/src/main/resources/assets/superbwarfare/animations/bocek.animation.json index 62c99b81b..d3dd54d9f 100644 --- a/src/main/resources/assets/superbwarfare/animations/bocek.animation.json +++ b/src/main/resources/assets/superbwarfare/animations/bocek.animation.json @@ -125,6 +125,62 @@ "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" } } + }, + "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 } } }, diff --git a/src/main/resources/assets/superbwarfare/geo/bocek.geo.json b/src/main/resources/assets/superbwarfare/geo/bocek.geo.json index 8f0835ee3..115f9170d 100644 --- a/src/main/resources/assets/superbwarfare/geo/bocek.geo.json +++ b/src/main/resources/assets/superbwarfare/geo/bocek.geo.json @@ -20,10 +20,15 @@ "pivot": [0, 0, 0] }, { - "name": "move", + "name": "shake", "parent": "root", "pivot": [0, 0, 0] }, + { + "name": "move", + "parent": "shake", + "pivot": [0, 0, 0] + }, { "name": "shen", "parent": "move",