diff --git a/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java b/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java index 211339fc7..edd192157 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java @@ -155,7 +155,7 @@ public class ClickHandler { double scroll = event.getScrollDelta(); - if (stack.is(ModTags.Items.GUN) && player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new ModVariables.PlayerVariables()).zoom) { + if (stack.is(ModTags.Items.GUN) && ClientEventHandler.zoom) { var tag = stack.getOrCreateTag(); if (tag.getBoolean("CanSwitchScope")) { ModUtils.PACKET_HANDLER.sendToServer(new SwitchScopeMessage(scroll)); @@ -165,6 +165,11 @@ public class ClickHandler { event.setCanceled(true); } + if (player.getVehicle() instanceof IVehicleEntity iVehicle && iVehicle.isDriver(player) && ClientEventHandler.zoom) { + ClientEventHandler.vehicleFov = Mth.clamp(ClientEventHandler.vehicleFov + 0.4 * scroll, 1, 6); + event.setCanceled(true); + } + if (stack.is(ModItems.MONITOR.get()) && stack.getOrCreateTag().getBoolean("Using") && stack.getOrCreateTag().getBoolean("Linked")) { ClientEventHandler.droneFov = Mth.clamp(ClientEventHandler.droneFov + 0.4 * scroll, 1, 6); event.setCanceled(true); @@ -293,13 +298,13 @@ public class ClickHandler { ModUtils.PACKET_HANDLER.sendToServer(new DroneFireMessage(0)); } - if (player.getVehicle() != null && player.getVehicle() instanceof ICannonEntity) { + if (player.getVehicle() instanceof ICannonEntity) { ModUtils.PACKET_HANDLER.sendToServer(new VehicleFireMessage(0)); return; } - if ((player.getVehicle() != null && player.getVehicle() instanceof SpeedboatEntity boat && boat.getFirstPassenger() == player)) { - ModUtils.PACKET_HANDLER.sendToServer(new FireMessage(0)); + if (player.getVehicle() instanceof IVehicleEntity iVehicle && iVehicle.isDriver(player)) { + ClientEventHandler.holdFire = true; } if (stack.is(ModTags.Items.GUN) && !(player.getVehicle() != null && player.getVehicle() instanceof ICannonEntity)) { diff --git a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ProjectileEntityModel.java b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ProjectileEntityModel.java index 93917605b..9bed90adc 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ProjectileEntityModel.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/model/entity/ProjectileEntityModel.java @@ -1,9 +1,11 @@ package com.atsuishio.superbwarfare.client.model.entity; import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.entity.IVehicleEntity; import com.atsuishio.superbwarfare.entity.projectile.ProjectileEntity; import com.atsuishio.superbwarfare.event.ClientEventHandler; import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.init.ModTags; import net.minecraft.client.Minecraft; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; @@ -27,7 +29,8 @@ public class ProjectileEntityModel extends GeoModel { if ((ClientEventHandler.zoom && !player.getMainHandItem().is(ModItems.MINIGUN.get())) || player.getMainHandItem().is(ModItems.GLOCK_17.get()) || player.getMainHandItem().is(ModItems.GLOCK_18.get()) - || player.getMainHandItem().is(ModItems.BOCEK.get())) { + || player.getMainHandItem().is(ModItems.BOCEK.get()) + || (player.getVehicle() instanceof IVehicleEntity iVehicle && iVehicle.isDriver(player) && !player.getMainHandItem().is(ModTags.Items.GUN))) { return new ResourceLocation(ModUtils.MODID, "geo/projectile_entity.geo.json"); } else { return new ResourceLocation(ModUtils.MODID, "geo/projectile_entity2.geo.json"); diff --git a/src/main/java/com/atsuishio/superbwarfare/client/screens/VehicleMgHudOverlay.java b/src/main/java/com/atsuishio/superbwarfare/client/screens/VehicleMgHudOverlay.java new file mode 100644 index 000000000..a47d0802c --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/screens/VehicleMgHudOverlay.java @@ -0,0 +1,72 @@ +package com.atsuishio.superbwarfare.client.screens; + +import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.client.RenderHelper; +import com.atsuishio.superbwarfare.entity.SpeedboatEntity; +import com.atsuishio.superbwarfare.event.ClientEventHandler; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.RenderGuiEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +import java.text.DecimalFormat; + +import static com.atsuishio.superbwarfare.client.RenderHelper.preciseBlit; + +@Mod.EventBusSubscriber(value = Dist.CLIENT) +public class VehicleMgHudOverlay { + public static float indicatorPosH = 0; + + @SubscribeEvent(priority = EventPriority.NORMAL) + public static void eventHandler(RenderGuiEvent.Pre event) { + int w = event.getWindow().getGuiScaledWidth(); + int h = event.getWindow().getGuiScaledHeight(); + Player player = Minecraft.getInstance().player; + + if (!shouldRenderCrossHair(player)) return; + + Entity cannon = player.getVehicle(); + if (cannon == null) return; + + RenderSystem.disableDepthTest(); + RenderSystem.depthMask(false); + RenderSystem.enableBlend(); + RenderSystem.setShader(GameRenderer::getPositionTexShader); + RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + RenderSystem.setShaderColor(1, 1, 1, 1); + + float fovAdjust = (float) 70 / Minecraft.getInstance().options.fov().get(); + + float f = (float) Math.min(w, h); + float f1 = Math.min((float) w / f, (float) h / f) * fovAdjust; + int i = Mth.floor(f * f1); + int j = Mth.floor(f * f1); + int k = (w - i) / 2; + int l = (h - j) / 2; + RenderHelper.preciseBlit(event.getGuiGraphics(), ModUtils.loc("textures/screens/cannon/cannon_crosshair_notzoom.png"), k, l, 0, 0.0F, i, j, i, j); + + if (ClientEventHandler.vehicleFovLerp > 1.01) { + event.getGuiGraphics().blit(ModUtils.loc("textures/screens/drone_fov.png"), w / 2 + 100, h / 2 - 64, 0, 0, 64, 129, 64, 129); + GuiGraphics guiGraphics = event.getGuiGraphics(); + preciseBlit(guiGraphics, ModUtils.loc("textures/screens/drone_fov_move.png"), (float) w / 2 + 100, (float) (h / 2 - 64 - ((ClientEventHandler.vehicleFovLerp - 1) * 23.8)), 0, 0, 64, 129, 64, 129); + event.getGuiGraphics().drawString(Minecraft.getInstance().font, Component.literal(new DecimalFormat("##.#").format(ClientEventHandler.vehicleFovLerp) + "x"), + w / 2 + 144, h / 2 + 56 - (int) ((ClientEventHandler.vehicleFovLerp - 1) * 23.8), -1, false); + } + } + + private static boolean shouldRenderCrossHair(Player player) { + if (player == null) return false; + return !player.isSpectator() + && player.getVehicle() instanceof SpeedboatEntity && ClientEventHandler.zoom; + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/config/server/CannonConfig.java b/src/main/java/com/atsuishio/superbwarfare/config/server/CannonConfig.java index b175a286a..16333f3ca 100644 --- a/src/main/java/com/atsuishio/superbwarfare/config/server/CannonConfig.java +++ b/src/main/java/com/atsuishio/superbwarfare/config/server/CannonConfig.java @@ -105,7 +105,7 @@ public class CannonConfig { SPEEDBOAT_MAX_ENERGY = builder.defineInRange("speedboat_max_energy", 100000d, 0d, Double.POSITIVE_INFINITY); builder.comment("The gun damage of Speedboat"); - SPEEDBOAT_GUN_DAMAGE = builder.defineInRange("speedboat_gun_damage", 25, 1, 10000000); + SPEEDBOAT_GUN_DAMAGE = builder.defineInRange("speedboat_gun_damage", 45, 1, 10000000); builder.pop(); } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/AnnihilatorEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/AnnihilatorEntity.java index e74f72e9b..b3c90d0af 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/AnnihilatorEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/AnnihilatorEntity.java @@ -550,4 +550,19 @@ public class AnnihilatorEntity extends Entity implements GeoEntity, ICannonEntit public float getMaxHealth() { return (int)MAX_HEALTH; } + + @Override + public boolean isDriver(Player player) { + return false; + } + + @Override + public int mainGunRpm() { + return 0; + } + + @Override + public boolean canShoot(Player player) { + return true; + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/ICannonEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/ICannonEntity.java index bcbf5772a..ac513e654 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/ICannonEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/ICannonEntity.java @@ -1,9 +1,6 @@ package com.atsuishio.superbwarfare.entity; -import net.minecraft.world.entity.player.Player; - public interface ICannonEntity extends IVehicleEntity { - void cannonShoot(Player player); float getHealth(); float getMaxHealth(); } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/IVehicleEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/IVehicleEntity.java index adb570855..a8b6e8132 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/IVehicleEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/IVehicleEntity.java @@ -1,5 +1,12 @@ package com.atsuishio.superbwarfare.entity; + +import net.minecraft.world.entity.player.Player; + public interface IVehicleEntity { + void cannonShoot(Player player); float getHealth(); float getMaxHealth(); + boolean isDriver(Player player); + int mainGunRpm(); + boolean canShoot(Player player); } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/Mk42Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/Mk42Entity.java index 0b813de9c..370aec7cc 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/Mk42Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/Mk42Entity.java @@ -431,4 +431,18 @@ public class Mk42Entity extends Entity implements GeoEntity, ICannonEntity { return (int)MAX_HEALTH; } + @Override + public boolean isDriver(Player player) { + return false; + } + + @Override + public int mainGunRpm() { + return 0; + } + + @Override + public boolean canShoot(Player player) { + return true; + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/Mle1934Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/Mle1934Entity.java index a5ce97c2c..d0559d153 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/Mle1934Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/Mle1934Entity.java @@ -526,4 +526,18 @@ public class Mle1934Entity extends Entity implements GeoEntity, ICannonEntity { return (int)MAX_HEALTH; } + @Override + public boolean isDriver(Player player) { + return false; + } + + @Override + public int mainGunRpm() { + return 0; + } + + @Override + public boolean canShoot(Player player) { + return true; + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/SpeedboatEntity.java b/src/main/java/com/atsuishio/superbwarfare/entity/SpeedboatEntity.java index 6bff33663..d653fbbfd 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/SpeedboatEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/SpeedboatEntity.java @@ -85,13 +85,13 @@ import java.util.List; public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, IVehicleEntity, HasCustomInventoryScreen, ContainerEntity { + public static final EntityDataAccessor FIRE_ANIM = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.INT); public static final EntityDataAccessor HEALTH = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.FLOAT); public static final EntityDataAccessor ENERGY = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.FLOAT); public static final EntityDataAccessor ROT_Y = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.FLOAT); public static final EntityDataAccessor DELTA_ROT = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.FLOAT); public static final EntityDataAccessor POWER = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.FLOAT); public static final EntityDataAccessor ROTOR = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.FLOAT); - public static final EntityDataAccessor COOL_DOWN = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.INT); public static final EntityDataAccessor HEAT = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.INT); protected static final EntityDataAccessor LAST_ATTACKER_UUID = SynchedEntityData.defineId(SpeedboatEntity.class, EntityDataSerializers.STRING); @@ -127,13 +127,13 @@ public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, @Override protected void defineSynchedData() { + this.entityData.define(FIRE_ANIM, 0); this.entityData.define(HEALTH, MAX_HEALTH); this.entityData.define(ENERGY, 0f); this.entityData.define(ROT_Y, 0f); this.entityData.define(DELTA_ROT, 0f); this.entityData.define(POWER, 0f); this.entityData.define(ROTOR, 0f); - this.entityData.define(COOL_DOWN, 0); this.entityData.define(HEAT, 0); this.entityData.define(LAST_ATTACKER_UUID, "undefined"); } @@ -297,14 +297,14 @@ public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, public void baseTick() { super.baseTick(); - if (this.entityData.get(COOL_DOWN) > 0) { - this.entityData.set(COOL_DOWN, this.entityData.get(COOL_DOWN) - 1); - } - if (this.entityData.get(HEAT) > 0) { this.entityData.set(HEAT, this.entityData.get(HEAT) - 1); } + if (this.entityData.get(FIRE_ANIM) > 0) { + this.entityData.set(FIRE_ANIM, this.entityData.get(FIRE_ANIM) - 1); + } + if (this.entityData.get(HEAT) < 40) { cannotFire = false; } @@ -355,7 +355,6 @@ public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, collideBlock(); gunnerAngle(); - gunnerFire(); pickUpItem(); this.refreshDimensions(); @@ -373,89 +372,82 @@ public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, /** * 机枪塔开火 */ - private void gunnerFire() { - if (this.entityData.get(COOL_DOWN) != 0 || this.cannotFire) return; - Entity driver = this.getFirstPassenger(); - if (driver == null) return; + @Override + public void cannonShoot(Player player) { + if (this.cannotFire) return; - if (driver instanceof Player player && !(player.getMainHandItem().is(ModTags.Items.GUN))) { - if (this.getItemStacks().stream().noneMatch(stack -> stack.is(ModItems.HEAVY_AMMO.get())) && !player.getInventory().hasAnyMatching(s -> s.is(ModItems.CREATIVE_AMMO_BOX.get()))) - return; - if (player.getCapability(ModVariables.PLAYER_VARIABLES_CAPABILITY, null).orElse(new ModVariables.PlayerVariables()).holdFire) { + ProjectileEntity projectile = new ProjectileEntity(player.level()) + .shooter(player) + .damage(CannonConfig.SPEEDBOAT_GUN_DAMAGE.get()) + .headShot(2f) + .zoom(false); - ProjectileEntity projectile = new ProjectileEntity(driver.level()) - .shooter(player) - .damage(CannonConfig.SPEEDBOAT_GUN_DAMAGE.get()) - .headShot(2f) - .zoom(false); + if (this.getItemStacks().size() > 102) { + ItemStack perkItem = this.getItemStacks().get(102); + if (perkItem.getItem() instanceof PerkItem perk) { + if (perk.getPerk() == ModPerks.SILVER_BULLET.get()) { + projectile.undeadMultiple(2.5f); + } else if (perk.getPerk() == ModPerks.BEAST_BULLET.get()) { + projectile.beast(); + } else if (perk.getPerk() == ModPerks.JHP_BULLET.get()) { + projectile.jhpBullet(true, 3); + } else if (perk.getPerk() == ModPerks.HE_BULLET.get()) { + projectile.heBullet(true, 3); + } else if (perk.getPerk() == ModPerks.INCENDIARY_BULLET.get()) { + projectile.fireBullet(true, 3, false); + } - projectile.bypassArmorRate(0.9f); - projectile.setPos(this.xo - this.getViewVector(1).scale(0.54).x - this.getDeltaMovement().x, this.yo + 3.0, this.zo - this.getViewVector(1).scale(0.54).z - this.getDeltaMovement().z); - projectile.shoot(player, player.getLookAngle().x, player.getLookAngle().y + (zooming() ? 0.002f : -0.009f), player.getLookAngle().z, 20, - (float) 0.4); - this.level().addFreshEntity(projectile); - - if (this.getItemStacks().size() > 102) { - ItemStack perkItem = this.getItemStacks().get(102); - if (perkItem.getItem() instanceof PerkItem perk) { - if (perk.getPerk() == ModPerks.SILVER_BULLET.get()) { - projectile.undeadMultiple(2.5f); - } else if (perk.getPerk() == ModPerks.BEAST_BULLET.get()) { - projectile.beast(); - } else if (perk.getPerk() == ModPerks.JHP_BULLET.get()) { - projectile.jhpBullet(true, 3); - } else if (perk.getPerk() == ModPerks.HE_BULLET.get()) { - projectile.heBullet(true, 3); - } else if (perk.getPerk() == ModPerks.INCENDIARY_BULLET.get()) { - projectile.fireBullet(true, 3, false); - } - - if (perk.getPerk() instanceof AmmoPerk ammoPerk) { - projectile.setRGB(ammoPerk.rgb); - if (!ammoPerk.mobEffects.get().isEmpty()) { - ArrayList mobEffectInstances = new ArrayList<>(); - for (MobEffect effect : ammoPerk.mobEffects.get()) { - mobEffectInstances.add(new MobEffectInstance(effect, 160, 2)); - } - projectile.effect(mobEffectInstances); - } + if (perk.getPerk() instanceof AmmoPerk ammoPerk) { + projectile.setRGB(ammoPerk.rgb); + if (!ammoPerk.mobEffects.get().isEmpty()) { + ArrayList mobEffectInstances = new ArrayList<>(); + for (MobEffect effect : ammoPerk.mobEffects.get()) { + mobEffectInstances.add(new MobEffectInstance(effect, 160, 2)); } + projectile.effect(mobEffectInstances); } } - - if (this.getItemStacks().size() > 104) { - ItemStack perkItem = this.getItemStacks().get(104); - if (perkItem.getItem() instanceof PerkItem perk) { - if (perk.getPerk() == ModPerks.MONSTER_HUNTER.get()) { - projectile.monsterMultiple(0.5f); - } - } - } - - float pitch = this.entityData.get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * java.lang.Math.abs(60 - this.entityData.get(HEAT))); - - if (player instanceof ServerPlayer serverPlayer) { - SoundTool.playLocalSound(serverPlayer, ModSounds.M_2_FIRE_1P.get(), 2, 1); - serverPlayer.level().playSound(null, serverPlayer.getOnPos(), ModSounds.M_2_FIRE_3P.get(), SoundSource.PLAYERS, 4, pitch); - serverPlayer.level().playSound(null, serverPlayer.getOnPos(), ModSounds.M_2_FAR.get(), SoundSource.PLAYERS, 12, pitch); - serverPlayer.level().playSound(null, serverPlayer.getOnPos(), ModSounds.M_2_VERYFAR.get(), SoundSource.PLAYERS, 24, pitch); - } - - Level level = player.level(); - final Vec3 center = new Vec3(this.getX(), this.getEyeY(), this.getZ()); - - 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) { - ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new ShakeClientMessage(6, 5, 5, this.getX(), this.getEyeY(), this.getZ())); - } - } - if (level instanceof ServerLevel) { - this.entityData.set(COOL_DOWN, 3); - this.entityData.set(HEAT, this.entityData.get(HEAT) + 4); - } - this.getItemStacks().stream().filter(stack -> stack.is(ModItems.HEAVY_AMMO.get())).findFirst().ifPresent(stack -> stack.shrink(1)); } } + + if (this.getItemStacks().size() > 104) { + ItemStack perkItem = this.getItemStacks().get(104); + if (perkItem.getItem() instanceof PerkItem perk) { + if (perk.getPerk() == ModPerks.MONSTER_HUNTER.get()) { + projectile.monsterMultiple(0.5f); + } + } + } + + projectile.bypassArmorRate(0.9f); + projectile.setPos(this.xo - this.getViewVector(1).scale(0.54).x - this.getDeltaMovement().x, this.yo + 3.0, this.zo - this.getViewVector(1).scale(0.54).z - this.getDeltaMovement().z); + projectile.shoot(player, player.getLookAngle().x, player.getLookAngle().y + (zooming() ? 0.002f : -0.009f), player.getLookAngle().z, 20, + (float) 0.4); + this.level().addFreshEntity(projectile); + + float pitch = this.entityData.get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * java.lang.Math.abs(60 - this.entityData.get(HEAT))); + + if (!player.level().isClientSide) { + if (player instanceof ServerPlayer serverPlayer) { + serverPlayer.playSound(ModSounds.M_2_FIRE_3P.get(), 4, pitch); + serverPlayer.playSound(ModSounds.M_2_FAR.get(), 12, pitch); + serverPlayer.playSound(ModSounds.M_2_VERYFAR.get(), 24, pitch); + } + } + + + Level level = player.level(); + final Vec3 center = new Vec3(this.getX(), this.getEyeY(), this.getZ()); + + 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) { + ModUtils.PACKET_HANDLER.send(PacketDistributor.PLAYER.with(() -> serverPlayer), new ShakeClientMessage(6, 5, 5, this.getX(), this.getEyeY(), this.getZ())); + } + } + + this.entityData.set(HEAT, this.entityData.get(HEAT) + 3); + this.entityData.set(FIRE_ANIM, 3); + this.getItemStacks().stream().filter(stack -> stack.is(ModItems.HEAVY_AMMO.get())).findFirst().ifPresent(stack -> stack.shrink(1)); } /** @@ -543,7 +535,7 @@ public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, level().playLocalSound(this.getX(), this.getY() + this.getBbHeight() * 0.5, this.getZ(), this.getEngineSound(), this.getSoundSource(), Math.min((this.getPersistentData().getBoolean("forward") || this.getPersistentData().getBoolean("backward") ? 7.5f : 5f) * 2 * Mth.abs(this.entityData.get(POWER)), 0.25f), (random.nextFloat() * 0.1f + 1f), false); } - this.entityData.set(POWER, this.entityData.get(POWER) * 0.9f); + this.entityData.set(POWER, this.entityData.get(POWER) * 0.87f); this.entityData.set(ROTOR, this.entityData.get(ROTOR) + this.entityData.get(POWER)); this.entityData.set(DELTA_ROT, this.entityData.get(DELTA_ROT) * 0.8f); @@ -724,9 +716,10 @@ public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, } private PlayState firePredicate(AnimationState event) { - if (this.entityData.get(COOL_DOWN) > 1 && !cannotFire) { + if (this.entityData.get(FIRE_ANIM) > 1) { return event.setAndContinue(RawAnimation.begin().thenPlay("animation.speedboat.fire")); } + return event.setAndContinue(RawAnimation.begin().thenLoop("animation.speedboat.idle")); } @@ -911,4 +904,21 @@ public class SpeedboatEntity extends Entity implements GeoEntity, IChargeEntity, public float getMaxHealth() { return (int) MAX_HEALTH; } + + @Override + public boolean isDriver(Player player) { + return player == this.getFirstPassenger(); + } + + @Override + public int mainGunRpm() { + return 500; + } + + @Override + public boolean canShoot(Player player) { + return (this.getItemStacks().stream().anyMatch(stack -> stack.is(ModItems.HEAVY_AMMO.get())) || player.getInventory().hasAnyMatching(s -> s.is(ModItems.CREATIVE_AMMO_BOX.get()))) + && !player.getMainHandItem().is(ModTags.Items.GUN) + && !cannotFire; + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java index cdaeed8f5..16569483d 100644 --- a/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/event/ClientEventHandler.java @@ -5,11 +5,13 @@ import com.atsuishio.superbwarfare.client.ClickHandler; import com.atsuishio.superbwarfare.config.client.DisplayConfig; import com.atsuishio.superbwarfare.entity.DroneEntity; import com.atsuishio.superbwarfare.entity.ICannonEntity; +import com.atsuishio.superbwarfare.entity.IVehicleEntity; import com.atsuishio.superbwarfare.entity.SpeedboatEntity; import com.atsuishio.superbwarfare.init.*; import com.atsuishio.superbwarfare.network.ModVariables; import com.atsuishio.superbwarfare.network.message.LaserShootMessage; import com.atsuishio.superbwarfare.network.message.ShootMessage; +import com.atsuishio.superbwarfare.network.message.VehicleFireMessage; import com.atsuishio.superbwarfare.perk.AmmoPerk; import com.atsuishio.superbwarfare.perk.Perk; import com.atsuishio.superbwarfare.perk.PerkHelper; @@ -51,6 +53,8 @@ import software.bernie.geckolib.core.animatable.model.CoreGeoBone; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; +import static com.atsuishio.superbwarfare.entity.SpeedboatEntity.HEAT; + @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT) public class ClientEventHandler { @@ -110,6 +114,7 @@ public class ClientEventHandler { public static double customZoom = 0; public static MillisTimer clientTimer = new MillisTimer(); + public static MillisTimer clientTimerVehicle = new MillisTimer(); public static boolean holdFire = false; @@ -131,6 +136,8 @@ public class ClientEventHandler { public static double shakeAmplitude = 0; public static double[] shakePos = {0, 0, 0}; public static double shakeType = 0; + public static double vehicleFov = 1; + public static double vehicleFovLerp = 1; @SubscribeEvent public static void handleWeaponTurn(RenderHandEvent event) { @@ -537,6 +544,59 @@ public class ClientEventHandler { }); } + @SubscribeEvent + public static void handleVehicleFire(TickEvent.RenderTickEvent event) { + ClientLevel level = Minecraft.getInstance().level; + Player player = Minecraft.getInstance().player; + if (player == null) return; + if (level == null) return; + + if (player.getVehicle() instanceof IVehicleEntity iVehicle && iVehicle.isDriver(player) && iVehicle.canShoot(player)) { + int rpm = iVehicle.mainGunRpm(); + if (rpm == 0) { + rpm = 240; + } + +// player.displayClientMessage(Component.literal("114 : " + clientTimerVehicle.getProgress()), true); + + double rps = (double) rpm / 60; + + // cooldown in ms + int cooldown = (int) (1000 / rps); + + if ((holdFire)) { + if (!clientTimerVehicle.started()) { + clientTimerVehicle.start(); + // 首发瞬间发射 + clientTimerVehicle.setProgress((cooldown + 1)); + } + if (clientTimerVehicle.getProgress() >= cooldown) { + ModUtils.PACKET_HANDLER.sendToServer(new VehicleFireMessage(0)); + playVehicleClientSounds(player, iVehicle); + clientTimerVehicle.setProgress((clientTimerVehicle.getProgress() - cooldown)); + } + + if (notInGame()) { + clientTimerVehicle.stop(); + } + + } else { + clientTimerVehicle.stop(); + } + + } else { + clientTimerVehicle.stop(); + } + } + + public static void playVehicleClientSounds(Player player, IVehicleEntity iVehicle) { + if (iVehicle instanceof SpeedboatEntity speedboat) { + float pitch = speedboat.getEntityData().get(HEAT) <= 60 ? 1 : (float) (1 - 0.011 * java.lang.Math.abs(60 - speedboat.getEntityData().get(HEAT))); + player.playSound(ModSounds.M_2_FIRE_1P.get(), 1f, pitch); + player.playSound(ModSounds.SHELL_CASING_50CAL.get(),0.3f, 1); + } + } + @SubscribeEvent public static void handleWeaponBreathSway(TickEvent.RenderTickEvent event) { Player player = Minecraft.getInstance().player; @@ -1142,6 +1202,13 @@ public class ClientEventHandler { event.setFOV(event.getFOV() / droneFovLerp); } + + if (player.getVehicle() instanceof IVehicleEntity && !(player.getVehicle() instanceof ICannonEntity) && zoom) { + + vehicleFovLerp = Mth.lerp(0.1 * Minecraft.getInstance().getDeltaFrameTime(), vehicleFovLerp, vehicleFov); + + event.setFOV(event.getFOV() / vehicleFovLerp); + } } @SubscribeEvent @@ -1168,6 +1235,10 @@ public class ClientEventHandler { return; } + if (mc.player.getVehicle() instanceof SpeedboatEntity && zoom) { + event.setCanceled(true); + } + if (mc.player.getMainHandItem().is(ModTags.Items.GUN) || (mc.player.getVehicle() != null && mc.player.getVehicle() instanceof ICannonEntity)) { event.setCanceled(true); } diff --git a/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java b/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java index 94fbb9e6a..76c402aa6 100644 --- a/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java +++ b/src/main/java/com/atsuishio/superbwarfare/mixins/MouseHandlerMixin.java @@ -1,6 +1,7 @@ package com.atsuishio.superbwarfare.mixins; import com.atsuishio.superbwarfare.entity.ICannonEntity; +import com.atsuishio.superbwarfare.entity.IVehicleEntity; import com.atsuishio.superbwarfare.event.ClientEventHandler; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModMobEffects; @@ -16,6 +17,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyVariable; import static com.atsuishio.superbwarfare.event.ClientEventHandler.droneFovLerp; +import static com.atsuishio.superbwarfare.event.ClientEventHandler.vehicleFovLerp; /** * Author: MrCrayfish @@ -50,6 +52,10 @@ public class MouseHandlerMixin { return 0.33 / (1 + 0.08 * (droneFovLerp - 1)); } + if (player.getVehicle() instanceof IVehicleEntity iVehicle && iVehicle.isDriver(player) && ClientEventHandler.zoom) { + return 0.33 / (1 + 0.08 * (vehicleFovLerp - 1)); + } + if (!stack.is(ModTags.Items.GUN)) { return original; } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/message/VehicleFireMessage.java b/src/main/java/com/atsuishio/superbwarfare/network/message/VehicleFireMessage.java index 6c4cfb658..0f2c8edee 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/message/VehicleFireMessage.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/message/VehicleFireMessage.java @@ -1,6 +1,6 @@ package com.atsuishio.superbwarfare.network.message; -import com.atsuishio.superbwarfare.entity.ICannonEntity; +import com.atsuishio.superbwarfare.entity.IVehicleEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.level.Level; import net.minecraftforge.network.NetworkEvent; @@ -34,7 +34,7 @@ public class VehicleFireMessage { return; } - if (player.getVehicle() instanceof ICannonEntity entity) { + if (player.getVehicle() instanceof IVehicleEntity entity) { entity.cannonShoot(player); } } diff --git a/src/main/resources/assets/superbwarfare/sounds/m2/m2_fire_1p.ogg b/src/main/resources/assets/superbwarfare/sounds/m2/m2_fire_1p.ogg index 1c8a9f1fe..b356d674c 100644 Binary files a/src/main/resources/assets/superbwarfare/sounds/m2/m2_fire_1p.ogg and b/src/main/resources/assets/superbwarfare/sounds/m2/m2_fire_1p.ogg differ