添加小型炮弹实体和lav150开火动画及音效

This commit is contained in:
Atsuihsio 2025-01-13 18:32:08 +08:00
parent 44066ed7f2
commit d5cdc8082c
24 changed files with 515 additions and 54 deletions

View file

@ -0,0 +1,28 @@
package com.atsuishio.superbwarfare.client.layer;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.vehicle.Lav150Entity;
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 Lav150Layer extends GeoRenderLayer<Lav150Entity> {
private static final ResourceLocation LAYER = ModUtils.loc("textures/entity/speedboat_e.png");
public Lav150Layer(GeoRenderer<Lav150Entity> entityRenderer) {
super(entityRenderer);
}
@Override
public void render(PoseStack poseStack, Lav150Entity 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);
}
}

View file

@ -0,0 +1,27 @@
package com.atsuishio.superbwarfare.client.layer;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.projectile.SmallCannonShellEntity;
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 SmallCannonShellLayer extends GeoRenderLayer<SmallCannonShellEntity> {
private static final ResourceLocation LAYER = new ResourceLocation(ModUtils.MODID, "textures/entity/cannon_shell_e.png");
public SmallCannonShellLayer(GeoRenderer<SmallCannonShellEntity> entityRenderer) {
super(entityRenderer);
}
@Override
public void render(PoseStack poseStack, SmallCannonShellEntity animatable, BakedGeoModel bakedModel, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight, int packedOverlay) {
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);
}
}

View file

@ -9,7 +9,7 @@ public class Lav150Model extends GeoModel<Lav150Entity> {
@Override @Override
public ResourceLocation getAnimationResource(Lav150Entity entity) { public ResourceLocation getAnimationResource(Lav150Entity entity) {
return null; return ModUtils.loc("animations/lav.animation.json");
} }
@Override @Override

View file

@ -0,0 +1,34 @@
package com.atsuishio.superbwarfare.client.model.entity;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.entity.projectile.SmallCannonShellEntity;
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;
public class SmallCannonShellModel extends GeoModel<SmallCannonShellEntity> {
@Override
public ResourceLocation getAnimationResource(SmallCannonShellEntity entity) {
return ModUtils.loc("animations/cannon_shell.animation.json");
}
@Override
public ResourceLocation getModelResource(SmallCannonShellEntity entity) {
return ModUtils.loc("geo/cannon_shell.geo.json");
}
@Override
public ResourceLocation getTextureResource(SmallCannonShellEntity entity) {
return ModUtils.loc("textures/entity/cannon_shell.png");
}
@Override
public void setCustomAnimations(SmallCannonShellEntity animatable, long instanceId, AnimationState animationState) {
CoreGeoBone bone = getAnimationProcessor().getBone("bone");
bone.setScaleX(0.17f);
bone.setScaleY(0.17f);
bone.setScaleZ(0.17f);
}
}

View file

@ -1,5 +1,6 @@
package com.atsuishio.superbwarfare.client.renderer.entity; package com.atsuishio.superbwarfare.client.renderer.entity;
import com.atsuishio.superbwarfare.client.layer.Lav150Layer;
import com.atsuishio.superbwarfare.client.model.entity.Lav150Model; import com.atsuishio.superbwarfare.client.model.entity.Lav150Model;
import com.atsuishio.superbwarfare.entity.vehicle.Lav150Entity; import com.atsuishio.superbwarfare.entity.vehicle.Lav150Entity;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
@ -18,6 +19,7 @@ public class Lav150Renderer extends GeoEntityRenderer<Lav150Entity> {
public Lav150Renderer(EntityRendererProvider.Context renderManager) { public Lav150Renderer(EntityRendererProvider.Context renderManager) {
super(renderManager, new Lav150Model()); super(renderManager, new Lav150Model());
this.addRenderLayer(new Lav150Layer(this));
} }
@Override @Override

View file

@ -0,0 +1,45 @@
package com.atsuishio.superbwarfare.client.renderer.entity;
import com.atsuishio.superbwarfare.client.layer.SmallCannonShellLayer;
import com.atsuishio.superbwarfare.client.model.entity.SmallCannonShellModel;
import com.atsuishio.superbwarfare.entity.projectile.SmallCannonShellEntity;
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.renderer.GeoEntityRenderer;
public class SmallCannonShellRenderer extends GeoEntityRenderer<SmallCannonShellEntity> {
public SmallCannonShellRenderer(EntityRendererProvider.Context renderManager) {
super(renderManager, new SmallCannonShellModel());
this.addRenderLayer(new SmallCannonShellLayer(this));
}
@Override
public RenderType getRenderType(SmallCannonShellEntity animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) {
return RenderType.entityTranslucent(getTextureLocation(animatable));
}
@Override
public void preRender(PoseStack poseStack, SmallCannonShellEntity 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(SmallCannonShellEntity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
poseStack.pushPose();
poseStack.mulPose(Axis.YP.rotationDegrees(Mth.lerp(partialTicks, entityIn.yRotO, entityIn.getYRot()) - 90));
poseStack.mulPose(Axis.ZP.rotationDegrees(90 + Mth.lerp(partialTicks, entityIn.xRotO, entityIn.getXRot())));
super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
poseStack.popPose();
}
}

View file

@ -81,8 +81,6 @@ public class GunGrenadeEntity extends ThrowableItemProjectile implements GeoEnti
float damageMultiplier = 1 + this.monsterMultiplier; float damageMultiplier = 1 + this.monsterMultiplier;
Entity entity = result.getEntity(); Entity entity = result.getEntity();
if (entity == this.getOwner() || entity == this.getVehicle()) return;
if (this.getOwner() instanceof LivingEntity living) { if (this.getOwner() instanceof LivingEntity living) {
if (!living.level().isClientSide() && living instanceof ServerPlayer player) { if (!living.level().isClientSide() && living instanceof ServerPlayer player) {
living.level().playSound(null, living.blockPosition(), ModSounds.INDICATION.get(), SoundSource.VOICE, 1, 1); living.level().playSound(null, living.blockPosition(), ModSounds.INDICATION.get(), SoundSource.VOICE, 1, 1);

View file

@ -588,7 +588,7 @@ public class ProjectileEntity extends Entity implements IEntityAdditionalSpawnDa
explosion.explode(); explosion.explode();
net.minecraftforge.event.ForgeEventFactory.onExplosionStart(projectile.level(), explosion); net.minecraftforge.event.ForgeEventFactory.onExplosionStart(projectile.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
ParticleTool.spawnSmallExplosionParticles(this.level(), hitVec); ParticleTool.spawnMiniExplosionParticles(this.level(), hitVec);
} }
protected void explosionBulletEntity(Entity projectile, Entity target, float damage, int heLevel, float monsterMultiple) { protected void explosionBulletEntity(Entity projectile, Entity target, float damage, int heLevel, float monsterMultiple) {
@ -598,7 +598,7 @@ public class ProjectileEntity extends Entity implements IEntityAdditionalSpawnDa
explosion.explode(); explosion.explode();
net.minecraftforge.event.ForgeEventFactory.onExplosionStart(projectile.level(), explosion); net.minecraftforge.event.ForgeEventFactory.onExplosionStart(projectile.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
ParticleTool.spawnSmallExplosionParticles(target.level(), target.position()); ParticleTool.spawnMiniExplosionParticles(target.level(), target.position());
} }
public void setDamage(float damage) { public void setDamage(float damage) {

View file

@ -93,7 +93,6 @@ public class RgoGrenadeEntity extends ThrowableItemProjectile implements GeoEnti
case ENTITY: case ENTITY:
EntityHitResult entityResult = (EntityHitResult) result; EntityHitResult entityResult = (EntityHitResult) result;
Entity entity = entityResult.getEntity(); Entity entity = entityResult.getEntity();
if (entity == this.getOwner() || entity == this.getVehicle()) return;
if (this.getOwner() instanceof LivingEntity living) { if (this.getOwner() instanceof LivingEntity living) {
if (!living.level().isClientSide() && living instanceof ServerPlayer player) { if (!living.level().isClientSide() && living instanceof ServerPlayer player) {
living.level().playSound(null, living.blockPosition(), ModSounds.INDICATION.get(), SoundSource.VOICE, 1, 1); living.level().playSound(null, living.blockPosition(), ModSounds.INDICATION.get(), SoundSource.VOICE, 1, 1);

View file

@ -0,0 +1,150 @@
package com.atsuishio.superbwarfare.entity.projectile;
import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.init.ModDamageTypes;
import com.atsuishio.superbwarfare.init.ModEntities;
import com.atsuishio.superbwarfare.init.ModItems;
import com.atsuishio.superbwarfare.init.ModSounds;
import com.atsuishio.superbwarfare.network.message.ClientIndicatorMessage;
import com.atsuishio.superbwarfare.tools.ParticleTool;
import com.atsuishio.superbwarfare.tools.ProjectileTool;
import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BellBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.PlayMessages;
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.util.GeckoLibUtil;
public class SmallCannonShellEntity extends ThrowableItemProjectile implements GeoEntity {
private float damage = 40.0f;
private float explosionDamage = 80f;
private float explosionRadius = 5f;
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
public SmallCannonShellEntity(EntityType<? extends SmallCannonShellEntity> type, Level world) {
super(type, world);
this.noCulling = true;
}
public SmallCannonShellEntity(LivingEntity entity, Level level, float damage, float explosionDamage, float explosionRadius) {
super(ModEntities.GUN_GRENADE.get(), entity, level);
this.damage = damage;
this.explosionDamage = explosionDamage;
this.explosionRadius = explosionRadius;
}
public SmallCannonShellEntity(PlayMessages.SpawnEntity spawnEntity, Level level) {
this(ModEntities.SMALL_CANNON_SHELL.get(), level);
}
@Override
public Packet<ClientGamePacketListener> getAddEntityPacket() {
return NetworkHooks.getEntitySpawningPacket(this);
}
@Override
protected Item getDefaultItem() {
return ModItems.GRENADE_40MM.get();
}
@Override
public boolean shouldRenderAtSqrDistance(double pDistance) {
return true;
}
@Override
protected void onHitEntity(EntityHitResult result) {
Entity entity = result.getEntity();
if (this.getOwner() instanceof LivingEntity living) {
if (!living.level().isClientSide() && living instanceof ServerPlayer player) {
living.level().playSound(null, living.blockPosition(), ModSounds.INDICATION.get(), SoundSource.VOICE, 1, 1);
ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> player), new ClientIndicatorMessage(0, 5));
}
}
entity.hurt(ModDamageTypes.causeGunFireHeadshotDamage(this.level().registryAccess(), this, this.getOwner()), damage);
if (entity instanceof LivingEntity) {
entity.invulnerableTime = 0;
}
if (this.tickCount > 1) {
if (this.level() instanceof ServerLevel) {
ProjectileTool.causeCustomExplode(this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), this, this.getOwner()),
entity, this.explosionDamage, this.explosionRadius, 1.25f);
}
}
this.discard();
}
@Override
public void onHitBlock(BlockHitResult blockHitResult) {
super.onHitBlock(blockHitResult);
BlockPos resultPos = blockHitResult.getBlockPos();
BlockState state = this.level().getBlockState(resultPos);
if (state.getBlock() instanceof BellBlock bell) {
bell.attemptToRing(this.level(), resultPos, blockHitResult.getDirection());
}
if (this.tickCount > 1) {
if (this.level() instanceof ServerLevel) {
ProjectileTool.causeCustomExplode(this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), this, this.getOwner()),
this, this.explosionDamage, this.explosionRadius, 1.25f);
}
this.discard();
}
}
@Override
public void tick() {
super.tick();
if (!this.level().isClientSide() && this.level() instanceof ServerLevel serverLevel) {
ParticleTool.sendParticle(serverLevel, ParticleTypes.SMOKE, this.xo, this.yo, this.zo,
1, 0, 0, 0, 0.02, true);
}
if (onGround()) {
this.setDeltaMovement(0,0,0);
}
if (this.tickCount > 200 || this.isInWater()) {
if (this.level() instanceof ServerLevel && !onGround()) {
ProjectileTool.causeCustomExplode(this,
ModDamageTypes.causeProjectileBoomDamage(this.level().registryAccess(), this, this.getOwner()),
this, this.explosionDamage, this.explosionRadius, 1.25f);
}
this.discard();
}
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar data) {
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.cache;
}
}

View file

@ -3,7 +3,7 @@ package com.atsuishio.superbwarfare.entity.vehicle;
import com.atsuishio.superbwarfare.ModUtils; import com.atsuishio.superbwarfare.ModUtils;
import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig; import com.atsuishio.superbwarfare.config.server.ExplosionDestroyConfig;
import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.config.server.VehicleConfig;
import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity; import com.atsuishio.superbwarfare.entity.projectile.SmallCannonShellEntity;
import com.atsuishio.superbwarfare.init.*; import com.atsuishio.superbwarfare.init.*;
import com.atsuishio.superbwarfare.network.ModVariables; import com.atsuishio.superbwarfare.network.ModVariables;
import com.atsuishio.superbwarfare.network.message.ShakeClientMessage; import com.atsuishio.superbwarfare.network.message.ShakeClientMessage;
@ -48,6 +48,10 @@ import org.joml.Vector4f;
import software.bernie.geckolib.animatable.GeoEntity; import software.bernie.geckolib.animatable.GeoEntity;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache; import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager; 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 software.bernie.geckolib.util.GeckoLibUtil;
import java.util.Comparator; import java.util.Comparator;
@ -231,9 +235,6 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
return false; return false;
} }
/**
* 机枪塔开火
*/
@Override @Override
public void vehicleShoot(Player player) { public void vehicleShoot(Player player) {
if (this.cannotFire) return; if (this.cannotFire) return;
@ -246,17 +247,29 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
Vector4f worldPosition = transformPosition(transform, x, y, z); Vector4f worldPosition = transformPosition(transform, x, y, z);
ProjectileEntity projectile = new ProjectileEntity(player.level()) // ProjectileEntity projectile = new ProjectileEntity(player.level())
.shooter(player) // .shooter(player)
.damage(VehicleConfig.SPEEDBOAT_GUN_DAMAGE.get()) // .damage(80)
.headShot(2f) // .headShot(3f)
.zoom(false); // .zoom(false);
//
// projectile.heBullet(true, 5);
// projectile.bypassArmorRate(1);
// projectile.setPos(worldPosition.x - 1.1 * this.getDeltaMovement().x, worldPosition.y, worldPosition.z - 1.1 * this.getDeltaMovement().z);
// projectile.shoot(player, getBarrelVector(1).x, getBarrelVector(1).y + 0.002f, getBarrelVector(1).z, 20,
// (float) 0.4);
// this.level().addFreshEntity(projectile);
projectile.bypassArmorRate(0.9f); SmallCannonShellEntity smallCannonShell = new SmallCannonShellEntity(player, this.level(),
projectile.setPos(worldPosition.x - 1.1 * this.getDeltaMovement().x, worldPosition.y, worldPosition.z - 1.1 * this.getDeltaMovement().z); 50,
projectile.shoot(player, getBarrelVector(1).x, getBarrelVector(1).y + 0.002f, getBarrelVector(1).z, 20, 40,
(float) 0.4); 4.5f);
this.level().addFreshEntity(projectile);
smallCannonShell.setPos(worldPosition.x - 1.1 * this.getDeltaMovement().x, worldPosition.y, worldPosition.z - 1.1 * this.getDeltaMovement().z);
smallCannonShell.shoot(getBarrelVector(1).x, getBarrelVector(1).y + 0.005f, getBarrelVector(1).z, 15,
0.5f);
this.level().addFreshEntity(smallCannonShell);
sendParticle((ServerLevel) this.level(), ParticleTypes.LARGE_SMOKE, worldPosition.x - 1.1 * this.getDeltaMovement().x, worldPosition.y, worldPosition.z - 1.1 * this.getDeltaMovement().z, 1, 0.02, 0.02, 0.02, 0, false); sendParticle((ServerLevel) this.level(), ParticleTypes.LARGE_SMOKE, worldPosition.x - 1.1 * this.getDeltaMovement().x, worldPosition.y, worldPosition.z - 1.1 * this.getDeltaMovement().z, 1, 0.02, 0.02, 0.02, 0, false);
@ -264,9 +277,9 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
if (!player.level().isClientSide) { if (!player.level().isClientSide) {
if (player instanceof ServerPlayer serverPlayer) { if (player instanceof ServerPlayer serverPlayer) {
serverPlayer.playSound(ModSounds.M_2_FIRE_3P.get(), 4, pitch); serverPlayer.playSound(ModSounds.LAV_CANNON_FIRE_3P.get(), 4, pitch);
serverPlayer.playSound(ModSounds.M_2_FAR.get(), 12, pitch); serverPlayer.playSound(ModSounds.LAV_CANNON_FAR.get(), 12, pitch);
serverPlayer.playSound(ModSounds.M_2_VERYFAR.get(), 24, pitch); serverPlayer.playSound(ModSounds.LAV_CANNON_VERYFAR.get(), 24, pitch);
} }
} }
@ -275,11 +288,11 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
for (Entity target : level.getEntitiesOfClass(Entity.class, new AABB(center, center).inflate(4), e -> true).stream().sorted(Comparator.comparingDouble(e -> e.distanceToSqr(center))).toList()) { for (Entity target : level.getEntitiesOfClass(Entity.class, new AABB(center, center).inflate(4), e -> true).stream().sorted(Comparator.comparingDouble(e -> e.distanceToSqr(center))).toList()) {
if (target instanceof ServerPlayer serverPlayer) { if (target instanceof ServerPlayer serverPlayer) {
ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new ShakeClientMessage(6, 5, 5, this.getX(), this.getEyeY(), this.getZ())); ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new ShakeClientMessage(6, 5, 9, this.getX(), this.getEyeY(), this.getZ()));
} }
} }
this.entityData.set(HEAT, this.entityData.get(HEAT) + 3); this.entityData.set(HEAT, this.entityData.get(HEAT) + 6);
this.entityData.set(FIRE_ANIM, 3); this.entityData.set(FIRE_ANIM, 3);
this.getItemStacks().stream().filter(stack -> stack.is(ModItems.HEAVY_AMMO.get())).findFirst().ifPresent(stack -> stack.shrink(1)); this.getItemStacks().stream().filter(stack -> stack.is(ModItems.HEAVY_AMMO.get())).findFirst().ifPresent(stack -> stack.shrink(1));
} }
@ -502,17 +515,17 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
this.clampRotation(entity); this.clampRotation(entity);
} }
// private PlayState firePredicate(AnimationState<Lav150Entity> event) { private PlayState firePredicate(AnimationState<Lav150Entity> event) {
// if (this.entityData.get(FIRE_ANIM) > 1) { if (this.entityData.get(FIRE_ANIM) > 1) {
// return event.setAndContinue(RawAnimation.begin().thenPlay("animation.speedboat.fire")); return event.setAndContinue(RawAnimation.begin().thenPlay("animation.lav.fire"));
// } }
//
// return event.setAndContinue(RawAnimation.begin().thenLoop("animation.speedboat.idle")); return event.setAndContinue(RawAnimation.begin().thenLoop("animation.lav.idle"));
// } }
@Override @Override
public void registerControllers(AnimatableManager.ControllerRegistrar data) { public void registerControllers(AnimatableManager.ControllerRegistrar data) {
// data.add(new AnimationController<>(this, "movement", 0, this::firePredicate)); data.add(new AnimationController<>(this, "movement", 0, this::firePredicate));
} }
@Override @Override
@ -547,7 +560,7 @@ public class Lav150Entity extends ContainerMobileEntity implements GeoEntity, IC
@Override @Override
public int mainGunRpm() { public int mainGunRpm() {
return 240; return 180;
} }
@Override @Override

View file

@ -409,24 +409,18 @@ public class ClientEventHandler {
} else { } else {
if (!clientTimer.started()) { if (!clientTimer.started()) {
clientTimer.start(); clientTimer.start();
// 首发瞬间发射 shootClient(player);
clientTimer.setProgress((cooldown + 1));
} }
if (clientTimer.getProgress() >= cooldown) { if (clientTimer.getProgress() >= cooldown) {
shootClient(player); clientTimer.stop();
clientTimer.setProgress((clientTimer.getProgress() - cooldown));
} }
} }
if (notInGame()) { if (notInGame()) {
clientTimer.stop(); clientTimer.stop();
} }
} else { } else {
if (mode != 0) {
clientTimer.stop();
}
fireSpread = 0; fireSpread = 0;
} }
@ -659,23 +653,17 @@ public class ClientEventHandler {
} }
double rps = (double) rpm / 60; double rps = (double) rpm / 60;
// cooldown in ms
int cooldown = (int) (1000 / rps); int cooldown = (int) (1000 / rps);
if ((holdFire)) { if ((holdFire)) {
if (!clientTimerVehicle.started()) { if (!clientTimerVehicle.started()) {
clientTimerVehicle.start(); clientTimerVehicle.start();
// 首发瞬间发射
clientTimerVehicle.setProgress((cooldown + 1));
}
if (clientTimerVehicle.getProgress() >= cooldown) {
ModUtils.PACKET_HANDLER.sendToServer(new VehicleFireMessage(0)); ModUtils.PACKET_HANDLER.sendToServer(new VehicleFireMessage(0));
playVehicleClientSounds(player, iVehicle); playVehicleClientSounds(player, iVehicle);
clientTimerVehicle.setProgress((clientTimerVehicle.getProgress() - cooldown));
} }
} else { if (clientTimerVehicle.getProgress() >= cooldown) {
clientTimerVehicle.stop(); clientTimerVehicle.stop();
}
} }
} else { } else {
clientTimerVehicle.stop(); clientTimerVehicle.stop();
@ -694,7 +682,11 @@ public class ClientEventHandler {
} else if (ah6Entity.getEntityData().get(WEAPON_TYPE) == 1) { } else if (ah6Entity.getEntityData().get(WEAPON_TYPE) == 1) {
player.playSound(ModSounds.HELICOPTER_ROCKET_FIRE_1P.get(), 1f, 1); player.playSound(ModSounds.HELICOPTER_ROCKET_FIRE_1P.get(), 1f, 1);
} }
}
if (iVehicle instanceof Lav150Entity lav150) {
float pitch = lav150.getEntityData().get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * java.lang.Math.abs(60 - lav150.getEntityData().get(HEAT)));
player.playSound(ModSounds.LAV_CANNON_FIRE_1P.get(), 1f, pitch);
player.playSound(ModSounds.SHELL_CASING_50CAL.get(), 0.3f, 1);
} }
} }

View file

@ -46,6 +46,8 @@ public class ModEntities {
.setUpdateInterval(1).sized(0.5f, 0.5f)); .setUpdateInterval(1).sized(0.5f, 0.5f));
public static final RegistryObject<EntityType<GunGrenadeEntity>> GUN_GRENADE = register("projectile_gun_grenade", public static final RegistryObject<EntityType<GunGrenadeEntity>> GUN_GRENADE = register("projectile_gun_grenade",
EntityType.Builder.<GunGrenadeEntity>of(GunGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(GunGrenadeEntity::new).sized(0.5f, 0.5f)); EntityType.Builder.<GunGrenadeEntity>of(GunGrenadeEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(GunGrenadeEntity::new).sized(0.5f, 0.5f));
public static final RegistryObject<EntityType<SmallCannonShellEntity>> SMALL_CANNON_SHELL = register("projectile_small_cannon_shell",
EntityType.Builder.<SmallCannonShellEntity>of(SmallCannonShellEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(SmallCannonShellEntity::new).sized(0.5f, 0.5f));
public static final RegistryObject<EntityType<RpgRocketEntity>> RPG_ROCKET = register("projectile_rpg_rocket", public static final RegistryObject<EntityType<RpgRocketEntity>> RPG_ROCKET = register("projectile_rpg_rocket",
EntityType.Builder.<RpgRocketEntity>of(RpgRocketEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(RpgRocketEntity::new).sized(0.5f, 0.5f)); EntityType.Builder.<RpgRocketEntity>of(RpgRocketEntity::new, MobCategory.MISC).setShouldReceiveVelocityUpdates(true).setTrackingRange(64).setUpdateInterval(1).setCustomClientFactory(RpgRocketEntity::new).sized(0.5f, 0.5f));
public static final RegistryObject<EntityType<MortarShellEntity>> MORTAR_SHELL = register("projectile_mortar_shell", public static final RegistryObject<EntityType<MortarShellEntity>> MORTAR_SHELL = register("projectile_mortar_shell",

View file

@ -35,5 +35,6 @@ public class ModEntityRenderers {
event.registerEntityRenderer(ModEntities.AH_6.get(), Ah6Renderer::new); event.registerEntityRenderer(ModEntities.AH_6.get(), Ah6Renderer::new);
event.registerEntityRenderer(ModEntities.FLARE_DECOY.get(), FlareDecoyEntityRenderer::new); event.registerEntityRenderer(ModEntities.FLARE_DECOY.get(), FlareDecoyEntityRenderer::new);
event.registerEntityRenderer(ModEntities.LAV_150.get(), Lav150Renderer::new); event.registerEntityRenderer(ModEntities.LAV_150.get(), Lav150Renderer::new);
event.registerEntityRenderer(ModEntities.SMALL_CANNON_SHELL.get(), SmallCannonShellRenderer::new);
} }
} }

View file

@ -396,5 +396,9 @@ public class ModSounds {
public static final RegistryObject<SoundEvent> DECOY_FIRE = REGISTRY.register("decoy_fire", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("decoy_fire"))); public static final RegistryObject<SoundEvent> DECOY_FIRE = REGISTRY.register("decoy_fire", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("decoy_fire")));
public static final RegistryObject<SoundEvent> DECOY_RELOAD = REGISTRY.register("decoy_reload", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("decoy_reload"))); public static final RegistryObject<SoundEvent> DECOY_RELOAD = REGISTRY.register("decoy_reload", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("decoy_reload")));
public static final RegistryObject<SoundEvent> LUNGE_MINE_GROWL = REGISTRY.register("lunge_mine_growl", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("lunge_mine_growl"))); public static final RegistryObject<SoundEvent> LUNGE_MINE_GROWL = REGISTRY.register("lunge_mine_growl", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("lunge_mine_growl")));
public static final RegistryObject<SoundEvent> LAV_CANNON_FIRE_1P = REGISTRY.register("lav_cannon_fire_1p", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("lav_fire_1p")));
public static final RegistryObject<SoundEvent> LAV_CANNON_FIRE_3P = REGISTRY.register("lav_cannon_fire_3p", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("lav_fire_3p")));
public static final RegistryObject<SoundEvent> LAV_CANNON_FAR = REGISTRY.register("lav_cannon_far", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("lav_far")));
public static final RegistryObject<SoundEvent> LAV_CANNON_VERYFAR = REGISTRY.register("lav_cannon_veryfar", () -> SoundEvent.createVariableRangeEvent(ModUtils.loc("lav_veryfar")));
} }

View file

@ -26,14 +26,20 @@ public class ParticleTool {
level.sendParticles(viewer, particle, force, x, y, z, count, xOffset, yOffset, zOffset, speed); level.sendParticles(viewer, particle, force, x, y, z, count, xOffset, yOffset, zOffset, speed);
} }
public static void spawnSmallExplosionParticles(Level level, Vec3 pos) { public static void spawnMiniExplosionParticles(Level level, Vec3 pos) {
double x = pos.x; double x = pos.x;
double y = pos.y; double y = pos.y;
double z = pos.z; double z = pos.z;
if (!level.isClientSide()) { if (!level.isClientSide()) {
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 2, 1);
}
level.playSound(null, BlockPos.containing(x, y + 1, z), SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 4, 1); level.playSound(null, BlockPos.containing(x, y + 1, z), SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 4, 1);
} else { } else {
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 1, 1, false);
}
level.playLocalSound(x, (y + 1), z, SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 2, 1, false); level.playLocalSound(x, (y + 1), z, SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 2, 1, false);
} }
@ -44,6 +50,38 @@ public class ParticleTool {
} }
} }
public static void spawnSmallExplosionParticles(Level level, Vec3 pos) {
double x = pos.x;
double y = pos.y;
double z = pos.z;
if (!level.isClientSide()) {
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 2, 1);
}
level.playSound(null, BlockPos.containing(x, y + 1, z), SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 4, 1);
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 3, 1);
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_FAR.get(), SoundSource.BLOCKS, 6, 1);
level.playSound(null, BlockPos.containing(x, y + 1, z), ModSounds.EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 12, 1);
} else {
if ((level.getBlockState(BlockPos.containing(x, y, z))).getBlock() == Blocks.WATER) {
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_WATER.get(), SoundSource.BLOCKS, 1, 1, false);
}
level.playLocalSound(x, (y + 1), z, SoundEvents.FIREWORK_ROCKET_BLAST, SoundSource.BLOCKS, 2, 1, false);
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_CLOSE.get(), SoundSource.BLOCKS, 1, 1, false);
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
level.playLocalSound(x, (y + 1), z, ModSounds.EXPLOSION_VERY_FAR.get(), SoundSource.BLOCKS, 1, 1, false);
}
if (level instanceof ServerLevel serverLevel) {
sendParticle(serverLevel, ParticleTypes.EXPLOSION, x, y + 1, z, 4, 0.25, 0.25, 0.25, 1, true);
sendParticle(serverLevel, ParticleTypes.CAMPFIRE_COSY_SMOKE, x, y, z, 3, 0.1, 0.1, 0.1, 0.02, true);
sendParticle(serverLevel, ParticleTypes.LARGE_SMOKE, x, y, z, 4, 0.2, 0.2, 0.2, 0.02, true);
sendParticle(serverLevel, ModParticleTypes.FIRE_STAR.get(), x, y, z, 20, 0, 0, 0, 0.6, true);
sendParticle(serverLevel, ParticleTypes.FLASH, x, y + 0.2, z, 20, 0.1, 0.1, 0.1, 20, true);
}
}
public static void spawnMediumExplosionParticles(Level level, Vec3 pos) { public static void spawnMediumExplosionParticles(Level level, Vec3 pos) {
double x = pos.x; double x = pos.x;
double y = pos.y; double y = pos.y;

View file

@ -17,7 +17,14 @@ public class ProjectileTool {
explosion.explode(); explosion.explode();
net.minecraftforge.event.ForgeEventFactory.onExplosionStart(projectile.level(), explosion); net.minecraftforge.event.ForgeEventFactory.onExplosionStart(projectile.level(), explosion);
explosion.finalizeExplosion(false); explosion.finalizeExplosion(false);
ParticleTool.spawnMediumExplosionParticles(projectile.level(), projectile.position()); if (radius <= 5) {
ParticleTool.spawnSmallExplosionParticles(projectile.level(), projectile.position());
} else if (radius > 5 && radius < 10) {
ParticleTool.spawnMediumExplosionParticles(projectile.level(), projectile.position());
} else {
ParticleTool.spawnHugeExplosionParticles(projectile.level(), projectile.position());
}
projectile.discard(); projectile.discard();
} }

View file

@ -0,0 +1,44 @@
{
"format_version": "1.8.0",
"animations": {
"animation.lav.fire": {
"animation_length": 0.4,
"bones": {
"barrel2": {
"position": {
"0.0": [0, 0, 0],
"0.0417": {
"pre": [0, 0, 6.1],
"post": [0, 0, 6.1],
"lerp_mode": "catmullrom"
},
"0.1": {
"post": [0, 0, 6.26563],
"lerp_mode": "catmullrom"
},
"0.1833": [0, 0, 3],
"0.275": [0, 0, 0]
}
},
"flare": {
"scale": {
"0.0": [0, 0, 0],
"0.0083": [8, 8, 8],
"0.05": [11, 11, 11],
"0.075": [1, 1, 1],
"0.0917": [0, 0, 0],
"0.15": [0, 0, 0]
}
}
}
},
"animation.lav.idle": {
"animation_length": 0.25,
"bones": {
"flare": {
"scale": 0
}
}
}
}
}

View file

@ -3005,6 +3005,51 @@
"parent": "cannon", "parent": "cannon",
"pivot": [0.375, 43.8072, -13.2] "pivot": [0.375, 43.8072, -13.2]
}, },
{
"name": "flare",
"parent": "barrel",
"pivot": [0.375, 45.61482, -63.67799],
"cubes": [
{
"origin": [-0.35251, 44.88732, -63.73986],
"size": [1.455, 1.455, 0],
"uv": {
"north": {"uv": [512, 0], "uv_size": [-128, 128]},
"south": {"uv": [384, 0], "uv_size": [128, 128]}
}
},
{
"origin": [-1.45501, 45.00731, -64.52738],
"size": [3.66, 1.215, 0],
"pivot": [0.37499, 45.61482, -64.52736],
"rotation": [0, -90, -60],
"uv": {
"north": {"uv": [512, 0], "uv_size": [-103, 128]},
"south": {"uv": [409, 0], "uv_size": [103, 128]}
}
},
{
"origin": [-1.45501, 45.00731, -64.52738],
"size": [3.66, 1.215, 0],
"pivot": [0.37499, 45.61482, -64.52736],
"rotation": [0, -90, -120],
"uv": {
"north": {"uv": [512, 0], "uv_size": [-103, 128]},
"south": {"uv": [409, 0], "uv_size": [103, 128]}
}
},
{
"origin": [-1.45501, 45.00731, -64.52738],
"size": [3.66, 1.215, 0],
"pivot": [0.37499, 45.61482, -64.52736],
"rotation": [0, -90, 0],
"uv": {
"north": {"uv": [512, 0], "uv_size": [-103, 128]},
"south": {"uv": [409, 0], "uv_size": [103, 128]}
}
}
]
},
{ {
"name": "barrel2", "name": "barrel2",
"parent": "barrel", "parent": "barrel",

View file

@ -2704,5 +2704,37 @@
"stream": false "stream": false
} }
] ]
},
"lav_fire_1p": {
"sounds": [
{
"name": "superbwarfare:lav/lav_fire_1p",
"stream": false
}
]
},
"lav_fire_3p": {
"sounds": [
{
"name": "superbwarfare:lav/lav_fire_3p",
"stream": false
}
]
},
"lav_far": {
"sounds": [
{
"name": "superbwarfare:lav/lav_far",
"stream": false
}
]
},
"lav_veryfar": {
"sounds": [
{
"name": "superbwarfare:lav/lav_veryfar",
"stream": false
}
]
} }
} }