diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidActiveFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidActiveFeature.kt index 3ebcae47c..3c808dcee 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidActiveFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidActiveFeature.kt @@ -12,7 +12,6 @@ abstract class AndroidActiveFeature(type: AndroidFeatureType<*>, android: Matter abstract fun activate(isClient: Boolean): Boolean open val previewRenderStage: RenderLevelStageEvent.Stage get() = RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS - open val isOnCooldown: Boolean get() = false /** * Called on client inside world render context to render previews of ability activation diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt index ea8a5b3eb..06aaddd96 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/AndroidSwitchableFeature.kt @@ -23,6 +23,20 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma open val allowToSwitchByPlayer: Boolean get() = true open val allowToSwitchByPlayerWhileSpectator: Boolean get() = true + open val maxCooldown: Int get() = 0 + open var cooldown by synchronizer.int() + val isOnCooldown: Boolean + get() = maxCooldown > 0 && cooldown > 0 + + fun getCooldownPercent(): Float { + if (maxCooldown <= 0) return 0.0f + return (cooldown.toFloat() / maxCooldown.toFloat()).coerceIn(0.0f, 1.0f) + } + + fun putOnCooldown() { + cooldown = maxCooldown + } + // TODO: PoseStack is stripped from server dist // but it doesn't seem to cause issues? abstract fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) @@ -30,11 +44,20 @@ abstract class AndroidSwitchableFeature(type: AndroidFeatureType<*>, android: Ma override fun serializeNBT(): CompoundTag { return super.serializeNBT().also { it["isActive"] = isActive + it["cooldown"] = cooldown } } override fun deserializeNBT(nbt: CompoundTag) { super.deserializeNBT(nbt) isActive = nbt.getBoolean("isActive") + cooldown = nbt.getInt("cooldown") + } + + override fun tickServer() { + super.tickServer() + if (cooldown > 0) { + cooldown-- + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt index 041a4308c..0985f16ba 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/EnderTeleporterFeature.kt @@ -57,28 +57,16 @@ import kotlin.math.roundToInt import kotlin.math.sin class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiveFeature(AndroidFeatures.ENDER_TELEPORTER, capability) { - var cooldown by synchronizer.int() var lastTeleport = 0 private set - override val isOnCooldown: Boolean - get() = cooldown > 0 + override val maxCooldown: Int + get() = ServerConfig.EnderTeleporter.COOLDOWN private fun canUse(): Boolean { return !isOnCooldown && android.androidEnergy.extractEnergyInnerExact(ServerConfig.EnderTeleporter.ENERGY_COST, true).isPositive } - override fun serializeNBT(): CompoundTag { - return super.serializeNBT().also { - it["cooldown"] = cooldown - } - } - - override fun deserializeNBT(nbt: CompoundTag) { - super.deserializeNBT(nbt) - cooldown = nbt.getInt("cooldown") - } - private fun isValidGround(blockPos: BlockPos): Boolean { return canSupportPlayer(blockPos) && !isWall(blockPos) } @@ -301,7 +289,7 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv } if (!isClient) { - cooldown = ServerConfig.EnderTeleporter.COOLDOWN + putOnCooldown() if (!canUse) { android.androidEnergy.extractEnergyInnerExact(ServerConfig.EnderTeleporter.ENERGY_COST, false) @@ -328,12 +316,6 @@ class EnderTeleporterFeature(capability: MatteryPlayerCapability) : AndroidActiv return true } - override fun tickServer() { - if (cooldown > 0) { - cooldown-- - } - } - override val previewRenderStage: RenderLevelStageEvent.Stage get() = RenderLevelStageEvent.Stage.AFTER_PARTICLES diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt index 0ebb4df09..5f794ab65 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/JumpBoostFeature.kt @@ -56,7 +56,10 @@ object TriggerJumpBoostPacket : MatteryPacket { class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.JUMP_BOOST, capability) { private var tickCooldownClient = false - var cooldown by synchronizer.int(setter = setter@{ value, access, setByRemote -> + override val maxCooldown: Int + get() = (ServerConfig.AndroidJumpBoost.BASE_COOLDOWN - ServerConfig.AndroidJumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0) + + override var cooldown by synchronizer.int(setter = setter@{ value, access, setByRemote -> access.write(value) if (setByRemote) { @@ -64,21 +67,6 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF } }) - override fun serializeNBT(): CompoundTag { - return super.serializeNBT().also { - it["cooldown"] = cooldown - } - } - - override fun deserializeNBT(nbt: CompoundTag) { - super.deserializeNBT(nbt) - cooldown = nbt.getInt("cooldown") - } - - fun putOnCooldown() { - cooldown = (ServerConfig.AndroidJumpBoost.BASE_COOLDOWN - ServerConfig.AndroidJumpBoost.COOLDOWN_REDUCTION * level).coerceAtLeast(0) - } - private var lastGround = false fun movementTick(isJumping: Boolean, isShifting: Boolean) { @@ -104,12 +92,6 @@ class JumpBoostFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF } } - override fun tickServer() { - if (cooldown > 0) { - cooldown-- - } - } - override fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) { if (cooldown > 0) { RenderSystem.setShaderColor(1f, 0.4f, 0.4f, 1f) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt index bc46509ed..ac2cd0b1b 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/android/feature/ShockwaveFeature.kt @@ -53,7 +53,7 @@ object TriggerShockwavePacket : MatteryPacket { context.enqueueWork { val shockwave = context.sender?.matteryPlayer?.getFeature(AndroidFeatures.SHOCKWAVE) as ShockwaveFeature? ?: return@enqueueWork - if (shockwave.cooldown <= 0 && shockwave.isActive && shockwave.airTicks > 0) { + if (!shockwave.isOnCooldown && shockwave.isActive && shockwave.airTicks > 0) { shockwave.shockwave() } } @@ -61,7 +61,8 @@ object TriggerShockwavePacket : MatteryPacket { } class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableFeature(AndroidFeatures.SHOCKWAVE, capability) { - var cooldown by synchronizer.int() + override val maxCooldown: Int + get() = ServerConfig.Shockwave.COOLDOWN private var wasMidair = false private var highestSpeed = 0.0 @@ -73,7 +74,7 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF !ply.isSpectator && isActive && ply.isShiftKeyDown && - cooldown <= 0 && + !isOnCooldown && android.androidEnergy.extractEnergyInnerExact(ServerConfig.Shockwave.ENERGY_COST, true).isPositive && ply.deltaMovement.y < -0.01 ) { @@ -84,11 +85,11 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF } fun shockwave() { - if (ply.isSpectator || cooldown > 0 || !android.androidEnergy.extractEnergyInnerExact(ServerConfig.Shockwave.ENERGY_COST, false).isPositive) { + if (ply.isSpectator || isOnCooldown || !android.androidEnergy.extractEnergyInnerExact(ServerConfig.Shockwave.ENERGY_COST, false).isPositive) { return } - cooldown = ServerConfig.Shockwave.COOLDOWN + putOnCooldown() if (ply is ServerPlayer) { ShockwaveTrigger.trigger(ply as ServerPlayer) @@ -169,7 +170,7 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF airTicks = (airTicks - 1).coerceAtLeast(0) } - if (!ply.isSpectator && isActive && cooldown <= 0 && android.androidEnergy.extractEnergyInnerExact(ServerConfig.Shockwave.ENERGY_COST, true).isPositive) { + if (!ply.isSpectator && isActive && !isOnCooldown && android.androidEnergy.extractEnergyInnerExact(ServerConfig.Shockwave.ENERGY_COST, true).isPositive) { val old = wasMidair wasMidair = !ply.isOnGround @@ -182,7 +183,7 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF // I HATE SELF-UPDATING PLAYERS // I HATE SELF-UPDATING PLAYERS // fix "bug" where shockwave doesn't trigger even when player is falling faster than orbiting satellite - cooldown = ServerConfig.Shockwave.COOLDOWN + putOnCooldown() MatteryPlayerNetworkChannel.sendToServer(TriggerShockwavePacket) } else { shockwave() @@ -199,21 +200,19 @@ class ShockwaveFeature(capability: MatteryPlayerCapability) : AndroidSwitchableF } override fun tickServer() { - if (cooldown > 0) { - cooldown-- - } + super.tickServer() ticker(false) } override fun renderIcon(stack: PoseStack, x: Float, y: Float, width: Float, height: Float) { - if (cooldown > 0) { + if (isOnCooldown) { RenderSystem.setShaderColor(1f, 0.4f, 0.4f, 1f) } ResearchIcons.ICON_SHOCKWAVE.render(stack, x, y, width, height) - if (cooldown > 0) { + if (isOnCooldown) { RenderSystem.setShaderColor(1f, 1f, 1f, 1f) } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt index d846cbf3a..d83240522 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/AndroidAbilityKeyMapping.kt @@ -1,6 +1,7 @@ package ru.dbotthepony.mc.otm.client import com.mojang.blaze3d.platform.InputConstants +import com.mojang.blaze3d.systems.RenderSystem import net.minecraft.client.KeyMapping import net.minecraftforge.client.event.RegisterKeyMappingsEvent import net.minecraftforge.client.event.RenderGuiEvent @@ -10,10 +11,12 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.android.AndroidActiveFeature import ru.dbotthepony.mc.otm.capability.matteryPlayer import ru.dbotthepony.mc.otm.client.render.Widgets18 +import ru.dbotthepony.mc.otm.client.render.drawRect import ru.dbotthepony.mc.otm.client.render.is3DContext import ru.dbotthepony.mc.otm.core.RGBAColor import ru.dbotthepony.mc.otm.network.ActivateAndroidFeaturePacket import ru.dbotthepony.mc.otm.network.MatteryPlayerNetworkChannel +import kotlin.math.roundToInt object AndroidAbilityKeyMapping : KeyMapping("key.otm.android_ability", KeyConflictContext.IN_GAME, InputConstants.Type.KEYSYM.getOrCreate(InputConstants.KEY_V), OverdriveThatMatters.MOD_ID) { private var feature: AndroidActiveFeature? = null @@ -62,6 +65,18 @@ object AndroidAbilityKeyMapping : KeyMapping("key.otm.android_ability", KeyConfl if (feature.isOnCooldown) { RGBAColor.WHITE.setSystemColor() + val cooldownPct = feature.getCooldownPercent() + + if (cooldownPct > 0.0f) { + RenderSystem.setShaderColor(1f, 1f, 1f, 0.5f) + + val nodrawpixels = (iconSize * (1 - cooldownPct)).roundToInt().toFloat() + drawRect(event.poseStack, x, y + nodrawpixels, iconSize, iconSize - nodrawpixels) + + RenderSystem.setShaderColor(1f, 1f, 1f, 1f) + } + + Widgets18.COOLDOWN.render(event.poseStack, x, y + iconSize, iconSize, iconSize) } }