添加激光防御塔
This commit is contained in:
parent
fd660f6b8d
commit
ccd74099dd
17 changed files with 2989 additions and 4 deletions
|
@ -1,5 +1,6 @@
|
|||
package com.atsuishio.superbwarfare.block;
|
||||
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.VehicleEntity;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
|
@ -7,7 +8,6 @@ import net.minecraft.network.chat.Component;
|
|||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.damagesource.DamageTypes;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
|
@ -93,9 +93,9 @@ public class BarbedWireBlock extends Block {
|
|||
public void entityInside(BlockState blockstate, Level world, BlockPos pos, Entity entity) {
|
||||
super.entityInside(blockstate, world, pos, entity);
|
||||
|
||||
if (entity instanceof LivingEntity living) {
|
||||
living.makeStuckInBlock(Blocks.AIR.defaultBlockState(), new Vec3(0.25, 0.05, 0.25));
|
||||
living.hurt(new DamageSource(world.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.CACTUS)), 1);
|
||||
if (!(entity instanceof VehicleEntity)) {
|
||||
entity.makeStuckInBlock(Blocks.AIR.defaultBlockState(), new Vec3(0.15, 0.04, 0.15));
|
||||
entity.hurt(new DamageSource(world.registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(DamageTypes.CACTUS)), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package com.atsuishio.superbwarfare.client.layer;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.cache.object.BakedGeoModel;
|
||||
import software.bernie.geckolib.renderer.GeoRenderer;
|
||||
import software.bernie.geckolib.renderer.layer.GeoRenderLayer;
|
||||
|
||||
public class LaserTowerLaserLayer extends GeoRenderLayer<LaserTowerEntity> {
|
||||
|
||||
private static final ResourceLocation LAYER = ModUtils.loc("textures/entity/laser_tower_laser.png");
|
||||
|
||||
public LaserTowerLaserLayer(GeoRenderer<LaserTowerEntity> entityRenderer) {
|
||||
super(entityRenderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack poseStack, LaserTowerEntity animatable, BakedGeoModel bakedModel, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight, int packedOverlay) {
|
||||
RenderType glowRenderType = RenderType.energySwirl(LAYER, 1, 1);
|
||||
getRenderer().reRender(getDefaultBakedModel(animatable), poseStack, bufferSource, animatable, glowRenderType, bufferSource.getBuffer(glowRenderType), partialTick, packedLight, OverlayTexture.NO_OVERLAY, 1, 1, 1, 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.atsuishio.superbwarfare.client.layer;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.cache.object.BakedGeoModel;
|
||||
import software.bernie.geckolib.renderer.GeoRenderer;
|
||||
import software.bernie.geckolib.renderer.layer.GeoRenderLayer;
|
||||
|
||||
import static com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity.ACTIVE;
|
||||
|
||||
public class LaserTowerPowerLayer extends GeoRenderLayer<LaserTowerEntity> {
|
||||
|
||||
private static final ResourceLocation LAYER = ModUtils.loc("textures/entity/laser_tower_e.png");
|
||||
|
||||
public LaserTowerPowerLayer(GeoRenderer<LaserTowerEntity> entityRenderer) {
|
||||
super(entityRenderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack poseStack, LaserTowerEntity animatable, BakedGeoModel bakedModel, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight, int packedOverlay) {
|
||||
if (animatable.getEnergy() <= 0 || !animatable.getEntityData().get(ACTIVE)) return;
|
||||
RenderType glowRenderType = RenderType.eyes(LAYER);
|
||||
getRenderer().reRender(getDefaultBakedModel(animatable), poseStack, bufferSource, animatable, glowRenderType, bufferSource.getBuffer(glowRenderType), partialTick, packedLight, OverlayTexture.NO_OVERLAY, 1, 1, 1, 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.atsuishio.superbwarfare.client.model.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.ModUtils;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import software.bernie.geckolib.core.animatable.model.CoreGeoBone;
|
||||
import software.bernie.geckolib.core.animation.AnimationState;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
|
||||
import static com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity.LASER_LENGTH;
|
||||
|
||||
public class LaserTowerModel extends GeoModel<LaserTowerEntity> {
|
||||
|
||||
@Override
|
||||
public ResourceLocation getAnimationResource(LaserTowerEntity entity) {
|
||||
return ModUtils.loc("animations/laser_tower.animation.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getModelResource(LaserTowerEntity entity) {
|
||||
return ModUtils.loc("geo/laser_tower.geo.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureResource(LaserTowerEntity entity) {
|
||||
return ModUtils.loc("textures/entity/laser_tower.png");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomAnimations(LaserTowerEntity animatable, long instanceId, AnimationState<LaserTowerEntity> animationState) {
|
||||
CoreGeoBone laser = getAnimationProcessor().getBone("laser");
|
||||
laser.setScaleZ(10 * animatable.getEntityData().get(LASER_LENGTH));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.atsuishio.superbwarfare.client.renderer.entity;
|
||||
|
||||
import com.atsuishio.superbwarfare.client.layer.LaserTowerLaserLayer;
|
||||
import com.atsuishio.superbwarfare.client.layer.LaserTowerPowerLayer;
|
||||
import com.atsuishio.superbwarfare.client.model.entity.LaserTowerModel;
|
||||
import com.atsuishio.superbwarfare.entity.vehicle.LaserTowerEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
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 LaserTowerRenderer extends GeoEntityRenderer<LaserTowerEntity> {
|
||||
|
||||
public LaserTowerRenderer(EntityRendererProvider.Context renderManager) {
|
||||
super(renderManager, new LaserTowerModel());
|
||||
this.addRenderLayer(new LaserTowerPowerLayer(this));
|
||||
this.addRenderLayer(new LaserTowerLaserLayer(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderType getRenderType(LaserTowerEntity animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) {
|
||||
return RenderType.entityTranslucent(getTextureLocation(animatable));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRender(PoseStack poseStack, LaserTowerEntity entity, BakedGeoModel model, MultiBufferSource bufferSource, VertexConsumer buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, float red, float green,
|
||||
float blue, float alpha) {
|
||||
float scale = 1f;
|
||||
this.scaleHeight = scale;
|
||||
this.scaleWidth = scale;
|
||||
super.preRender(poseStack, entity, model, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(LaserTowerEntity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
|
||||
poseStack.pushPose();
|
||||
super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
|
||||
poseStack.popPose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderRecursively(PoseStack poseStack, LaserTowerEntity 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("turret")) {
|
||||
bone.setRotY(-Mth.lerp(partialTick, animatable.yRotO, animatable.getYRot()) * Mth.DEG_TO_RAD);
|
||||
}
|
||||
if (name.equals("barrel")) {
|
||||
bone.setRotX(-Mth.lerp(partialTick, animatable.xRotO, animatable.getXRot()) * Mth.DEG_TO_RAD);
|
||||
}
|
||||
|
||||
super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,341 @@
|
|||
package com.atsuishio.superbwarfare.entity.vehicle;
|
||||
|
||||
import com.atsuishio.superbwarfare.init.*;
|
||||
import com.atsuishio.superbwarfare.item.ContainerBlockItem;
|
||||
import com.atsuishio.superbwarfare.tools.CustomExplosion;
|
||||
import com.atsuishio.superbwarfare.tools.EntityFindUtil;
|
||||
import com.atsuishio.superbwarfare.tools.ParticleTool;
|
||||
import com.atsuishio.superbwarfare.tools.VectorTool;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.players.OldUsersConverter;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.util.Mth;
|
||||
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.monster.Monster;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
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.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.network.NetworkHooks;
|
||||
import net.minecraftforge.network.PlayMessages;
|
||||
import org.joml.Math;
|
||||
import software.bernie.geckolib.animatable.GeoEntity;
|
||||
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
|
||||
import software.bernie.geckolib.core.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.core.animation.AnimationController;
|
||||
import software.bernie.geckolib.core.animation.AnimationState;
|
||||
import software.bernie.geckolib.core.animation.RawAnimation;
|
||||
import software.bernie.geckolib.core.object.PlayState;
|
||||
import software.bernie.geckolib.util.GeckoLibUtil;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
||||
|
||||
public class LaserTowerEntity extends EnergyVehicleEntity implements GeoEntity, OwnableEntity {
|
||||
public static final EntityDataAccessor<Integer> COOL_DOWN = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.INT);
|
||||
public static final EntityDataAccessor<Boolean> ACTIVE = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.BOOLEAN);
|
||||
public static final EntityDataAccessor<Optional<UUID>> OWNER_UUID = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.OPTIONAL_UUID);
|
||||
public static final EntityDataAccessor<Float> LASER_LENGTH = SynchedEntityData.defineId(LaserTowerEntity.class, EntityDataSerializers.FLOAT);
|
||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||
|
||||
public static final float MAX_HEALTH = 100;
|
||||
public static final int MAX_ENERGY = 500000;
|
||||
public static final int SHOOT_COST = 5000;
|
||||
|
||||
public LaserTowerEntity(PlayMessages.SpawnEntity packet, Level world) {
|
||||
this(ModEntities.LASER_TOWER.get(), world);
|
||||
}
|
||||
|
||||
public LaserTowerEntity(EntityType<LaserTowerEntity> type, Level world) {
|
||||
super(type, world);
|
||||
this.noCulling = true;
|
||||
}
|
||||
|
||||
public LaserTowerEntity(LivingEntity owner, Level level) {
|
||||
super(ModEntities.CLAYMORE.get(), level);
|
||||
this.setOwnerUUID(owner.getUUID());
|
||||
}
|
||||
|
||||
public boolean isOwnedBy(LivingEntity pEntity) {
|
||||
return pEntity == this.getOwner();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
super.defineSynchedData();
|
||||
this.entityData.define(OWNER_UUID, Optional.empty());
|
||||
this.entityData.define(COOL_DOWN, 0);
|
||||
this.entityData.define(LASER_LENGTH, 0f);
|
||||
this.entityData.define(ACTIVE, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag compound) {
|
||||
super.addAdditionalSaveData(compound);
|
||||
compound.putInt("CoolDown", this.entityData.get(COOL_DOWN));
|
||||
compound.putBoolean("Active", this.entityData.get(ACTIVE));
|
||||
if (this.getOwnerUUID() != null) {
|
||||
compound.putUUID("Owner", this.getOwnerUUID());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag compound) {
|
||||
super.readAdditionalSaveData(compound);
|
||||
this.entityData.set(COOL_DOWN, compound.getInt("CoolDown"));
|
||||
this.entityData.set(ACTIVE, compound.getBoolean("Active"));
|
||||
|
||||
UUID uuid;
|
||||
if (compound.hasUUID("Owner")) {
|
||||
uuid = compound.getUUID("Owner");
|
||||
} else {
|
||||
String s = compound.getString("Owner");
|
||||
|
||||
assert this.getServer() != null;
|
||||
uuid = OldUsersConverter.convertMobOwnerIfNecessary(this.getServer(), s);
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
try {
|
||||
this.setOwnerUUID(uuid);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOwnerUUID(@javax.annotation.Nullable UUID pUuid) {
|
||||
this.entityData.set(OWNER_UUID, Optional.ofNullable(pUuid));
|
||||
}
|
||||
|
||||
@javax.annotation.Nullable
|
||||
public UUID getOwnerUUID() {
|
||||
return this.entityData.get(OWNER_UUID).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<ClientGamePacketListener> getAddEntityPacket() {
|
||||
return NetworkHooks.getEntitySpawningPacket(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hurt(DamageSource source, float amount) {
|
||||
super.hurt(source, amount);
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), this.getX(), this.getY() + 2.5, this.getZ(), 4, 0.2, 0.2, 0.2, 0.2, false);
|
||||
}
|
||||
|
||||
if (source.is(DamageTypes.ARROW)) {
|
||||
amount *= 0.1f;
|
||||
}
|
||||
if (source.is(DamageTypes.TRIDENT)) {
|
||||
amount *= 0.2f;
|
||||
}
|
||||
if (source.is(DamageTypes.MOB_ATTACK)) {
|
||||
amount *= 0.2f;
|
||||
}
|
||||
if (source.is(DamageTypes.MOB_ATTACK_NO_AGGRO)) {
|
||||
amount *= 0.2f;
|
||||
}
|
||||
if (source.is(DamageTypes.MOB_PROJECTILE)) {
|
||||
amount *= 0.4f;
|
||||
}
|
||||
if (source.is(DamageTypes.PLAYER_ATTACK)) {
|
||||
amount *= 0.4f;
|
||||
}
|
||||
if (source.is(DamageTypes.LAVA)) {
|
||||
amount *= 1f;
|
||||
}
|
||||
if (source.is(DamageTypes.EXPLOSION)) {
|
||||
amount *= 1.5f;
|
||||
}
|
||||
if (source.is(DamageTypes.PLAYER_EXPLOSION)) {
|
||||
amount *= 1.5f;
|
||||
}
|
||||
|
||||
if (source.is(ModDamageTypes.CUSTOM_EXPLOSION)) {
|
||||
amount *= 0.5f;
|
||||
}
|
||||
if (source.is(ModDamageTypes.PROJECTILE_BOOM)) {
|
||||
amount *= 0.5f;
|
||||
}
|
||||
if (source.is(ModDamageTypes.MINE)) {
|
||||
amount *= 0.5f;
|
||||
}
|
||||
if (source.is(ModDamageTypes.LUNGE_MINE)) {
|
||||
amount *= 0.5f;
|
||||
}
|
||||
if (source.is(ModDamageTypes.CANNON_FIRE)) {
|
||||
amount *= 0.6f;
|
||||
}
|
||||
if (source.is(ModTags.DamageTypes.PROJECTILE)) {
|
||||
amount *= 0.08f;
|
||||
}
|
||||
if (source.is(ModTags.DamageTypes.PROJECTILE_ABSOLUTE)) {
|
||||
amount *= 0.5f;
|
||||
}
|
||||
if (source.is(ModDamageTypes.VEHICLE_STRIKE)) {
|
||||
amount *= 5f;
|
||||
}
|
||||
|
||||
this.level().playSound(null, this.getOnPos(), ModSounds.HIT.get(), SoundSource.PLAYERS, 1, 1);
|
||||
this.hurt(Math.max(amount - 2, 0), source.getEntity(), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Player player, InteractionHand hand) {
|
||||
ItemStack stack = player.getMainHandItem();
|
||||
if (player.isCrouching()) {
|
||||
if (stack.is(ModItems.CROWBAR.get())) {
|
||||
ItemStack container = ContainerBlockItem.createInstance(this);
|
||||
if (!player.addItem(container)) {
|
||||
player.drop(container, false);
|
||||
}
|
||||
this.remove(RemovalReason.DISCARDED);
|
||||
this.discard();
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!entityData.get(ACTIVE)) {
|
||||
entityData.set(ACTIVE, true);
|
||||
this.setOwnerUUID(player.getUUID());
|
||||
if (player instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.level().playSound(null, serverPlayer.getOnPos(), SoundEvents.ARROW_HIT_PLAYER, SoundSource.PLAYERS, 0.5F, 1);
|
||||
}
|
||||
return InteractionResult.sidedSuccess(this.level().isClientSide());
|
||||
}
|
||||
}
|
||||
return InteractionResult.sidedSuccess(this.level().isClientSide());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 getDeltaMovement() {
|
||||
return new Vec3(0, Math.min(super.getDeltaMovement().y, 0), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void baseTick() {
|
||||
super.baseTick();
|
||||
|
||||
if (this.entityData.get(COOL_DOWN) > 0) {
|
||||
this.entityData.set(COOL_DOWN, this.entityData.get(COOL_DOWN) - 1);
|
||||
}
|
||||
|
||||
this.move(MoverType.SELF, this.getDeltaMovement());
|
||||
if (this.onGround()) {
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
} else {
|
||||
this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04, 0.0));
|
||||
}
|
||||
|
||||
autoAim();
|
||||
this.refreshDimensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Entity attacker = EntityFindUtil.findEntity(this.level(), this.entityData.get(LAST_ATTACKER_UUID));
|
||||
if (level() instanceof ServerLevel) {
|
||||
CustomExplosion explosion = new CustomExplosion(this.level(), this,
|
||||
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), attacker, attacker), 10f,
|
||||
this.getX(), this.getY(), this.getZ(), 3f, Explosion.BlockInteraction.KEEP).setDamageMultiplier(1);
|
||||
explosion.explode();
|
||||
net.minecraftforge.event.ForgeEventFactory.onExplosionStart(this.level(), explosion);
|
||||
explosion.finalizeExplosion(false);
|
||||
ParticleTool.spawnMediumExplosionParticles(this.level(), this.position());
|
||||
}
|
||||
this.discard();
|
||||
}
|
||||
|
||||
public void autoAim() {
|
||||
if (this.entityData.get(ENERGY) <= 0 || !entityData.get(ACTIVE) || this.entityData.get(COOL_DOWN) > 10) return;
|
||||
|
||||
Entity naerestEntity = seekNearLivingEntity(80);
|
||||
|
||||
if (naerestEntity != null) {
|
||||
Vec3 barrelRootPos = new Vec3(this.getX(), this.getY() + 1.390625f, this.getZ());
|
||||
Vec3 targetVec = barrelRootPos.vectorTo(naerestEntity.getEyePosition()).normalize();
|
||||
|
||||
double d0 = targetVec.x;
|
||||
double d1 = targetVec.y;
|
||||
double d2 = targetVec.z;
|
||||
double d3 = Math.sqrt(d0 * d0 + d2 * d2);
|
||||
this.setXRot(Mth.clamp(Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * 57.2957763671875))), -90, 40));
|
||||
float targetY = Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * 57.2957763671875) - 90.0F);
|
||||
|
||||
float diffY = Math.clamp(-90f, 90f, Mth.wrapDegrees(targetY - this.getYRot()));
|
||||
|
||||
this.setYRot(this.getYRot() + Mth.clamp(0.5f * diffY, -25f, 25f));
|
||||
this.setRot(this.getYRot(), this.getXRot());
|
||||
|
||||
if (this.entityData.get(COOL_DOWN) == 0 && VectorTool.calculateAngle(getViewVector(1), targetVec) < 1) {
|
||||
if (level() instanceof ServerLevel) {
|
||||
this.level().playSound(this, getOnPos(), ModSounds.CHARGE_RIFLE_FIRE_BOOM_3P.get(), SoundSource.PLAYERS, 2, 1);
|
||||
}
|
||||
naerestEntity.hurt(ModDamageTypes.causeLaserDamage(this.level().registryAccess(), getOwner(), getOwner()), (float) 25);
|
||||
naerestEntity.invulnerableTime = 0;
|
||||
entityData.set(LASER_LENGTH, distanceTo(naerestEntity));
|
||||
this.entityData.set(COOL_DOWN, 20);
|
||||
this.consumeEnergy(SHOOT_COST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Entity seekNearLivingEntity(double seekRange) {
|
||||
return StreamSupport.stream(EntityFindUtil.getEntities(level()).getAll().spliterator(), false)
|
||||
.filter(e -> {
|
||||
// TODO 自定义目标列表
|
||||
if (e.distanceTo(this) <= seekRange && e instanceof Monster) {
|
||||
return level().clip(new ClipContext(this.getEyePosition(), e.getEyePosition(),
|
||||
ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, this)).getType() != HitResult.Type.BLOCK;
|
||||
}
|
||||
return false;
|
||||
}).min(Comparator.comparingDouble(e -> e.distanceTo(this))).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private PlayState movementPredicate(AnimationState<LaserTowerEntity> event) {
|
||||
if (this.entityData.get(COOL_DOWN) > 10) {
|
||||
return event.setAndContinue(RawAnimation.begin().thenPlay("animation.lt.fire"));
|
||||
}
|
||||
return event.setAndContinue(RawAnimation.begin().thenLoop("animation.lt.idle"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerControllers(AnimatableManager.ControllerRegistrar data) {
|
||||
data.add(new AnimationController<>(this, "movement", 0, this::movementPredicate));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatableInstanceCache getAnimatableInstanceCache() {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxEnergy() {
|
||||
return MAX_ENERGY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMaxHealth() {
|
||||
return MAX_HEALTH;
|
||||
}
|
||||
}
|
|
@ -86,6 +86,8 @@ public class ModEntities {
|
|||
EntityType.Builder.<Bmp2Entity>of(Bmp2Entity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(Bmp2Entity::new).fireImmune().sized(4f, 3f));
|
||||
public static final RegistryObject<EntityType<WgMissileEntity>> WG_MISSILE = register("wg_missile",
|
||||
EntityType.Builder.<WgMissileEntity>of(WgMissileEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(WgMissileEntity::new).fireImmune().sized(0.5f, 0.5f));
|
||||
public static final RegistryObject<EntityType<LaserTowerEntity>> LASER_TOWER = register("laser_tower",
|
||||
EntityType.Builder.<LaserTowerEntity>of(LaserTowerEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(3).setCustomClientFactory(LaserTowerEntity::new).fireImmune().sized(0.9f, 1.65f));
|
||||
|
||||
private static <T extends Entity> RegistryObject<EntityType<T>> register(String name, EntityType.Builder<T> entityTypeBuilder) {
|
||||
return REGISTRY.register(name, () -> entityTypeBuilder.build(name));
|
||||
|
|
|
@ -41,5 +41,6 @@ public class ModEntityRenderers {
|
|||
event.registerEntityRenderer(ModEntities.MELON_BOMB.get(), MelonBombEntityRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.BMP_2.get(), Bmp2Renderer::new);
|
||||
event.registerEntityRenderer(ModEntities.WG_MISSILE.get(), WgMissileRenderer::new);
|
||||
event.registerEntityRenderer(ModEntities.LASER_TOWER.get(), LaserTowerRenderer::new);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@ public class ModTabs {
|
|||
output.accept(ContainerBlockItem.createInstance(ModEntities.MK_42.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.MLE_1934.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.ANNIHILATOR.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.LASER_TOWER.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.SPEEDBOAT.get(), true));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.AH_6.get()));
|
||||
output.accept(ContainerBlockItem.createInstance(ModEntities.LAV_150.get(),true));
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.lt.fire": {
|
||||
"loop": "hold_on_last_frame",
|
||||
"animation_length": 1,
|
||||
"bones": {
|
||||
"laser": {
|
||||
"scale": {
|
||||
"0.0": [0, 0, 1],
|
||||
"0.0083": [1.3, 1.3, 1],
|
||||
"0.1333": [1.3, 1.3, 1],
|
||||
"0.2667": [0, 0, 1],
|
||||
"0.9917": [0, 0, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.lt.idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"laser": {
|
||||
"scale": [0, 0, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
2427
src/main/resources/assets/superbwarfare/geo/laser_tower.geo.json
Normal file
2427
src/main/resources/assets/superbwarfare/geo/laser_tower.geo.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -406,6 +406,7 @@
|
|||
"entity.superbwarfare.melon_bomb": "Melon Bomb",
|
||||
"entity.superbwarfare.bmp_2": "BMP-2",
|
||||
"entity.superbwarfare.wg_missile": "Wire Guide Missile",
|
||||
"entity.superbwarfare.laser_tower": "Laser Defense Tower",
|
||||
|
||||
"key.categories.superbwarfare": "Superb Warfare",
|
||||
"key.superbwarfare.hold_zoom": "Zoom(Hold)",
|
||||
|
|
|
@ -404,6 +404,7 @@
|
|||
"entity.superbwarfare.melon_bomb": "西瓜航弹",
|
||||
"entity.superbwarfare.bmp_2": "BMP-2 履带式步兵战车",
|
||||
"entity.superbwarfare.wg_missile": "线控导弹",
|
||||
"entity.superbwarfare.laser_tower": "激光防御塔",
|
||||
|
||||
"key.categories.superbwarfare": "卓越前线",
|
||||
"key.superbwarfare.hold_zoom": "瞄准(按住)",
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"type": "minecraft:crafting_shaped",
|
||||
"category": "misc",
|
||||
"pattern": [
|
||||
" a ",
|
||||
" b ",
|
||||
"dcd"
|
||||
],
|
||||
"key": {
|
||||
"a": {
|
||||
"item": "minecraft:beacon"
|
||||
},
|
||||
"b": {
|
||||
"item": "superbwarfare:motor"
|
||||
},
|
||||
"c": {
|
||||
"item": "superbwarfare:cell"
|
||||
},
|
||||
"d": {
|
||||
"item": "minecraft:iron_ingot"
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"item": "superbwarfare:container",
|
||||
"nbt": {
|
||||
"BlockEntityTag": {
|
||||
"EntityType": "superbwarfare:laser_tower"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue