无人机不再是生物

This commit is contained in:
Atsuihsio 2025-01-12 18:31:03 +08:00
parent 0e9502bec5
commit 3d23f3b91b
10 changed files with 232 additions and 248 deletions

View file

@ -4,9 +4,7 @@ import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.DroneEntity;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import software.bernie.geckolib.core.animatable.model.CoreGeoBone;
@ -16,15 +14,8 @@ import software.bernie.geckolib.model.GeoModel;
import java.util.UUID;
import static com.atsuishio.superbwarfare.entity.DroneEntity.*;
import static com.atsuishio.superbwarfare.event.ClientEventHandler.droneBodyAngle;
public class DroneModel extends GeoModel<DroneEntity> {
public static float rotX = 0;
public static float rotZ = 0;
public static float rotation = 0;
@Override
public ResourceLocation getAnimationResource(DroneEntity entity) {
return ModUtils.loc("animations/drone.animation.json");
@ -49,7 +40,6 @@ public class DroneModel extends GeoModel<DroneEntity> {
CoreGeoBone ammo5 = getAnimationProcessor().getBone("ammo5");
CoreGeoBone ammo6 = getAnimationProcessor().getBone("ammo6");
CoreGeoBone shell = getAnimationProcessor().getBone("shell");
CoreGeoBone main = getAnimationProcessor().getBone("0");
ammo6.setHidden(animatable.getEntityData().get(AMMO) <= 5);
ammo5.setHidden(animatable.getEntityData().get(AMMO) <= 4);
@ -59,33 +49,6 @@ public class DroneModel extends GeoModel<DroneEntity> {
ammo1.setHidden(animatable.getEntityData().get(AMMO) <= 0);
shell.setHidden(!animatable.getEntityData().get(KAMIKAZE));
float times = Math.min(Minecraft.getInstance().getDeltaFrameTime(), 1);
if (Minecraft.getInstance().options.keyRight.isDown()) {
rotZ = Mth.lerp(0.025f * times, rotZ, -0.25f);
} else if (Minecraft.getInstance().options.keyLeft.isDown()) {
rotZ = Mth.lerp(0.025f * times, rotZ, 0.25f);
} else {
rotZ = Mth.lerp(0.04f * times, rotZ, 0);
}
main.setRotZ(rotZ);
droneBodyAngle(rotZ);
// 螺旋桨控制
CoreGeoBone wingFL = getAnimationProcessor().getBone("wingFL");
CoreGeoBone wingFR = getAnimationProcessor().getBone("wingFR");
CoreGeoBone wingBL = getAnimationProcessor().getBone("wingBL");
CoreGeoBone wingBR = getAnimationProcessor().getBone("wingBR");
rotation = (float) Mth.lerp(times, rotation, animatable.onGround() ? 0 : 0.2);
wingFL.setRotY(wingFL.getRotY() - rotation);
wingFR.setRotY(wingFL.getRotY() - rotation);
wingBL.setRotY(wingFL.getRotY() - rotation);
wingBR.setRotY(wingFL.getRotY() - rotation);
CoreGeoBone weapon = getAnimationProcessor().getBone("Weapon");
String id = animatable.getEntityData().get(CONTROLLER);
UUID uuid;

View file

@ -40,7 +40,7 @@ public class Ah6Renderer extends GeoEntityRenderer<Ah6Entity> {
poseStack.pushPose();
poseStack.mulPose(Axis.YP.rotationDegrees(-entityYaw));
poseStack.mulPose(Axis.XP.rotationDegrees(Mth.lerp(partialTicks, entityIn.xRotO, entityIn.getXRot())));
poseStack.mulPose(Axis.ZP.rotationDegrees(entityIn.getRoll(partialTicks)));
poseStack.mulPose(Axis.ZP.rotationDegrees(Mth.lerp(partialTicks, entityIn.prevRoll, entityIn.getRoll())));
super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
poseStack.popPose();
}

View file

@ -5,11 +5,14 @@ import com.atsuishio.superbwarfare.client.model.entity.DroneModel;
import com.atsuishio.superbwarfare.entity.DroneEntity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Axis;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.cache.object.GeoBone;
import software.bernie.geckolib.renderer.GeoEntityRenderer;
public class DroneRenderer extends GeoEntityRenderer<DroneEntity> {
@ -33,12 +36,30 @@ public class DroneRenderer extends GeoEntityRenderer<DroneEntity> {
}
@Override
protected float getDeathMaxRotation(DroneEntity entityLivingBaseIn) {
return 0.0F;
public void render(DroneEntity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
poseStack.pushPose();
poseStack.mulPose(Axis.YP.rotationDegrees(-entityIn.getYaw(partialTicks)));
poseStack.mulPose(Axis.XP.rotationDegrees(entityIn.getBodyPitch(partialTicks)));
poseStack.mulPose(Axis.ZP.rotationDegrees(entityIn.getRoll(partialTicks)));
super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
poseStack.popPose();
}
@Override
public boolean shouldShowName(DroneEntity animatable) {
return animatable.hasCustomName();
public void renderRecursively(PoseStack poseStack, DroneEntity animatable, GeoBone bone, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
String name = bone.getName();
if (name.equals("wingFL")) {
bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot()));
}
if (name.equals("wingFR")) {
bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot()));
}
if (name.equals("wingBL")) {
bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot()));
}
if (name.equals("wingBR")) {
bone.setRotY(Mth.lerp(partialTick, animatable.propellerRotO, animatable.getPropellerRot()));
}
super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
}
}

