激光防御塔添加拦截弹射物功能
This commit is contained in:
parent
d0043785da
commit
9c071e4767
3 changed files with 78 additions and 65 deletions
|
@ -35,15 +35,12 @@ import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.damagesource.DamageTypes;
|
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.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.entity.projectile.Projectile;
|
import net.minecraft.world.entity.projectile.Projectile;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
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.AABB;
|
||||||
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 org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -258,7 +255,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
||||||
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 % 2 == 0) {
|
if (entityData.get(TARGET_UUID).equals("none") && tickCount % 2 == 0) {
|
||||||
Entity naerestEntity = seekNearLivingEntity(barrelRootPos,-32.5,90,3,160);
|
Entity naerestEntity = seekNearLivingEntity(barrelRootPos,-32.5,90,3,160, 0.3);
|
||||||
if (naerestEntity != null) {
|
if (naerestEntity != null) {
|
||||||
entityData.set(TARGET_UUID, naerestEntity.getStringUUID());
|
entityData.set(TARGET_UUID, naerestEntity.getStringUUID());
|
||||||
}
|
}
|
||||||
|
@ -300,7 +297,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
||||||
this.setYRot(this.getYRot() + Mth.clamp(0.9f * diffY, -20f, 20f));
|
this.setYRot(this.getYRot() + Mth.clamp(0.9f * diffY, -20f, 20f));
|
||||||
|
|
||||||
if (target.distanceTo(this) <= 144 && VectorTool.calculateAngle(getViewVector(1), targetVec) < 10) {
|
if (target.distanceTo(this) <= 144 && VectorTool.calculateAngle(getViewVector(1), targetVec) < 10) {
|
||||||
if (checkNoClip(target) && entityData.get(AMMO) > 0) {
|
if (checkNoClip(target, barrelRootPos) && entityData.get(AMMO) > 0) {
|
||||||
vehicleShoot(player, 0);
|
vehicleShoot(player, 0);
|
||||||
|
|
||||||
findEntityOnPath(barrelRootPos, targetVec);
|
findEntityOnPath(barrelRootPos, targetVec);
|
||||||
|
@ -335,7 +332,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
||||||
Entity target = StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
|
Entity target = StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
|
||||||
.filter(e -> {
|
.filter(e -> {
|
||||||
if (e == entity && e instanceof Projectile && !(e instanceof ProjectileEntity || e instanceof SmallCannonShellEntity)) {
|
if (e == entity && e instanceof Projectile && !(e instanceof ProjectileEntity || e instanceof SmallCannonShellEntity)) {
|
||||||
return checkNoClip(e);
|
return checkNoClip(e, pos);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
||||||
|
@ -365,36 +362,6 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
||||||
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
|
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 -> {
|
|
||||||
// TODO 自定义目标列表
|
|
||||||
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 == seekThreateningEntity())
|
|
||||||
&& smokeFilter(e)) {
|
|
||||||
return checkNoClip(e);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}).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.getBbWidth() >= 0.3 || e.getBbHeight() >= 0.3) && 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(),
|
|
||||||
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() != HitResult.Type.BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getGunRot() {
|
public float getGunRot() {
|
||||||
return this.gunRot;
|
return this.gunRot;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,11 @@ import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResult;
|
import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.damagesource.DamageTypes;
|
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.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.Explosion;
|
import net.minecraft.world.level.Explosion;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
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 org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -43,10 +41,8 @@ import software.bernie.geckolib.animation.AnimationState;
|
||||||
import software.bernie.geckolib.animation.*;
|
import software.bernie.geckolib.animation.*;
|
||||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||||
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.StreamSupport;
|
|
||||||
|
|
||||||
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
||||||
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
|
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
|
||||||
|
@ -244,8 +240,8 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
|
||||||
|
|
||||||
Vec3 barrelRootPos = new Vec3(this.getX(), this.getY() + 1.390625f, this.getZ());
|
Vec3 barrelRootPos = new Vec3(this.getX(), this.getY() + 1.390625f, this.getZ());
|
||||||
|
|
||||||
if (entityData.get(TARGET_UUID).equals("none") && tickCount % 10 == 0) {
|
if (entityData.get(TARGET_UUID).equals("none") && tickCount % 5 == 0) {
|
||||||
Entity naerestEntity = seekNearLivingEntity(barrelRootPos,-40, 90,1,72);
|
Entity naerestEntity = seekNearLivingEntity(barrelRootPos,-40, 90,1,72, 0.01);
|
||||||
if (naerestEntity != null) {
|
if (naerestEntity != null) {
|
||||||
entityData.set(TARGET_UUID, naerestEntity.getStringUUID());
|
entityData.set(TARGET_UUID, naerestEntity.getStringUUID());
|
||||||
}
|
}
|
||||||
|
@ -254,6 +250,10 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
|
||||||
Entity target = EntityFindUtil.findEntity(level(), entityData.get(TARGET_UUID));
|
Entity target = EntityFindUtil.findEntity(level(), entityData.get(TARGET_UUID));
|
||||||
|
|
||||||
if (target != null && smokeFilter(target)) {
|
if (target != null && smokeFilter(target)) {
|
||||||
|
if (target.distanceTo(this) > 72) {
|
||||||
|
this.entityData.set(TARGET_UUID, "none");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (target instanceof LivingEntity living && living.getHealth() <= 0) {
|
if (target instanceof LivingEntity living && living.getHealth() <= 0) {
|
||||||
this.entityData.set(TARGET_UUID, "none");
|
this.entityData.set(TARGET_UUID, "none");
|
||||||
return;
|
return;
|
||||||
|
@ -262,6 +262,10 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
|
||||||
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 targetVec = barrelRootPos.vectorTo(target.getEyePosition()).normalize();
|
Vec3 targetVec = barrelRootPos.vectorTo(target.getEyePosition()).normalize();
|
||||||
|
|
||||||
|
@ -283,7 +287,7 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
|
||||||
changeTargetTimer++;
|
changeTargetTimer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.entityData.get(COOL_DOWN) == 0 && VectorTool.calculateAngle(getViewVector(1), targetVec) < 1 && checkNoClip(target)) {
|
if (this.entityData.get(COOL_DOWN) == 0 && VectorTool.calculateAngle(getViewVector(1), targetVec) < 1 && checkNoClip(target, barrelRootPos)) {
|
||||||
this.entityData.set(COOL_DOWN, VehicleConfig.LASER_TOWER_COOLDOWN.get());
|
this.entityData.set(COOL_DOWN, VehicleConfig.LASER_TOWER_COOLDOWN.get());
|
||||||
|
|
||||||
if (level() instanceof ServerLevel serverLevel) {
|
if (level() instanceof ServerLevel serverLevel) {
|
||||||
|
@ -298,6 +302,12 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
|
||||||
if (Math.random() < 0.25 && target instanceof LivingEntity living) {
|
if (Math.random() < 0.25 && target instanceof LivingEntity living) {
|
||||||
living.setRemainingFireTicks(2);
|
living.setRemainingFireTicks(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target instanceof Projectile) {
|
||||||
|
causeAirExplode(target.position());
|
||||||
|
target.discard();
|
||||||
|
}
|
||||||
|
|
||||||
if (!target.isAlive()) {
|
if (!target.isAlive()) {
|
||||||
entityData.set(TARGET_UUID, "none");
|
entityData.set(TARGET_UUID, "none");
|
||||||
}
|
}
|
||||||
|
@ -314,26 +324,22 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entity seekNearLivingEntity(Vec3 pos, double minAngle, double maxAngle, double minRange, double seekRange) {
|
private void causeAirExplode(Vec3 vec3) {
|
||||||
return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
|
CustomExplosion explosion = new CustomExplosion(this.level(), this,
|
||||||
.filter(e -> {
|
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(),
|
||||||
// TODO 自定义目标列表
|
this,
|
||||||
if (e.distanceTo(this) > minRange
|
this.getOwner()),
|
||||||
&& e.distanceTo(this) <= seekRange
|
5,
|
||||||
&& canAim(pos, e, minAngle, maxAngle)
|
vec3.x,
|
||||||
&& e instanceof LivingEntity living
|
vec3.y,
|
||||||
&& living instanceof Enemy
|
vec3.z,
|
||||||
&& living.getHealth() > 0
|
1,
|
||||||
&& smokeFilter(e)) {
|
Explosion.BlockInteraction.KEEP).
|
||||||
return checkNoClip(e);
|
setDamageMultiplier(1);
|
||||||
}
|
explosion.explode();
|
||||||
return false;
|
EventHooks.onExplosionStart(this.level(), explosion);
|
||||||
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
explosion.finalizeExplosion(false);
|
||||||
}
|
ParticleTool.spawnMediumExplosionParticles(this.level(), vec3);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayState movementPredicate(AnimationState<LaserTowerEntity> event) {
|
private PlayState movementPredicate(AnimationState<LaserTowerEntity> event) {
|
||||||
|
|
|
@ -42,15 +42,19 @@ import net.minecraft.world.InteractionResult;
|
||||||
import net.minecraft.world.damagesource.DamageSource;
|
import net.minecraft.world.damagesource.DamageSource;
|
||||||
import net.minecraft.world.damagesource.DamageTypes;
|
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.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.entity.projectile.AbstractArrow;
|
import net.minecraft.world.entity.projectile.AbstractArrow;
|
||||||
|
import net.minecraft.world.entity.projectile.Projectile;
|
||||||
import net.minecraft.world.entity.projectile.ThrownPotion;
|
import net.minecraft.world.entity.projectile.ThrownPotion;
|
||||||
import net.minecraft.world.entity.vehicle.DismountHelper;
|
import net.minecraft.world.entity.vehicle.DismountHelper;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.item.Items;
|
import net.minecraft.world.item.Items;
|
||||||
|
import net.minecraft.world.level.ClipContext;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraft.world.level.gameevent.GameEvent;
|
import net.minecraft.world.level.gameevent.GameEvent;
|
||||||
import net.minecraft.world.level.material.Fluid;
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
import net.minecraft.world.phys.HitResult;
|
||||||
import net.minecraft.world.phys.Vec3;
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.neoforged.api.distmarker.Dist;
|
import net.neoforged.api.distmarker.Dist;
|
||||||
import net.neoforged.api.distmarker.OnlyIn;
|
import net.neoforged.api.distmarker.OnlyIn;
|
||||||
|
@ -63,12 +67,15 @@ import org.joml.Matrix4f;
|
||||||
import org.joml.Vector4f;
|
import org.joml.Vector4f;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import static com.atsuishio.superbwarfare.client.RenderHelper.preciseBlit;
|
import static com.atsuishio.superbwarfare.client.RenderHelper.preciseBlit;
|
||||||
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
||||||
|
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
|
||||||
|
|
||||||
public abstract class VehicleEntity extends Entity {
|
public abstract class VehicleEntity extends Entity {
|
||||||
public static final EntityDataAccessor<Float> HEALTH = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.FLOAT);
|
public static final EntityDataAccessor<Float> HEALTH = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.FLOAT);
|
||||||
|
@ -969,6 +976,39 @@ public abstract class VehicleEntity extends Entity {
|
||||||
return getEyePosition();
|
return getEyePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//防御类载具实体搜寻周围实体
|
||||||
|
public Entity seekNearLivingEntity(Vec3 pos, double minAngle, double maxAngle, double minRange, double seekRange, double size) {
|
||||||
|
return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
|
||||||
|
.filter(e -> {
|
||||||
|
// TODO 自定义目标列表
|
||||||
|
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 == seekThreateningEntity(size, pos))
|
||||||
|
&& smokeFilter(e)) {
|
||||||
|
return checkNoClip(e, pos);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断具有威胁的弹射物
|
||||||
|
public Entity seekThreateningEntity(double size, Vec3 pos) {
|
||||||
|
return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
|
||||||
|
.filter(e -> {
|
||||||
|
if (!e.onGround() && e instanceof Projectile && (e.getBbWidth() >= size || e.getBbHeight() >= size) && VectorTool.calculateAngle(e.getDeltaMovement().normalize(), e.position().vectorTo(this.position()).normalize()) < 30) {
|
||||||
|
return checkNoClip(e, pos);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断载具和目标之间有无障碍物
|
||||||
|
public boolean checkNoClip(Entity target, Vec3 pos) {
|
||||||
|
return level().clip(new ClipContext(this.getEyePosition(), target.getEyePosition(),
|
||||||
|
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() != HitResult.Type.BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean canAim(Vec3 pos, Entity target, double minAngle, double maxAngle) {
|
public static boolean canAim(Vec3 pos, Entity target, double minAngle, double maxAngle) {
|
||||||
Vec3 targetPos = new Vec3(target.getX(), target.getY() + target.getBbHeight() / 2, target.getZ());
|
Vec3 targetPos = new Vec3(target.getX(), target.getY() + target.getBbHeight() / 2, target.getZ());
|
||||||
Vec3 toVec = pos.vectorTo(targetPos).normalize();
|
Vec3 toVec = pos.vectorTo(targetPos).normalize();
|
||||||
|
|
Loading…
Add table
Reference in a new issue