diff --git a/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java b/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java index 59a2b5d31..ffdec8fcc 100644 --- a/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/client/ClickHandler.java @@ -11,6 +11,7 @@ import com.atsuishio.superbwarfare.entity.vehicle.base.CannonEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity; import com.atsuishio.superbwarfare.entity.vehicle.base.WeaponVehicleEntity; import com.atsuishio.superbwarfare.event.ClientEventHandler; +import com.atsuishio.superbwarfare.event.ClientMouseHandler; import com.atsuishio.superbwarfare.init.*; import com.atsuishio.superbwarfare.item.gun.GunItem; import com.atsuishio.superbwarfare.network.message.send.*; @@ -151,6 +152,13 @@ public class ClickHandler { double scroll = event.getScrollDeltaY(); + // 按下自由视角键时,为具有自由视角功能的载具调整相机距离 + if (player.getVehicle() instanceof VehicleEntity vehicle && vehicle.allowFreeCam() && player == vehicle.getFirstPassenger() && ModKeyMappings.FREE_CAMERA.isDown()) { + ClientMouseHandler.custom3pDistance = Mth.clamp(ClientMouseHandler.custom3pDistance - event.getScrollDeltaY(), -3, 8); + event.setCanceled(true); + return; + } + // 未按下shift时,为有武器的载具切换武器 if (!Screen.hasShiftDown() && player.getVehicle() instanceof VehicleEntity vehicle diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/A10Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/A10Entity.java index 5a2958ddb..4cda1a8be 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/A10Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/A10Entity.java @@ -6,6 +6,7 @@ import com.atsuishio.superbwarfare.config.server.VehicleConfig; import com.atsuishio.superbwarfare.entity.vehicle.base.*; import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier; import com.atsuishio.superbwarfare.entity.vehicle.weapon.*; +import com.atsuishio.superbwarfare.event.ClientMouseHandler; import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModParticleTypes; @@ -1061,13 +1062,13 @@ public class A10Entity extends ContainerMobileVehicleEntity implements GeoEntity if (this.getSeatIndex(player) == 0) { Matrix4f transform = getClientVehicleTransform(partialTicks); - - Vector4f worldPosition = transformPosition(transform, 0f, 4, -14); + Vector4f maxCameraPosition = transformPosition(transform, 0, 4, -14 - (float) ClientMouseHandler.custom3pDistanceLerp); + Vec3 finalPos = CameraTool.getMaxZoom(transform, maxCameraPosition); if (isFirstPerson) { return new Vec3(Mth.lerp(partialTicks, player.xo, player.getX()), Mth.lerp(partialTicks, player.yo + player.getEyeHeight(), player.getEyeY()), Mth.lerp(partialTicks, player.zo, player.getZ())); } else { - return new Vec3(worldPosition.x, worldPosition.y, worldPosition.z); + return finalPos; } } return super.getCameraPosition(partialTicks, player, false, false); diff --git a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Ah6Entity.java b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Ah6Entity.java index d6ac0b901..fdd24d978 100644 --- a/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Ah6Entity.java +++ b/src/main/java/com/atsuishio/superbwarfare/entity/vehicle/Ah6Entity.java @@ -12,13 +12,11 @@ import com.atsuishio.superbwarfare.entity.vehicle.damage.DamageModifier; import com.atsuishio.superbwarfare.entity.vehicle.weapon.HeliRocketWeapon; import com.atsuishio.superbwarfare.entity.vehicle.weapon.SmallCannonShellWeapon; import com.atsuishio.superbwarfare.entity.vehicle.weapon.VehicleWeapon; +import com.atsuishio.superbwarfare.event.ClientMouseHandler; import com.atsuishio.superbwarfare.init.ModDamageTypes; import com.atsuishio.superbwarfare.init.ModItems; import com.atsuishio.superbwarfare.init.ModSounds; -import com.atsuishio.superbwarfare.tools.Ammo; -import com.atsuishio.superbwarfare.tools.CustomExplosion; -import com.atsuishio.superbwarfare.tools.InventoryTool; -import com.atsuishio.superbwarfare.tools.ParticleTool; +import com.atsuishio.superbwarfare.tools.*; import com.mojang.math.Axis; import it.unimi.dsi.fastutil.Pair; import net.minecraft.core.particles.ParticleTypes; @@ -676,6 +674,21 @@ public class Ah6Entity extends ContainerMobileVehicleEntity implements GeoEntity return seatIndex == 0 ? 0 : original; } + @Override + public double getMouseSensitivity() { + return 0.15; + } + + @Override + public double getMouseSpeedX() { + return 0.35; + } + + @Override + public double getMouseSpeedY() { + return 0.2; + } + @OnlyIn(Dist.CLIENT) @Nullable public Pair getPassengerRotation(Entity entity, float tickDelta) { @@ -711,14 +724,13 @@ public class Ah6Entity extends ContainerMobileVehicleEntity implements GeoEntity public Vec3 getCameraPosition(float partialTicks, Player player, boolean zoom, boolean isFirstPerson) { if (this.getSeatIndex(player) == 0) { Matrix4f transform = getClientVehicleTransform(partialTicks); - - - Vector4f worldPosition = transformPosition(transform, -2.1f, 1, -10); + Vector4f maxCameraPosition = transformPosition(transform, -2.1f, 1, -10 - (float) ClientMouseHandler.custom3pDistanceLerp); + Vec3 finalPos = CameraTool.getMaxZoom(transform, maxCameraPosition); if (isFirstPerson) { return new Vec3(Mth.lerp(partialTicks, player.xo, player.getX()), Mth.lerp(partialTicks, player.yo + player.getEyeHeight(), player.getEyeY()), Mth.lerp(partialTicks, player.zo, player.getZ())); } else { - return new Vec3(worldPosition.x, worldPosition.y, worldPosition.z); + return finalPos; } } return super.getCameraPosition(partialTicks, player, false, false); diff --git a/src/main/java/com/atsuishio/superbwarfare/event/ClientMouseHandler.java b/src/main/java/com/atsuishio/superbwarfare/event/ClientMouseHandler.java index 795560c68..b54e740f4 100644 --- a/src/main/java/com/atsuishio/superbwarfare/event/ClientMouseHandler.java +++ b/src/main/java/com/atsuishio/superbwarfare/event/ClientMouseHandler.java @@ -43,6 +43,9 @@ public class ClientMouseHandler { public static double freeCameraPitch = 0; public static double freeCameraYaw = 0; + public static double custom3pDistance = 0; + public static double custom3pDistanceLerp = 0; + private static boolean notInGame() { Minecraft mc = Minecraft.getInstance(); if (mc.player == null) return true; @@ -78,8 +81,15 @@ public class ClientMouseHandler { } if (!notInGame() && player.getVehicle() instanceof VehicleEntity vehicle && player == vehicle.getFirstPassenger()) { + + int y = 1; + + if (vehicle instanceof AirEntity && VehicleControlConfig.INVERT_AIRCRAFT_CONTROL.get()) { + y = -1; + } + speedX = vehicle.getMouseSensitivity() * (posN.x - posO.x); - speedY = vehicle.getMouseSensitivity() * (posN.y - posO.y); + speedY = y * vehicle.getMouseSensitivity() * (posN.y - posO.y); lerpSpeedX = Mth.lerp(vehicle.getMouseSpeedX(), lerpSpeedX, speedX); lerpSpeedY = Mth.lerp(vehicle.getMouseSpeedY(), lerpSpeedY, speedY); @@ -120,10 +130,10 @@ public class ClientMouseHandler { if (isFreeCam(player)) { freeCameraYaw -= 0.4f * times * lerpSpeedX; - freeCameraPitch += 0.2f * times * lerpSpeedY; + freeCameraPitch += 0.3f * times * lerpSpeedY; } else { - freeCameraYaw = Mth.lerp(0.075 * event.getPartialTick(), freeCameraYaw, 0); - freeCameraPitch = Mth.lerp(0.075 * event.getPartialTick(), freeCameraPitch, 0); + freeCameraYaw = Mth.lerp(0.2 * times, freeCameraYaw, 0); + freeCameraPitch = Mth.lerp(0.2 * times, freeCameraPitch, 0); } while (freeCameraYaw > 180F) { @@ -139,10 +149,12 @@ public class ClientMouseHandler { freeCameraPitch += 360; } - if (player.getVehicle() instanceof AirEntity) { + if (player.getVehicle() instanceof VehicleEntity vehicle && player == vehicle.getFirstPassenger() && vehicle instanceof AirEntity) { player.setYRot(player.getVehicle().getYRot()); player.setYHeadRot(player.getYRot()); } + + custom3pDistanceLerp = Mth.lerp(times, custom3pDistanceLerp, custom3pDistance); } @SubscribeEvent diff --git a/src/main/java/com/atsuishio/superbwarfare/tools/CameraTool.java b/src/main/java/com/atsuishio/superbwarfare/tools/CameraTool.java new file mode 100644 index 000000000..2a2048fd4 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/tools/CameraTool.java @@ -0,0 +1,33 @@ +package com.atsuishio.superbwarfare.tools; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import org.joml.Matrix4f; +import org.joml.Vector4f; + +public class CameraTool { + public static Vec3 getMaxZoom(Matrix4f transform, Vector4f maxCameraPos) { + Minecraft mc = Minecraft.getInstance(); + Player player = mc.player; + + Vector4f vehiclePos = transformPosition(transform, 0, 0, 0); + Vec3 maxCameraPosVec3 = new Vec3(maxCameraPos.x, maxCameraPos.y, maxCameraPos.z); + Vec3 vehiclePosVec3 = new Vec3(vehiclePos.x, vehiclePos.y, vehiclePos.z); + Vec3 toVec = vehiclePosVec3.vectorTo(maxCameraPosVec3); + + if (player != null) { + HitResult hitresult = player.level().clip(new ClipContext(vehiclePosVec3, vehiclePosVec3.add(toVec), ClipContext.Block.VISUAL, ClipContext.Fluid.NONE, player)); + if (hitresult.getType() == HitResult.Type.BLOCK) { + return hitresult.getLocation().add(toVec.normalize().scale(-0.25)); + } + } + return maxCameraPosVec3; + } + + public static Vector4f transformPosition(Matrix4f transform, float x, float y, float z) { + return transform.transform(new Vector4f(x, y, z, 1)); + } +}