View file

@ -3,6 +3,7 @@ package com.atsuishio.superbwarfare.entity;
import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig;
import com.atsuishio.superbwarfare.entity.projectile.RgoGrenadeEntity;
import com.atsuishio.superbwarfare.entity.vehicle.MobileVehicleEntity;
import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModEntities;
import com.atsuishio.superbwarfare.init.ModItems;
@ -12,8 +13,6 @@ import com.atsuishio.superbwarfare.tools.CustomExplosion;
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
import com.atsuishio.superbwarfare.tools.ParticleTool;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
@ -31,15 +30,14 @@ import net.minecraft.world.InteractionHand;
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.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.event.ForgeEventFactory;
@ -47,6 +45,7 @@ import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PlayMessages;
import org.jetbrains.annotations.NotNull;
import org.joml.Math;
import org.joml.Vector3f;
import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
@ -57,28 +56,26 @@ import java.util.Comparator;
import java.util.Objects;
import java.util.UUID;
public class DroneEntity extends LivingEntity implements GeoEntity {
public class DroneEntity extends MobileVehicleEntity implements GeoEntity {
public static final EntityDataAccessor<Boolean> LINKED = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.BOOLEAN);
public static final EntityDataAccessor<String> CONTROLLER = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.STRING);
public static final EntityDataAccessor<Integer> AMMO = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.INT);
public static final EntityDataAccessor<Boolean> KAMIKAZE = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.BOOLEAN);
public static final EntityDataAccessor<Float> DELTA_ROT = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.FLOAT);
public static final EntityDataAccessor<Float> DELTA_X_ROT = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.FLOAT);
public static final EntityDataAccessor<Float> PROPELLER_ROT = SynchedEntityData.defineId(DroneEntity.class, EntityDataSerializers.FLOAT);
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
public double moveX = 0;
public double moveY = 0;
public double moveZ = 0;
public boolean leftInputDown;
public boolean rightInputDown;
public boolean forwardInputDown;
public boolean backInputDown;
public boolean upInputDown;
public boolean downInputDown;
public static final float MAX_HEALTH = 5;
public float propellerRot;
public float propellerRotO;
public boolean fire;
public int collisionCoolDown;
public double lastTickSpeed;
public double lastTickVerticalSpeed;
public float pitch;
public float pitchO;
public DroneEntity(PlayMessages.SpawnEntity packet, Level world) {
this(ModEntities.DRONE.get(), world);
@ -86,7 +83,30 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
public DroneEntity(EntityType<DroneEntity> type, Level world) {
super(type, world);
this.noCulling = true;
}
public float getBodyPitch() {
return pitch;
}
public void setBodyXRot(float rot) {
pitch = rot;
}
public float getBodyPitch(float tickDelta) {
return Mth.lerp(0.6f * tickDelta, pitchO, getBodyPitch());
}
@Override
public boolean hurt(DamageSource source, float amount) {
super.hurt(source, amount);
this.hurt(amount);
return true;
}
@Override
public float getMaxHealth() {
return MAX_HEALTH;
}
public DroneEntity(EntityType<? extends DroneEntity> type, Level world, float moveX, float moveY, float moveZ) {
@ -96,41 +116,20 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
@Override
protected void defineSynchedData() {
super.defineSynchedData();
this.entityData.define(PROPELLER_ROT, 0f);
this.entityData.define(DELTA_ROT, 0f);
this.entityData.define(DELTA_X_ROT, 0f);
this.entityData.define(CONTROLLER, "undefined");
this.entityData.define(LINKED, false);
this.entityData.define(AMMO, 0);
this.entityData.define(KAMIKAZE, false);
}
@Override
protected float getStandingEyeHeight(Pose poseIn, EntityDimensions sizeIn) {
return 0.075F;
}
@Override
public Packet<ClientGamePacketListener> getAddEntityPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
@Override
public MobType getMobType() {
return super.getMobType();
}
@Override
public Iterable<ItemStack> getArmorSlots() {
return NonNullList.withSize(1, ItemStack.EMPTY);
}
@Override
public ItemStack getItemBySlot(EquipmentSlot pSlot) {
return ItemStack.EMPTY;
}
@Override
public void setItemSlot(EquipmentSlot pSlot, ItemStack pStack) {
}
@Override
public boolean causeFallDamage(float l, float d, DamageSource source) {
return false;
@ -139,7 +138,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
@Override
public void addAdditionalSaveData(CompoundTag compound) {
super.addAdditionalSaveData(compound);
compound.putBoolean("Linked", this.entityData.get(LINKED));
compound.putString("Controller", this.entityData.get(CONTROLLER));
compound.putInt("Ammo", this.entityData.get(AMMO));
@ -149,7 +147,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
@Override
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
if (compound.contains("Linked"))
this.entityData.set(LINKED, compound.getBoolean("Linked"));
if (compound.contains("Controller"))
@ -160,25 +157,12 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
this.entityData.set(KAMIKAZE, compound.getBoolean("Kamikaze"));
}
public Vector3f getForwardDirection() {
return new Vector3f(
Mth.sin(-getYRot() * ((float) Math.PI / 180)),
0.0f,
Mth.cos(getYRot() * ((float) Math.PI / 180))
).normalize();
}
public Vector3f getRightDirection() {
return new Vector3f(
Mth.cos(-getYRot() * ((float) Math.PI / 180)),
0.0f,
Mth.sin(getYRot() * ((float) Math.PI / 180))
).normalize();
}
@Override
public void baseTick() {
pitchO = this.getBodyPitch();
setBodyXRot(pitch * 0.9f);
propellerRotO = this.getPropellerRot();
super.baseTick();
lastTickSpeed = this.getDeltaMovement().length();
@ -188,49 +172,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
collisionCoolDown--;
}
if (!this.onGround()) {
// left and right
if (leftInputDown) {
moveX = Mth.clamp(moveX + 0.3f, 0, 3);
} else if (rightInputDown) {
moveX = Mth.clamp(moveX - 0.3f, -3, 0);
}
// forward and backward
if (forwardInputDown) {
moveZ = Mth.clamp(moveZ + 0.3f, 0, 3);
} else if (backInputDown) {
moveZ = Mth.clamp(moveZ - 0.3f, -3, 0);
}
moveX *= 0.25;
moveZ *= 0.25;
} else {
moveX = 0;
moveZ = 0;
}
// up and down
if (upInputDown) {
moveY = Mth.clamp(moveY + 0.3f, 0, 3);
} else if (downInputDown) {
moveY = Mth.clamp(moveY - 0.15f, -2, 0);
}
moveY *= 0.3;
setDeltaMovement(getDeltaMovement().add(0.0f, (this.onGround() ? 0.059 : 0) + moveY, 0.0f));
Vector3f direction = getRightDirection().mul((float) moveX);
setDeltaMovement(getDeltaMovement().add(new Vec3(direction.x, direction.y, direction.z).scale(0.8)));
Vector3f directionZ = getForwardDirection().mul((float) moveZ);
setDeltaMovement(getDeltaMovement().add(new Vec3(directionZ.x, directionZ.y, directionZ.z).scale(0.8)));
Vec3 vec = this.getDeltaMovement();
this.setDeltaMovement(vec.multiply(1.055, 0.9, 1.055));
Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER));
if (!this.onGround()) {
@ -257,12 +198,11 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
}
}
if (this.entityData.get(KAMIKAZE)) {
this.discard();
if (controller != null) {
if (controller.getMainHandItem().is(ModItems.MONITOR.get())) {
Monitor.disLink(controller.getMainHandItem());
Monitor.disLink(controller.getMainHandItem(), controller);
}
kamikazeExplosion(controller);
this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), controller), 10000);
}
}
@ -272,6 +212,14 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
this.refreshDimensions();
}
public float getPropellerRot() {
return this.propellerRot;
}
public void setPropellerRot(float pPropellerRot) {
this.propellerRot = pPropellerRot;
}
private void droneDrop(Player player) {
Level level = player.level();
if (!level.isClientSide()) {
@ -284,8 +232,6 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
@Override
public InteractionResult interact(Player player, InteractionHand hand) {
super.interact(player, hand);
ItemStack stack = player.getMainHandItem();
if (stack.getItem() == ModItems.MONITOR.get()) {
if (!player.isCrouching()) {
@ -317,7 +263,7 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
this.entityData.set(CONTROLLER, "none");
this.entityData.set(LINKED, false);
Monitor.disLink(stack);
Monitor.disLink(stack, player);
player.displayClientMessage(Component.translatable("tips.superbwarfare.monitor.unlinked").withStyle(ChatFormatting.RED), true);
if (player instanceof ServerPlayer serverPlayer) {
@ -339,7 +285,7 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
player.getInventory().items.stream().filter(stack_ -> stack_.getItem() == ModItems.MONITOR.get())
.forEach(stack_ -> {
if (stack_.getOrCreateTag().getString(Monitor.LINKED_DRONE).equals(this.getStringUUID())) {
Monitor.disLink(stack_);
Monitor.disLink(stack_, player);
}
});
@ -368,22 +314,86 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
}
@Override
public void travel(Vec3 dir) {
Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER));
public void travel() {
float diffX;
float diffY;
if (!this.onGround()) {
// left and right
if (rightInputDown) {
this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) - 0.3f);
} else if (this.leftInputDown) {
this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) + 0.3f);
}
// forward and backward
if (forwardInputDown) {
this.entityData.set(DELTA_X_ROT, this.entityData.get(DELTA_X_ROT) - 0.3f);
} else if (backInputDown) {
this.entityData.set(DELTA_X_ROT, this.entityData.get(DELTA_X_ROT) + 0.3f);
}
float f = (float) (0.97f - 0.02f * lastTickSpeed);
this.setDeltaMovement(this.getDeltaMovement().multiply(f, 0.9, f));
} else {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.8, 1, 0.8));
this.setZRot(this.roll * 0.9f);
this.setXRot(this.getXRot() * 0.9f);
this.setBodyXRot(this.getBodyPitch() * 0.9f);
}
if (this.isInWater() && this.tickCount % 4 == 0) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 0.6, 0.6));
this.hurt(ModDamageTypes.causeVehicleStrikeDamage(this.level().registryAccess(), this, this.getFirstPassenger() == null ? this : this.getFirstPassenger()), 26 + (float) (60 * ((lastTickSpeed - 0.4) * (lastTickSpeed - 0.4))));
}
boolean up = this.upInputDown;
boolean down = this.downInputDown;
if (up) {
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.01f, 0.15f));
}
if (down) {
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.01f, 0));
}
if (!(up || down)) {
if (this.getDeltaMovement().y() < 0) {
this.entityData.set(POWER, Math.min(this.entityData.get(POWER) + 0.001f, 0.15f));
} else {
this.entityData.set(POWER, Math.max(this.entityData.get(POWER) - 0.001f, 0));
}
}
this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) * 0.8f);
this.entityData.set(DELTA_X_ROT, this.entityData.get(DELTA_X_ROT) * 0.8f);
this.entityData.set(PROPELLER_ROT, Mth.lerp(0.08f, this.entityData.get(PROPELLER_ROT), this.entityData.get(POWER)));
this.setPropellerRot(this.getPropellerRot() + 30 * this.entityData.get(PROPELLER_ROT));
this.entityData.set(PROPELLER_ROT, this.entityData.get(PROPELLER_ROT) * 0.9995f);
this.setZRot(Mth.clamp(this.getRoll() - this.entityData.get(DELTA_ROT), -30, 30));
this.setBodyXRot(Mth.clamp(this.getBodyPitch() - this.entityData.get(DELTA_X_ROT), -30, 30));
setDeltaMovement(getDeltaMovement().add(0.0f, Math.min(Math.sin((90 - this.getBodyPitch()) * Mth.DEG_TO_RAD), Math.sin((90 + this.getRoll()) * Mth.DEG_TO_RAD)) * this.entityData.get(POWER), 0.0f));
Vector3f direction = getRightDirection().mul(Math.cos((this.getRoll() + 90) * Mth.DEG_TO_RAD) * 0.1f);
setDeltaMovement(getDeltaMovement().add(new Vec3(direction.x, direction.y, direction.z).scale(4)));
Vector3f directionZ = getForwardDirection().mul(-Math.cos((this.getBodyPitch() + 90) * Mth.DEG_TO_RAD) * 0.1f);
setDeltaMovement(getDeltaMovement().add(new Vec3(directionZ.x, directionZ.y, directionZ.z).scale(4)));
Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER));
if (controller != null) {
ItemStack stack = controller.getMainHandItem();
if (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using")) {
this.setYRot(controller.getYRot());
this.yRotO = this.getYRot();
this.setXRot(Mth.clamp(controller.getXRot(), -25, 90));
this.setRot(this.getYRot(), this.getXRot());
this.yBodyRot = controller.getYRot();
this.yHeadRot = controller.getYRot();
diffY = Math.clamp(-90f, 90f, Mth.wrapDegrees(controller.getYHeadRot() - this.getYRot()));
diffX = Math.clamp(-60f, 60f, Mth.wrapDegrees(controller.getXRot() - this.getXRot()));
this.setYRot(this.getYRot() + 0.5f * diffY);
this.setXRot(Mth.clamp(this.getXRot() + 0.5f * diffX, -10, 90));
}
}
super.travel(dir);
float f = 0.7f;
AABB aabb = AABB.ofSize(this.getEyePosition(), f, 0.3, f);
var level = this.level();
@ -397,15 +407,16 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
}
public void hitEntityCrash(Player controller, Entity target) {
if (lastTickSpeed > 0.2) {
if (this.entityData.get(KAMIKAZE) && 6 * lastTickSpeed > this.getHealth()) {
if (lastTickSpeed > 0.12) {
if (this.entityData.get(KAMIKAZE) && 20 * lastTickSpeed > this.getHealth()) {
target.hurt(ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, controller), ExplosionConfig.DRONE_KAMIKAZE_HIT_DAMAGE.get());
if (controller.getMainHandItem().is(ModItems.MONITOR.get())) {
Monitor.disLink(controller.getMainHandItem(), controller);
}
}
target.hurt(ModDamageTypes.causeDroneHitDamage(this.level().registryAccess(), this, controller), (float) (5 * lastTickSpeed));
if (target instanceof Mob mobEntity) {
mobEntity.setTarget(this);
}
this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), Objects.requireNonNullElse(controller, this)), (float) ((this.entityData.get(KAMIKAZE) ? 6 : 0.5) * lastTickSpeed));
this.hurt(new DamageSource(level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.EXPLOSION), Objects.requireNonNullElse(controller, this)), (float) ((this.entityData.get(KAMIKAZE) ? 20 : 4) * lastTickSpeed));
}
}
@ -416,8 +427,9 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
if (lastTickSpeed < 0.2 || collisionCoolDown > 0) return;
if ((verticalCollision) && Mth.abs((float) lastTickVerticalSpeed) > 0.2) {
if ((verticalCollision) && Mth.abs((float) lastTickVerticalSpeed) > 0.3) {
this.hurt(ModDamageTypes.causeCustomExplosionDamage(this.level().registryAccess(), this, controller == null ? this : controller), (float) (20 * ((Mth.abs((float) lastTickVerticalSpeed) - 0.3) * (lastTickSpeed - 0.2) * (lastTickSpeed - 0.2))));
collisionCoolDown = 4;
}
if (this.horizontalCollision) {
@ -427,13 +439,7 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
}
@Override
public boolean canBeCollidedWith() {
return super.canBeCollidedWith();
}
@Override
public void die(DamageSource source) {
super.die(source);
public void destroy() {
String id = this.entityData.get(CONTROLLER);
UUID uuid;
@ -448,22 +454,13 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
player.getInventory().items.stream().filter(stack -> stack.getItem() == ModItems.MONITOR.get())
.forEach(stack -> {
if (stack.getOrCreateTag().getString(Monitor.LINKED_DRONE).equals(this.getStringUUID())) {
Monitor.disLink(stack);
Monitor.disLink(stack, player);
}
});
}
Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER));
if (this.entityData.get(KAMIKAZE)) {
this.discard();
if (controller != null) {
if (controller.getMainHandItem().is(ModItems.MONITOR.get())) {
Monitor.disLink(controller.getMainHandItem());
}
kamikazeExplosion(controller);
}
kamikazeExplosion();
}
ItemStack stack = new ItemStack(ModItems.RGO_GRENADE.get(), this.entityData.get(AMMO));
@ -477,13 +474,23 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
if (level() instanceof ServerLevel) {
level().explode(null, this.getX(), this.getY(), this.getZ(), 0, Level.ExplosionInteraction.NONE);
}
Player controller = EntityFindUtil.findPlayer(this.level(), this.entityData.get(CONTROLLER));
if (controller != null) {
if (controller.getMainHandItem().is(ModItems.MONITOR.get())) {
Monitor.disLink(controller.getMainHandItem(), controller);
this.discard();
}
}
this.discard();
}
private void kamikazeExplosion(Entity source) {
private void kamikazeExplosion() {
Entity attacker = EntityFindUtil.findEntity(this.level(), this.entityData.get(LAST_ATTACKER_UUID));
CustomExplosion explosion = new CustomExplosion(this.level(), this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), source, source), ExplosionConfig.DRONE_KAMIKAZE_EXPLOSION_DAMAGE.get(),
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), attacker, attacker), ExplosionConfig.DRONE_KAMIKAZE_EXPLOSION_DAMAGE.get(),
this.getX(), this.getY(), this.getZ(), ExplosionConfig.DRONE_KAMIKAZE_EXPLOSION_RADIUS.get(), ExplosionDestroyConfig.EXPLOSION_DESTROY.get() ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.KEEP).setDamageMultiplier(1);
explosion.explode();
ForgeEventFactory.onExplosionStart(this.level(), explosion);
@ -491,35 +498,10 @@ public class DroneEntity extends LivingEntity implements GeoEntity {
ParticleTool.spawnMediumExplosionParticles(this.level(), this.position());
}
@Override
protected void checkFallDamage(double y, boolean onGroundIn, BlockState state, BlockPos pos) {
}
@Override
public boolean isNoGravity() {
return !this.onGround();
}
public static AttributeSupplier.Builder createAttributes() {
AttributeSupplier.Builder builder = Mob.createMobAttributes();
builder = builder.add(Attributes.MOVEMENT_SPEED, 0);
builder = builder.add(Attributes.MAX_HEALTH, 4);
builder = builder.add(Attributes.ARMOR, 0);
builder = builder.add(Attributes.ATTACK_DAMAGE, 0);
builder = builder.add(Attributes.FOLLOW_RANGE, 64);
builder = builder.add(Attributes.FLYING_SPEED, 10);
return builder;
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar data) {
}
@Override
public HumanoidArm getMainArm() {
return HumanoidArm.RIGHT;
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.cache;

View file

@ -1,5 +1,6 @@
package com.atsuishio.superbwarfare.entity.vehicle;
import com.atsuishio.superbwarfare.entity.DroneEntity;
import com.atsuishio.superbwarfare.entity.TargetEntity;
import com.atsuishio.superbwarfare.entity.projectile.FlareDecoyEntity;
import com.atsuishio.superbwarfare.entity.projectile.LaserEntity;
@ -128,6 +129,7 @@ public class MobileVehicleEntity extends EnergyVehicleEntity {
* @param velocity 动量
*/
public void crushEntities(Vec3 velocity) {
if (this instanceof DroneEntity) return;
if (velocity.horizontalDistance() < 0.1) return;
if (isRemoved()) return;
var frontBox = getBoundingBox().move(velocity.scale(0.5));

View file

@ -1,5 +1,6 @@
package com.atsuishio.superbwarfare.entity.vehicle;
import com.atsuishio.superbwarfare.entity.DroneEntity;
import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModParticleTypes;
@ -58,15 +59,15 @@ public class VehicleEntity extends Entity {
}
public float getRoll(float tickDelta) {
return Mth.lerp(0.6f * tickDelta, prevRoll, getRoll());
return Mth.lerp(tickDelta, prevRoll, getRoll());
}
public float getYaw(float tickDelta) {
return Mth.lerp(0.6f * tickDelta, yRotO, getYRot());
return Mth.lerp(tickDelta, yRotO, getYRot());
}
public float getPitch(float tickDelta) {
return Mth.lerp(0.6f * tickDelta, xRotO, getXRot());
return Mth.lerp(tickDelta, xRotO, getXRot());
}
public void setZRot(float rot) {
@ -258,8 +259,10 @@ public class VehicleEntity extends Entity {
if (this.getHealth() <= 0.1 * this.getMaxHealth()) {
this.hurt(0.1f);
} else {
if (!(this instanceof DroneEntity)) {
this.heal(0.05f);
}
}
this.refreshDimensions();
}

View file

@ -94,7 +94,6 @@ public class ClientEventHandler {
public static double recoilHorizon = 0;
public static double recoilY = 0;
public static double droneRotZ = 0;
public static double droneFov = 1;
public static double droneFovLerp = 1;
@ -795,22 +794,14 @@ public class ClientEventHandler {
}
}
public static void droneBodyAngle(float RotZ) {
LocalPlayer player = Minecraft.getInstance().player;
if (player != null) {
droneRotZ = RotZ;
}
}
private static void handleDroneCamera(ViewportEvent.ComputeCameraAngles event, LivingEntity entity) {
ItemStack stack = entity.getMainHandItem();
double roll = event.getRoll();
float yaw = event.getYaw();
DroneEntity drone = EntityFindUtil.findDrone(entity.level(), stack.getOrCreateTag().getString("LinkedDrone"));
if (drone != null) {
event.setRoll((float) (roll - Mth.RAD_TO_DEG * droneRotZ));
event.setRoll(drone.getRoll((float) event.getPartialTick()) * (1 - (drone.getPitch((float) event.getPartialTick()) / 90)));
}
if (drone != null && stack.getOrCreateTag().getBoolean("Using")) {

View file

@ -39,7 +39,7 @@ public class ModEntities {
EntityType.Builder.<AnnihilatorEntity>of(AnnihilatorEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(AnnihilatorEntity::new).fireImmune().sized(13f, 4.2f));
public static final RegistryObject<EntityType<DroneEntity>> DRONE = register("drone",
EntityType.Builder.<DroneEntity>of(DroneEntity::new, MobCategory.CREATURE).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(DroneEntity::new).sized(0.6f, 0.2f));
EntityType.Builder.<DroneEntity>of(DroneEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(DroneEntity::new).sized(0.6f, 0.2f));
public static final RegistryObject<EntityType<TaserBulletProjectileEntity>> TASER_BULLET_PROJECTILE = register("projectile_taser_bullet_projectile",
EntityType.Builder.<TaserBulletProjectileEntity>of(TaserBulletProjectileEntity::new, MobCategory.MISC).setCustomClientFactory(TaserBulletProjectileEntity::new).setShouldReceiveVelocityUpdates(true).setTrackingRange(64)
@ -89,6 +89,5 @@ public class ModEntities {
public static void registerAttributes(EntityAttributeCreationEvent event) {
event.put(TARGET.get(), TargetEntity.createAttributes().build());
event.put(SENPAI.get(), SenpaiEntity.createAttributes().build());
event.put(DRONE.get(), DroneEntity.createAttributes().build());
}
}

View file

@ -41,9 +41,14 @@ public class Monitor extends Item {
itemstack.getOrCreateTag().putString(LINKED_DRONE, id);
}
public static void disLink(ItemStack itemstack) {
public static void disLink(ItemStack itemstack, Player player) {
ItemNBTTool.setBoolean(itemstack, LINKED, false);
itemstack.getOrCreateTag().putString(LINKED_DRONE, "none");
if (player.level().isClientSide) {
if (lastCameraType != null) {
Minecraft.getInstance().options.setCameraType(lastCameraType);
}
}
}
private void resetDroneData(DroneEntity drone) {

View file

@ -6,6 +6,7 @@ import com.atsuishio.superbwarfare.event.ClientEventHandler;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
import com.mojang.math.Axis;
import net.minecraft.client.Camera;
import net.minecraft.client.CameraType;
import net.minecraft.client.Minecraft;
@ -15,9 +16,12 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import org.joml.Matrix4f;
import org.joml.Vector3d;
import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -60,25 +64,39 @@ public abstract class CameraMixin {
if (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using") && stack.getOrCreateTag().getBoolean("Linked")) {
DroneEntity drone = EntityFindUtil.findDrone(player.level(), stack.getOrCreateTag().getString("LinkedDrone"));
if (drone != null) {
float yRot = drone.getYRot();
if (yRot < 0) {
yRot += 360;
}
yRot = yRot + 90 % 360;
var CameraPos = new Vector3d(0.22, 0.075, 0);
CameraPos.rotateZ(-drone.getXRot() * Mth.DEG_TO_RAD);
CameraPos.rotateY(-yRot * Mth.DEG_TO_RAD);
Matrix4f transform = superbWarfare$getVehicleTransform(drone, partialTicks);
float x0 = 0f;
float y0 = 0.075f;
float z0 = 0.18f;
setRotation(Mth.lerp(partialTicks, player.yBobO, player.yBob), drone.getViewXRot(partialTicks));
setPosition(Mth.lerp(partialTicks, drone.xo + CameraPos.x, drone.getX() + CameraPos.x), Mth.lerp(partialTicks, drone.yo + 0.075, drone.getEyeY()), Mth.lerp(partialTicks, drone.zo + CameraPos.z, drone.getZ() + CameraPos.z));
Vector4f worldPosition = superbWarfare$transformPosition(transform, x0, y0, z0);
setRotation(drone.getYaw(partialTicks), drone.getPitch(partialTicks));
setPosition(worldPosition.x, worldPosition.y, worldPosition.z);
info.cancel();
}
}
}
}
@Unique
private static Matrix4f superbWarfare$getVehicleTransform(DroneEntity vehicle, float ticks) {
Matrix4f transform = new Matrix4f();
transform.translate((float) Mth.lerp(ticks, vehicle.xo, vehicle.getX()), (float) Mth.lerp(ticks, vehicle.yo, vehicle.getY()), (float) Mth.lerp(ticks, vehicle.zo, vehicle.getZ()));
transform.rotate(Axis.YP.rotationDegrees(-vehicle.getYaw(ticks)));
transform.rotate(Axis.XP.rotationDegrees(vehicle.getBodyPitch(ticks)));
transform.rotate(Axis.ZP.rotationDegrees(vehicle.getRoll(ticks)));
return transform;
}
@Unique
private static Vector4f superbWarfare$transformPosition(Matrix4f transform, float x, float y, float z) {
return transform.transform(new Vector4f(x, y, z, 1));
}
@Inject(method = "setup", at = @At("TAIL"))
public void ia$setup(BlockGetter area, Entity entity, boolean thirdPerson, boolean inverseView, float tickDelta, CallbackInfo ci) {
if (thirdPerson && entity.getVehicle() instanceof Mk42Entity) {