From d9ce8ca3b5ed953fed65f7889da8ed1cfb4065f3 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Sun, 15 May 2022 13:53:11 +0700 Subject: [PATCH] Plasma weapon heating, hud and energy usage --- .../mc/otm/client/render/RenderHelper.java | 17 ++- .../ru/dbotthepony/mc/otm/core/EuclidMath.kt | 9 ++ .../ru/dbotthepony/mc/otm/core/RGBAColor.kt | 15 ++- .../mc/otm/item/weapon/AbstractWeaponItem.kt | 72 ++++++++++- .../mc/otm/item/weapon/PlasmaRifleItem.kt | 122 ++---------------- .../mc/otm/item/weapon/PlasmaWeaponItem.kt | 103 ++++++++++++++- .../mc/otm/item/weapon/VelocityCalculation.kt | 114 ++++++++++++++++ .../mc/otm/registry/MSoundEvents.kt | 6 +- .../overdrive_that_matters/lang/en_us.json | 6 +- .../assets/overdrive_that_matters/sounds.json | 6 + 10 files changed, 347 insertions(+), 123 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/VelocityCalculation.kt diff --git a/src/main/java/ru/dbotthepony/mc/otm/client/render/RenderHelper.java b/src/main/java/ru/dbotthepony/mc/otm/client/render/RenderHelper.java index 0a4bd7405..2945b6f9d 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/client/render/RenderHelper.java +++ b/src/main/java/ru/dbotthepony/mc/otm/client/render/RenderHelper.java @@ -340,6 +340,8 @@ public class RenderHelper { private static RGBAColor draw_color = new RGBAColor(255, 255, 255, 255); + public static boolean forwardWinding = true; + /** * Draws a solid color rectangle on screen, defined by last setDrawColor(RGBColor rect_color) call * @@ -368,10 +370,17 @@ public class RenderHelper { builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); - builder.vertex(matrix, x, y + height, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); - builder.vertex(matrix, x + width, y + height, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); - builder.vertex(matrix, x + width, y, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); - builder.vertex(matrix, x, y, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + if (forwardWinding) { + builder.vertex(matrix, x, y + height, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + builder.vertex(matrix, x + width, y + height, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + builder.vertex(matrix, x + width, y, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + builder.vertex(matrix, x, y, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + } else { + builder.vertex(matrix, x, y, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + builder.vertex(matrix, x + width, y, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + builder.vertex(matrix, x + width, y + height, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + builder.vertex(matrix, x, y + height, depth_z).color(draw_color.getRed(), draw_color.getGreen(), draw_color.getBlue(), draw_color.getAlpha()).endVertex(); + } tess.end(); diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt index 041aee99f..348a52b90 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/EuclidMath.kt @@ -261,6 +261,15 @@ data class MutableAngle(override var pitch: Double = 0.0, override var yaw: Doub } } +fun linearInterpolation(t: Float, a: Float, b: Float): Float { + if (t <= 0f) + return a + else if (t >= 1f) + return b + + return a + t * (b - a) +} + fun linearInterpolation(t: Double, a: Double, b: Double): Double { if (t <= 0.0) return a diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt index 78f675cb5..db008b641 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt @@ -41,6 +41,15 @@ data class RGBAColor(val red: Float, val green: Float, val blue: Float, val alph RenderHelper.setDrawColor(this) } + fun linearInterpolation(t: Float, other: RGBAColor): RGBAColor { + return RGBAColor( + linearInterpolation(t, red, other.red), + linearInterpolation(t, green, other.green), + linearInterpolation(t, blue, other.blue), + linearInterpolation(t, alpha, other.alpha), + ) + } + companion object { val BLACK = RGBAColor(0f, 0f, 0f, 1f) val WHITE = RGBAColor(1f, 1f, 1f, 1f) @@ -55,4 +64,8 @@ data class RGBAColor(val red: Float, val green: Float, val blue: Float, val alph return RGBAColor(a, b, g, r) } } -} \ No newline at end of file +} + +fun linearInterpolation(t: Float, a: RGBAColor, b: RGBAColor): RGBAColor { + return a.linearInterpolation(t, b) +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt index 85cc3014f..ac7d5c26e 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/AbstractWeaponItem.kt @@ -1,11 +1,15 @@ package ru.dbotthepony.mc.otm.item.weapon +import com.mojang.blaze3d.systems.RenderSystem +import com.mojang.blaze3d.vertex.* import com.mojang.math.Vector3f import net.minecraft.client.Minecraft import net.minecraft.client.model.HumanoidModel +import net.minecraft.client.renderer.GameRenderer import net.minecraft.client.renderer.block.model.ItemTransforms import net.minecraft.nbt.CompoundTag import net.minecraft.network.FriendlyByteBuf +import net.minecraft.server.level.ServerPlayer import net.minecraft.world.entity.Entity import net.minecraft.world.entity.player.Player import net.minecraft.world.item.Item @@ -20,9 +24,14 @@ import net.minecraftforge.event.TickEvent import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.fml.LogicalSide import net.minecraftforge.network.NetworkEvent +import org.lwjgl.opengl.GL30 import ru.dbotthepony.mc.otm.* +import ru.dbotthepony.mc.otm.capability.matteryEnergy +import ru.dbotthepony.mc.otm.client.font +import ru.dbotthepony.mc.otm.client.render.RenderHelper import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.Vector +import ru.dbotthepony.mc.otm.menu.FormattingHelper import ru.dbotthepony.mc.otm.network.MatteryNetworking import java.util.* import java.util.function.Supplier @@ -104,7 +113,7 @@ open class WeaponDataTable(val tag: CompoundTag) { var fireAnim = 0.0 var fireAnimDeviation = Angle.ZERO - fun doFireAnim(amount: Double = 1.0, deviation: Angle? = null) { + fun doFireAnim(amount: Double = 0.8, deviation: Angle? = null) { fireAnim = (fireAnim + amount).coerceAtLeast(0.0).coerceAtMost(1.0) if (deviation != null) { @@ -225,8 +234,17 @@ abstract class AbstractWeaponItem(val tables: KClass, ra return false } + open fun canPrimaryFire(itemStack: ItemStack, player: Player, dt: D = dataTable(itemStack)): Boolean { + if (player is ServerPlayer) { + // allow a little deviation, becuse nothing is perfect + return dt.nextPrimaryFire <= 2 + } + + return dt.nextPrimaryFire <= 0 + } + fun tryPrimaryFire(itemStack: ItemStack, player: Player, dt: D = dataTable(itemStack)): Boolean { - if (dt.nextPrimaryFire <= 0 && primaryFire(itemStack, player, dt)) { + if (canPrimaryFire(itemStack, player, dt) && primaryFire(itemStack, player, dt)) { dt.nextPrimaryFire = fireCooldown return true } @@ -357,7 +375,7 @@ abstract class AbstractWeaponItem(val tables: KClass, ra (item as AbstractWeaponItem).dataTable = predictedData predictedData?.deployTime = (predictedData!!.deployTime + diff.toDouble() / (300_000_000.0 * item.deployAnimSpeed)).coerceAtMost(1.0).coerceAtLeast(0.0) - predictedData?.fireAnim = (predictedData!!.fireAnim - diff.toDouble() / (300_000_000.0 * item.fireAnimRecovery)).coerceAtMost(1.0).coerceAtLeast(0.0) + predictedData?.fireAnim = (predictedData!!.fireAnim - diff.toDouble() / (400_000_000.0 * item.fireAnimRecovery)).coerceAtMost(1.0).coerceAtLeast(0.0) val player = Minecraft.getInstance().player!! val pose = event.poseStack @@ -404,9 +422,9 @@ abstract class AbstractWeaponItem(val tables: KClass, ra ) val rotFire = item.rotFireAnim - pitch += (rotFire.pitch + (predictedData?.fireAnimDeviation?.pitch ?: 0.0)) * fireAnim - yaw += (rotFire.yaw + (predictedData?.fireAnimDeviation?.yaw ?: 0.0)) * fireAnim - roll += (rotFire.roll + (predictedData?.fireAnimDeviation?.roll ?: 0.0)) * fireAnim + pitch += (rotFire.pitch + (predictedData?.fireAnimDeviation?.pitch ?: 0.0)) * fireAnim * (1.0 - progress * 0.6) + yaw += (rotFire.yaw + (predictedData?.fireAnimDeviation?.yaw ?: 0.0)) * fireAnim * (1.0 - progress * 0.6) + roll += (rotFire.roll + (predictedData?.fireAnimDeviation?.roll ?: 0.0)) * fireAnim * (1.0 - progress * 0.6) pose.mulPose(Vector3f.ZP.rotation(roll.toFloat())) pose.mulPose(Vector3f.YP.rotation(yaw.toFloat())) @@ -422,12 +440,51 @@ abstract class AbstractWeaponItem(val tables: KClass, ra event.packedLight ) + if (item is PlasmaWeaponItem<*>) { + // RenderSystem.setShader(GameRenderer::getPositionColorShader) + // RenderSystem.disableTexture() + // RenderSystem.enableBlend() + + RenderSystem.setShaderColor(1f, 1f, 1f, 1f) + + pose.translate(-0.85, 0.25, -0.25) + pose.mulPose(Vector3f.ZP.rotationDegrees(180f)) + pose.mulPose(Vector3f.YP.rotationDegrees(180f)) + pose.scale(0.01f, 0.01f, 0.01f) + + RenderHelper.setDrawColor(holoHudBackground) + RenderHelper.drawRect(pose, -2f, -2f, 72f, 34f) + + stack.matteryEnergy?.let { + pose.pushPose() + pose.translate(0.0, 0.0, -1.0) + pose.scale(0.7f, 0.7f, 0.7f) + val text = FormattingHelper.formatPower(it.batteryLevel) + font.draw(pose, text, 2f, 2f, RGBAColor.WHITE.toInt()) + pose.popPose() + } + + pose.translate(60.0, 0.0, 0.0) + + RenderHelper.setDrawColor(heatBackground) + RenderHelper.drawRect(pose, -1f, -1f, 9f, 32f) + + val heat = item.heatProgress(stack, event.partialTicks.toDouble()).toFloat() + RenderHelper.setDrawColor(linearInterpolation(heat, initialHeatColor, finalHeatColor)) + RenderHelper.drawRect(pose, 0f, 30f * (1f - heat), 7f, 30f * heat) + } + pose.popPose() item.dataTable = null inRender = false } + private val holoHudBackground get() = RGBAColor(75, 75, 75, 160) + private val heatBackground get() = RGBAColor(40, 144, 210, 160) + private val initialHeatColor get() = RGBAColor(85, 68, 7, 160) + private val finalHeatColor get() = RGBAColor(245, 118, 41, 160) + private val localPlayer: Player? get() { return Minecraft.getInstance().player } @@ -486,6 +543,9 @@ abstract class AbstractWeaponItem(val tables: KClass, ra } (stack.item as? AbstractWeaponItem<*>)?.let { + if (event.side == LogicalSide.CLIENT && stack.weaponDataTable?.uuid != predictedData?.uuid) + return@let + if (event.side == LogicalSide.CLIENT) { (it as AbstractWeaponItem).dataTable = predictedData } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt index b9ba3fcfe..f13e00e28 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaRifleItem.kt @@ -6,6 +6,7 @@ import net.minecraft.world.entity.Entity import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack import net.minecraft.world.phys.Vec3 +import ru.dbotthepony.mc.otm.capability.extractEnergyInnerExact import ru.dbotthepony.mc.otm.core.* import ru.dbotthepony.mc.otm.core.Vector import ru.dbotthepony.mc.otm.entity.PlasmaProjectile @@ -16,123 +17,20 @@ import kotlin.math.PI import kotlin.math.cos import kotlin.math.sin -private val random = Random() -private const val DEGS = PI / 180.0 - -class VelocityCalculation( - xRot: Double, - yRot: Double, - zRot: Double = 0.0, - force: Double, - deviation: Double = 0.0, - owner: Entity? = null, -) { - constructor( - xRot: Float, - yRot: Float, - zRot: Float = 0f, - force: Double, - deviation: Double = 0.0, - owner: Entity? = null, - ) : this(xRot.toDouble(), yRot.toDouble(), zRot.toDouble(), force, deviation, owner) - - constructor( - xRot: Float, - yRot: Float, - zRot: Float = 0f, - force: Float, - deviation: Double = 0.0, - owner: Entity? = null, - ) : this(xRot.toDouble(), yRot.toDouble(), zRot.toDouble(), force.toDouble(), deviation, owner) - - constructor( - xRot: Float, - yRot: Float, - zRot: Float = 0f, - force: Float, - deviation: Float, - owner: Entity? = null, - ) : this(xRot.toDouble(), yRot.toDouble(), zRot.toDouble(), force.toDouble(), deviation.toDouble(), owner) - - constructor( - owner: Entity, - force: Float, - deviation: Float, - ) : this(owner.xRot.toDouble() - 4.5 * (1 / force), owner.yRot.toDouble(), 0.0, force.toDouble(), deviation.toDouble(), owner) - - constructor( - owner: Entity, - force: Double, - deviation: Float, - ) : this(owner.xRot.toDouble() - 4.5 * (1 / force), owner.yRot.toDouble(), 0.0, force, deviation.toDouble(), owner) - - constructor( - owner: Entity, - force: Double, - deviation: Double, - ) : this(owner.xRot.toDouble() - 4.5 * (1 / force), owner.yRot.toDouble(), 0.0, force, deviation, owner) - - val xVelocity = -sin(yRot * DEGS) * cos(xRot * (PI / 180.0)) - val yVelocity = -sin((xRot + zRot) * DEGS) - val zVelocity = cos(yRot * DEGS) * cos(xRot * DEGS) - - val velocity: Vec3 - - init { - var velocity = Vec3( - xVelocity, - yVelocity, - zVelocity - ).normalize() - - velocity += Vec3( - random.nextGaussian() * 0.0075 * deviation, - random.nextGaussian() * 0.0075 * deviation, - random.nextGaussian() * 0.0075 * deviation, - ) - - velocity *= force - - if (owner != null) { - val ownerVel = owner.deltaMovement - - if (owner.isOnGround) { - velocity += ownerVel - } else { - velocity += Vec3(ownerVel.x, 0.0, ownerVel.z) - } - } - - this.velocity = velocity - } - - val yRotation = Mth.atan2(velocity.x, velocity.z).toFloat() * (180f / Math.PI.toFloat()) - val xRotation = Mth.atan2(velocity.y, velocity.horizontalDistance()).toFloat() * (180f / Math.PI.toFloat()) - - fun load(onto: Entity, withRotation: Boolean = true) { - if (withRotation) { - onto.xRot = xRotation - onto.yRot = yRotation - } - - onto.deltaMovement = velocity - } -} - -class PlasmaRifleItem : PlasmaWeaponItem(WeaponDataTable::class, ImpreciseFraction(200_000)) { +class PlasmaRifleItem : PlasmaWeaponItem(PlasmaWeaponDataTable::class, ImpreciseFraction(200_000)) { override val roundsPerMinute: Int = 200 override val scopingTime: Int = 7 override val positionIdle: Vector - get() = Vector(0.2,-0.4,-0.6) + get() = Vector(0.2, -0.4, -0.6) override val positionIronSights: Vector - get() = Vector(0.0,-0.24,-1.0) + get() = Vector(0.0, -0.24, -1.0) override val rotIdle: Angle get() = Angle(0.0, -0.02, 0.0) override val rotIronSights: Angle get() = Angle(-0.02, 0.0, 0.0) - override fun primaryFire(itemStack: ItemStack, player: Player, dt: WeaponDataTable): Boolean { + override fun primaryFire(itemStack: ItemStack, player: Player, dt: PlasmaWeaponDataTable): Boolean { if (!player.level.isClientSide) { val arrow = PlasmaProjectile(player.level) arrow.position = player.eyePosition @@ -147,18 +45,26 @@ class PlasmaRifleItem : PlasmaWeaponItem(WeaponDataTable::class dt.doFireAnim(deviation = rotFireAnimDeviation) } + receiveHeat(itemStack, player, 10.0, dt) + player.level.playSound( player, player, MSoundEvents.RIFLE_SHOT, - SoundSource.NEUTRAL, + SoundSource.PLAYERS, 1f, 1f ) + energyData(itemStack).extractEnergyInner(ENERGY_PER_SHOT, false) + return true } + override fun canPrimaryFire(itemStack: ItemStack, player: Player, dt: PlasmaWeaponDataTable): Boolean { + return super.canPrimaryFire(itemStack, player, dt) && energyData(itemStack).extractEnergyInnerExact(ENERGY_PER_SHOT, true).isPositive + } + companion object { private val ENERGY_PER_SHOT = ImpreciseFraction(3_000) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt index cacd57500..16c325346 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/PlasmaWeaponItem.kt @@ -5,6 +5,8 @@ import net.minecraft.core.Direction import net.minecraft.nbt.CompoundTag import net.minecraft.network.chat.Component import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerPlayer +import net.minecraft.sounds.SoundSource import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack import net.minecraft.world.item.TooltipFlag @@ -16,8 +18,12 @@ import net.minecraftforge.common.util.LazyOptional import net.minecraftforge.energy.CapabilityEnergy import ru.dbotthepony.mc.otm.capability.* import ru.dbotthepony.mc.otm.core.ImpreciseFraction +import ru.dbotthepony.mc.otm.core.bezierCurve +import ru.dbotthepony.mc.otm.doubles import ru.dbotthepony.mc.otm.ifPresentK +import ru.dbotthepony.mc.otm.ints import ru.dbotthepony.mc.otm.menu.FormattingHelper +import ru.dbotthepony.mc.otm.registry.MSoundEvents import ru.dbotthepony.mc.otm.set import kotlin.reflect.KClass @@ -112,7 +118,7 @@ class PlasmaWeaponEnergy(val itemStack: ItemStack, private val innerCapacity: Im return totalReceived } - val newEnergy = (innerBatteryLevel - howMuch).coerceAtMost(innerCapacity) + val newEnergy = (innerBatteryLevel + howMuch).coerceAtMost(innerCapacity) val diff = newEnergy - innerBatteryLevel if (!simulate) { @@ -145,7 +151,12 @@ class PlasmaWeaponEnergy(val itemStack: ItemStack, private val innerCapacity: Im get() = (battery.energy?.maxEnergyStoredMattery ?: ImpreciseFraction.ZERO) + innerCapacity } -abstract class PlasmaWeaponItem(tables: KClass, private val energyCapacity: ImpreciseFraction) : AbstractWeaponItem(tables) { +open class PlasmaWeaponDataTable(tag: CompoundTag) : WeaponDataTable(tag) { + var heatScore by tag.doubles + var heatCooldown by tag.ints +} + +abstract class PlasmaWeaponItem(tables: KClass, private val energyCapacity: ImpreciseFraction) : AbstractWeaponItem(tables) { override fun appendHoverText( itemStack: ItemStack, p_41422_: Level?, @@ -167,9 +178,97 @@ abstract class PlasmaWeaponItem(tables: KClass, private fun energyData(itemStack: ItemStack) = itemStack.matteryEnergy as PlasmaWeaponEnergy + open val cooldownSpeed get() = 1.0 + open val maxHeat = 40.0 + open val overheatCooldown = 30 + + open val cooldownSpline = doubleArrayOf( + 0.1, + 0.14, + 0.18, + 0.25, + 0.35, + 0.45, + 0.6, + 0.8, + 0.97, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.1, + 1.2, + 1.3, + 1.4, + ) + + override fun canPrimaryFire(itemStack: ItemStack, player: Player, dt: D): Boolean { + if (player is ServerPlayer) { + // allow little deviation because nothing is perfect + return super.canPrimaryFire(itemStack, player, dt) && dt.heatCooldown <= 2 + } + + return super.canPrimaryFire(itemStack, player, dt) && dt.heatCooldown <= 0 + } + + open fun canCooldown(itemStack: ItemStack, player: Player, dt: D = dataTable(itemStack)): Boolean { + return true + } + + protected open fun coolWeaponDown(itemStack: ItemStack, player: Player, dt: D) { + if (!canCooldown(itemStack, player, dt)) + return + + if (dt.heatScore > 0.0) + dt.heatScore = (dt.heatScore - cooldownSpeed * bezierCurve(heatProgress(itemStack, dt = dt), cooldownSpline)).coerceAtLeast(0.0) + + if (dt.heatCooldown > 0) + dt.heatCooldown-- + } + + open fun heatProgress(itemStack: ItemStack, partialTicks: Double = 0.0, dt: D = dataTable(itemStack)): Double { + if (dt.heatScore <= 0) + return 0.0 + + if (dt.heatScore - cooldownSpeed > maxHeat) + return 1.0 + + val result = dt.heatScore - cooldownSpeed * partialTicks + return result / maxHeat + } + + open fun overheatProgress(itemStack: ItemStack, partialTicks: Double = 0.0, dt: D = dataTable(itemStack)): Double { + if (dt.heatCooldown <= 0) + return 0.0 + + if (dt.heatCooldown - partialTicks > overheatCooldown) + return 1.0 + + val result = dt.heatCooldown - partialTicks + return result / overheatCooldown + } + + open fun receiveHeat(itemStack: ItemStack, player: Player, byTicks: Double, dt: D = dataTable(itemStack)) { + dt.heatScore = (dt.heatScore + byTicks).coerceAtMost(maxHeat * 2) + + if (dt.heatScore > maxHeat) { + val before = dt.heatCooldown > 0 + + dt.heatCooldown = overheatCooldown + + if (!before) { + player.level.playSound(player, player, MSoundEvents.PLASMA_WEAPON_OVERHEAT, SoundSource.PLAYERS, 1f, 1f) + } + } + } + override fun think2(itemStack: ItemStack, player: Player, dt: D) { super.think2(itemStack, player, dt) + coolWeaponDown(itemStack, player, dt) + itemStack.getCapability(MatteryCapability.ENERGY).ifPresentK { it as PlasmaWeaponEnergy it.think() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/VelocityCalculation.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/VelocityCalculation.kt new file mode 100644 index 000000000..c94c26837 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/weapon/VelocityCalculation.kt @@ -0,0 +1,114 @@ +package ru.dbotthepony.mc.otm.item.weapon + +import net.minecraft.util.Mth +import net.minecraft.world.entity.Entity +import net.minecraft.world.phys.Vec3 +import ru.dbotthepony.mc.otm.core.plus +import ru.dbotthepony.mc.otm.core.times +import java.util.* +import kotlin.math.PI +import kotlin.math.cos +import kotlin.math.sin + +private val random = Random() +private const val DEGS = PI / 180.0 + +class VelocityCalculation( + xRot: Double, + yRot: Double, + zRot: Double = 0.0, + force: Double, + deviation: Double = 0.0, + owner: Entity? = null, +) { + constructor( + xRot: Float, + yRot: Float, + zRot: Float = 0f, + force: Double, + deviation: Double = 0.0, + owner: Entity? = null, + ) : this(xRot.toDouble(), yRot.toDouble(), zRot.toDouble(), force, deviation, owner) + + constructor( + xRot: Float, + yRot: Float, + zRot: Float = 0f, + force: Float, + deviation: Double = 0.0, + owner: Entity? = null, + ) : this(xRot.toDouble(), yRot.toDouble(), zRot.toDouble(), force.toDouble(), deviation, owner) + + constructor( + xRot: Float, + yRot: Float, + zRot: Float = 0f, + force: Float, + deviation: Float, + owner: Entity? = null, + ) : this(xRot.toDouble(), yRot.toDouble(), zRot.toDouble(), force.toDouble(), deviation.toDouble(), owner) + + constructor( + owner: Entity, + force: Float, + deviation: Float, + ) : this(owner.xRot.toDouble() - 4.5 * (1 / force), owner.yRot.toDouble(), 0.0, force.toDouble(), deviation.toDouble(), owner) + + constructor( + owner: Entity, + force: Double, + deviation: Float, + ) : this(owner.xRot.toDouble() - 4.5 * (1 / force), owner.yRot.toDouble(), 0.0, force, deviation.toDouble(), owner) + + constructor( + owner: Entity, + force: Double, + deviation: Double, + ) : this(owner.xRot.toDouble() - 4.5 * (1 / force), owner.yRot.toDouble(), 0.0, force, deviation, owner) + + val xVelocity = -sin(yRot * DEGS) * cos(xRot * (PI / 180.0)) + val yVelocity = -sin((xRot + zRot) * DEGS) + val zVelocity = cos(yRot * DEGS) * cos(xRot * DEGS) + + val velocity: Vec3 + + init { + var velocity = Vec3( + xVelocity, + yVelocity, + zVelocity + ).normalize() + + velocity += Vec3( + random.nextGaussian() * 0.0075 * deviation, + random.nextGaussian() * 0.0075 * deviation, + random.nextGaussian() * 0.0075 * deviation, + ) + + velocity *= force + + if (owner != null) { + val ownerVel = owner.deltaMovement + + if (owner.isOnGround) { + velocity += ownerVel + } else { + velocity += Vec3(ownerVel.x, 0.0, ownerVel.z) + } + } + + this.velocity = velocity + } + + val yRotation = Mth.atan2(velocity.x, velocity.z).toFloat() * (180f / Math.PI.toFloat()) + val xRotation = Mth.atan2(velocity.y, velocity.horizontalDistance()).toFloat() * (180f / Math.PI.toFloat()) + + fun load(onto: Entity, withRotation: Boolean = true) { + if (withRotation) { + onto.xRot = xRotation + onto.yRot = yRotation + } + + onto.deltaMovement = velocity + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MSoundEvents.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MSoundEvents.kt index 58f759899..4fa442dfd 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MSoundEvents.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MSoundEvents.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.registry import net.minecraft.resources.ResourceLocation import net.minecraft.sounds.SoundEvent +import net.minecraft.sounds.SoundEvents import net.minecraft.world.entity.EntityType import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext import net.minecraftforge.registries.DeferredRegister @@ -11,7 +12,10 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters object MSoundEvents { private val registry: DeferredRegister = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, OverdriveThatMatters.MOD_ID) - val RIFLE_SHOT by registry.register("item.rifle_shot") { SoundEvent(ResourceLocation(OverdriveThatMatters.MOD_ID, "item.rifle_shot")) } + private fun make(name: String) = registry.register(name) { SoundEvent(ResourceLocation(OverdriveThatMatters.MOD_ID, name)) } + + val RIFLE_SHOT: SoundEvent by make("item.rifle_shot") + val PLASMA_WEAPON_OVERHEAT: SoundEvent by make("item.plasma_weapon_overheat") internal fun register() { registry.register(FMLJavaModLoadingContext.get().modEventBus) diff --git a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json index 8dbf13b49..9f11755e4 100644 --- a/src/main/resources/assets/overdrive_that_matters/lang/en_us.json +++ b/src/main/resources/assets/overdrive_that_matters/lang/en_us.json @@ -1,5 +1,7 @@ { - "otm.sound.rifle_shoot": "Plasma rifle fire", + "otm.sound.rifle_shoot": "Plasma rifle fires", + "otm.sound.plasma_weapon_overheat": "Plasma weapon overheats", + "itemGroup.otm": "Overdrive That Matters", "otm.pill.warning": "WARNING: This will INSTANTLY decommission you upon ingestion!", @@ -287,6 +289,8 @@ "item.overdrive_that_matters.tritanium_pants": "Tritanium Leggings", "item.overdrive_that_matters.tritanium_boots": "Tritanium Boots", + "item.overdrive_that_matters.plasma_rifle": "Plasma Rifle", + "item.overdrive_that_matters.matter_capacitor_parts": "Matter Capacitor Parts", "item.overdrive_that_matters.matter_capacitor_basic": "Basic Matter Capacitor", "item.overdrive_that_matters.matter_capacitor_normal": "Matter Capacitor", diff --git a/src/main/resources/assets/overdrive_that_matters/sounds.json b/src/main/resources/assets/overdrive_that_matters/sounds.json index 74cf34289..3db8da407 100644 --- a/src/main/resources/assets/overdrive_that_matters/sounds.json +++ b/src/main/resources/assets/overdrive_that_matters/sounds.json @@ -8,5 +8,11 @@ "weight": 1 } ] + }, + + "item.plasma_weapon_overheat": { + "subtitle": "otm.sound.plasma_weapon_overheat", + "sounds": [ + ] } } \ No newline at end of file