提取瞄准方法
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.ProjectileEntity;
|
||||
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.ContainerMobileVehicleEntity;
|
||||
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;
|
||||
|
||||
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<Float> GUN_ROTATE = SynchedEntityData.defineId(Hpj11Entity.class, EntityDataSerializers.FLOAT);
|
||||
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);
|
||||
|
||||
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) {
|
||||
entityData.set(TARGET_UUID, naerestEntity.getStringUUID());
|
||||
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));
|
||||
|
||||
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);
|
||||
findEntityOnPath(barrelRootPos, targetVec);
|
||||
} else {
|
||||
|
@ -364,7 +366,7 @@ public class Hpj11Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
|||
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, pos);
|
||||
return checkNoClip(this, e, pos);
|
||||
}
|
||||
return false;
|
||||
}).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.entity.TargetEntity;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.base.AutoAimable;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.base.EnergyVehicleEntity;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier;
|
||||
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.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<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());
|
||||
|
||||
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) {
|
||||
entityData.set(TARGET_UUID, naerestEntity.getStringUUID());
|
||||
}
|
||||
|
@ -291,7 +292,7 @@ public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity,
|
|||
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());
|
||||
|
||||
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.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.AbstractArrow;
|
||||
import net.minecraft.world.entity.projectile.Projectile;
|
||||
import net.minecraft.world.entity.projectile.ThrownPotion;
|
||||
import net.minecraft.world.entity.vehicle.DismountHelper;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.api.distmarker.OnlyIn;
|
||||
|
@ -67,17 +63,15 @@ import org.joml.Matrix4f;
|
|||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static com.atsuishio.superbwarfare.client.RenderHelper.preciseBlit;
|
||||
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
||||
import static com.atsuishio.superbwarfare.tools.SeekTool.smokeFilter;
|
||||
|
||||
public abstract class VehicleEntity extends Entity {
|
||||
|
||||
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_DRIVER_UUID = SynchedEntityData.defineId(VehicleEntity.class, EntityDataSerializers.STRING);
|
||||
|
@ -976,55 +970,6 @@ public abstract class VehicleEntity extends Entity {
|
|||
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)
|
||||
public void renderFirstPersonOverlay(GuiGraphics guiGraphics, Font font, Player player, int screenWidth, int screenHeight, float scale) {
|
||||
if (!(this instanceof WeaponVehicleEntity weaponVehicle)) return;
|
||||
|
|
Loading…
Add table
Reference in a new issue