提取瞄准方法
This commit is contained in:
parent
61bd74c8f4
commit
5f3486eaae
4 changed files with 77 additions and 63 deletions
|
@ -7,6 +7,7 @@ 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.ProjectileEntity;
|
||||||
import com.atsuishio.superbwarfare.entity.projectile.SmallCannonShellEntity;
|
import com.atsuishio.superbwarfare.entity.projectile.SmallCannonShellEntity;
|
||||||
|
import com.atsuishio.superbwarfare.entity.vehicle.base.AutoAimable;
|
||||||
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;
|
||||||
|
@ -61,7 +62,8 @@ import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
|
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
|
||||||
|
|
||||||
public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEntity, CannonEntity, OwnableEntity {
|
public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEntity, CannonEntity, OwnableEntity, AutoAimable {
|
||||||
|
|
||||||
public static final EntityDataAccessor<Integer> ANIM_TIME = SynchedEntityData.defineId(Hpj11Entity.class, EntityDataSerializers.INT);
|
public static final EntityDataAccessor<Integer> ANIM_TIME = SynchedEntityData.defineId(Hpj11Entity.class, EntityDataSerializers.INT);
|
||||||
public static final EntityDataAccessor<Float> GUN_ROTATE = SynchedEntityData.defineId(Hpj11Entity.class, EntityDataSerializers.FLOAT);
|
public static final EntityDataAccessor<Float> GUN_ROTATE = SynchedEntityData.defineId(Hpj11Entity.class, EntityDataSerializers.FLOAT);
|
||||||
public static final EntityDataAccessor<Boolean> ACTIVE = SynchedEntityData.defineId(Hpj11Entity.class, EntityDataSerializers.BOOLEAN);
|
public static final EntityDataAccessor<Boolean> ACTIVE = SynchedEntityData.defineId(Hpj11Entity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
@ -263,7 +265,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, 0.3);
|
Entity naerestEntity = seekNearLivingEntity(this, 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());
|
||||||
this.consumeEnergy(VehicleConfig.HPJ11_SEEK_COST.get());
|
this.consumeEnergy(VehicleConfig.HPJ11_SEEK_COST.get());
|
||||||
|
@ -314,7 +316,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, barrelRootPos) && entityData.get(AMMO) > 0) {
|
if (checkNoClip(this, target, barrelRootPos) && entityData.get(AMMO) > 0) {
|
||||||
vehicleShoot(player, 0);
|
vehicleShoot(player, 0);
|
||||||
findEntityOnPath(barrelRootPos, targetVec);
|
findEntityOnPath(barrelRootPos, targetVec);
|
||||||
} else {
|
} else {
|
||||||
|
@ -364,7 +366,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, pos);
|
return checkNoClip(this, e, pos);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.atsuishio.superbwarfare.entity.vehicle;
|
||||||
|
|
||||||
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.vehicle.base.AutoAimable;
|
||||||
import com.atsuishio.superbwarfare.entity.vehicle.base.EnergyVehicleEntity;
|
import com.atsuishio.superbwarfare.entity.vehicle.base.EnergyVehicleEntity;
|
||||||
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
|
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
|
||||||
import com.atsuishio.superbwarfare.init.*;
|
import com.atsuishio.superbwarfare.init.*;
|
||||||
|
@ -47,7 +48,7 @@ import java.util.UUID;
|
||||||
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;
|
||||||
|
|
||||||
public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity, OwnableEntity {
|
public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity, OwnableEntity, AutoAimable {
|
||||||
|
|
||||||
public static final EntityDataAccessor<Integer> COOL_DOWN = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.INT);
|
public static final EntityDataAccessor<Integer> COOL_DOWN = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.INT);
|
||||||
public static final EntityDataAccessor<String> TARGET_UUID = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.STRING);
|
public static final EntityDataAccessor<String> TARGET_UUID = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.STRING);
|
||||||
|
@ -241,7 +242,7 @@ 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 % 5 == 0) {
|
if (entityData.get(TARGET_UUID).equals("none") && tickCount % 5 == 0) {
|
||||||
Entity naerestEntity = seekNearLivingEntity(barrelRootPos,-40, 90,1,72, 0.01);
|
Entity naerestEntity = seekNearLivingEntity(this, 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());
|
||||||
}
|
}
|
||||||
|
@ -291,7 +292,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, barrelRootPos)) {
|
if (this.entityData.get(COOL_DOWN) == 0 && VectorTool.calculateAngle(getViewVector(1), targetVec) < 1 && checkNoClip(this, 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) {
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.atsuishio.superbwarfare.entity.vehicle.base;
|
||||||
|
|
||||||
|
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
|
||||||
|
import com.atsuishio.superbwarfare.tools.VectorTool;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
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.level.ClipContext;
|
||||||
|
import net.minecraft.world.phys.HitResult;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
|
||||||
|
|
||||||
|
public interface AutoAimable {
|
||||||
|
|
||||||
|
// 防御类载具实体搜寻周围实体
|
||||||
|
default Entity seekNearLivingEntity(Entity attacker, Vec3 pos, double minAngle, double maxAngle, double minRange, double seekRange, double size) {
|
||||||
|
return StreamSupport.stream(EntityFindUtil.getEntities(attacker.level()).getAll().spliterator(), false)
|
||||||
|
.filter(e -> {
|
||||||
|
// TODO 自定义目标列表
|
||||||
|
if (e.distanceTo(attacker) > minRange
|
||||||
|
&& e.distanceTo(attacker) <= seekRange
|
||||||
|
&& canAim(pos, e, minAngle, maxAngle)
|
||||||
|
&& !(e instanceof Player player && (player.isSpectator() || player.isCreative()))
|
||||||
|
&& ((e instanceof LivingEntity living && living instanceof Enemy && living.getHealth() > 0) || e == seekThreateningEntity(attacker, size, pos) || basicEnemyFilter(e))
|
||||||
|
&& smokeFilter(e)) {
|
||||||
|
return checkNoClip(attacker, e, pos);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).min(Comparator.comparingDouble(e -> e.distanceTo(attacker))).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断具有威胁的弹射物
|
||||||
|
default Entity seekThreateningEntity(Entity attacker, double size, Vec3 pos) {
|
||||||
|
return StreamSupport.stream(EntityFindUtil.getEntities(attacker.level()).getAll().spliterator(), false)
|
||||||
|
.filter(e -> {
|
||||||
|
if (!e.onGround() && e instanceof Projectile projectile && (e.getBbWidth() >= size || e.getBbHeight() >= size) &&
|
||||||
|
VectorTool.calculateAngle(e.getDeltaMovement().normalize(), e.position().vectorTo(attacker.position()).normalize()) < 30) {
|
||||||
|
return checkNoClip(attacker, e, pos) && basicEnemyProjectileFilter(projectile);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}).min(Comparator.comparingDouble(e -> e.distanceTo(attacker))).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断载具和目标之间有无障碍物
|
||||||
|
default boolean checkNoClip(Entity attacker, Entity target, Vec3 pos) {
|
||||||
|
return attacker.level().clip(new ClipContext(pos, target.getEyePosition(),
|
||||||
|
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, attacker)).getType() != HitResult.Type.BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean basicEnemyFilter(Entity pEntity);
|
||||||
|
|
||||||
|
boolean basicEnemyProjectileFilter(Projectile projectile);
|
||||||
|
|
||||||
|
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 toVec = pos.vectorTo(targetPos).normalize();
|
||||||
|
double targetAngle = VehicleEntity.getXRotFromVector(toVec);
|
||||||
|
return minAngle < targetAngle && targetAngle < maxAngle;
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,19 +42,15 @@ 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;
|
||||||
|
@ -67,17 +63,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);
|
||||||
public static final EntityDataAccessor<String> LAST_ATTACKER_UUID = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.STRING);
|
public static final EntityDataAccessor<String> LAST_ATTACKER_UUID = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.STRING);
|
||||||
public static final EntityDataAccessor<String> LAST_DRIVER_UUID = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.STRING);
|
public static final EntityDataAccessor<String> LAST_DRIVER_UUID = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.STRING);
|
||||||
|
@ -976,55 +970,6 @@ 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 Player player && (player.isSpectator() || player.isCreative()))
|
|
||||||
&& ((e instanceof LivingEntity living && living instanceof Enemy && living.getHealth() > 0) || e == seekThreateningEntity(size, pos) || basicEnemyFilter(e))
|
|
||||||
&& 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 projectile && (e.getBbWidth() >= size || e.getBbHeight() >= size) && VectorTool.calculateAngle(e.getDeltaMovement().normalize(), e.position().vectorTo(this.position()).normalize()) < 30) {
|
|
||||||
return checkNoClip(e, pos) && basicEnemyProjectileFilter(projectile);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
//判断载具和目标之间有无障碍物
|
|
||||||
public boolean checkNoClip(Entity target, Vec3 pos) {
|
|
||||||
return level().clip(new ClipContext(pos, target.getEyePosition(),
|
|
||||||
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() != HitResult.Type.BLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean basicEnemyFilter(Entity pEntity) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean basicEnemyProjectileFilter(Projectile projectile) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 toVec = pos.vectorTo(targetPos).normalize();
|
|
||||||
double targetAngle = VehicleEntity.getXRotFromVector(toVec);
|
|
||||||
return minAngle < targetAngle && targetAngle < maxAngle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
@OnlyIn(Dist.CLIENT)
|
||||||
public void renderFirstPersonOverlay(GuiGraphics guiGraphics, Font font, Player player, int screenWidth, int screenHeight, float scale) {
|
public void renderFirstPersonOverlay(GuiGraphics guiGraphics, Font font, Player player, int screenWidth, int screenHeight, float scale) {
|
||||||
if (!(this instanceof WeaponVehicleEntity weaponVehicle)) return;
|
if (!(this instanceof WeaponVehicleEntity weaponVehicle)) return;
|
||||||
|
|
Loading…
Add table
Reference in a new issue