diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt
index 23059d825..ac35140e7 100644
--- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt
+++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/English.kt
@@ -453,6 +453,9 @@ private fun blocks(provider: MatteryLanguageProvider) {
 
 private fun items(provider: MatteryLanguageProvider) {
 	with(provider.english) {
+		add(MItems.PROCEDURAL_BATTERY, "Mythical Battery")
+		add(MItems.PROCEDURAL_BATTERY, "desc", "These batteries are found in dungeons with randomized stats")
+
 		add(MItems.EXPLOSIVE_HAMMER, "Explosive Hammer")
 		add(MItems.EXPLOSIVE_HAMMER, "desc", "For those who feel bored")
 		add(MItems.EXPLOSIVE_HAMMER, "primed", "Primed!")
diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt
index 4e5260406..dd46dbd90 100644
--- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt
+++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/lang/Russian.kt
@@ -458,6 +458,9 @@ private fun blocks(provider: MatteryLanguageProvider) {
 
 private fun items(provider: MatteryLanguageProvider) {
 	with(provider.russian) {
+		add(MItems.PROCEDURAL_BATTERY, "Загадочный аккумулятор")
+		add(MItems.PROCEDURAL_BATTERY, "desc", "Данные аккумуляторы можно найти в подземельях, со случайными характеристиками")
+
 		add(MItems.EXPLOSIVE_HAMMER, "Молоток-убийца")
 		add(MItems.EXPLOSIVE_HAMMER, "desc", "Для тех, кому стало скучно")
 		add(MItems.EXPLOSIVE_HAMMER, "primed", "Заряжен!")
diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt
index 4ca29433b..b62d7f57e 100644
--- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt
+++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/DSL.kt
@@ -28,6 +28,7 @@ inline fun LootTable.Builder.singleItem(item: ItemLike, configurator: LootPoolSi
 
 inline fun lootPool(configurator: LootPool.Builder.() -> Unit): LootPool = LootPool.lootPool().also(configurator).build()
 inline fun singleItem(item: ItemLike, configurator: LootPoolSingletonContainer.Builder<*>.() -> Unit): LootPool = lootPool { item(item, configurator) }
+
 fun singleRandomizedItem(item: ItemLike, rarity: Rarity = Rarity.COMMON, chance: Double? = null): LootPool {
 	return lootPool {
 		item(item) {
diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt
index 61e301237..6b3002281 100644
--- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt
+++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/loot/LootModifiersData.kt
@@ -7,12 +7,15 @@ import net.minecraft.world.item.Rarity
 import net.minecraft.world.level.storage.loot.BuiltInLootTables
 import net.minecraft.world.level.storage.loot.predicates.LootItemCondition
 import net.minecraftforge.common.loot.LootTableIdCondition
+import ru.dbotthepony.mc.otm.core.math.Decimal
+import ru.dbotthepony.mc.otm.data.UniformDecimal
 import ru.dbotthepony.mc.otm.data.condition.ChanceWithPlaytimeCondition
 import ru.dbotthepony.mc.otm.data.condition.HasExoPackCondition
 import ru.dbotthepony.mc.otm.data.condition.ItemInInventoryCondition
 import ru.dbotthepony.mc.otm.data.condition.KilledByRealPlayerOrIndirectly
 import ru.dbotthepony.mc.otm.data.loot.LootPoolAppender
 import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction
+import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem
 import ru.dbotthepony.mc.otm.registry.MItems
 
 @Suppress("FunctionName")
@@ -25,7 +28,7 @@ fun LootTableIdCondition(location: ResourceLocation): LootItemCondition {
 	return LootTableIdCondition.Builder(location).build()
 }
 
-private fun exosuitModifiers(it: LootModifiers) {
+fun addLootModifiers(it: LootModifiers) {
 	it.add("dungeon_exosuit", LootPoolAppender(
 		arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
 
@@ -40,10 +43,20 @@ private fun exosuitModifiers(it: LootModifiers) {
 		},
 	))
 
-	it.add("mineshaft_exosuit", LootPoolAppender(
+	it.add("mineshaft_additions", LootPoolAppender(
 		arrayOf(LootTableIdCondition(BuiltInLootTables.ABANDONED_MINESHAFT)),
 		singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1),
-		singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1, rarity = Rarity.UNCOMMON)
+		singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.1, rarity = Rarity.UNCOMMON),
+
+		singleItem(MItems.PROCEDURAL_BATTERY) {
+			chanceCondition(0.15)
+
+			apply(ProceduralBatteryItem.Randomizer(
+				maxBatteryLevel = UniformDecimal(Decimal(8_000_000), Decimal(40_000_000)),
+				batteryLevel = UniformDecimal(Decimal(0), Decimal(20_000_000)),
+				maxInput = UniformDecimal(Decimal(700), Decimal(4_000)),
+			))
+		}
 	))
 
 	it.add("desert_pyramid_exosuit", LootPoolAppender(
@@ -64,10 +77,6 @@ private fun exosuitModifiers(it: LootModifiers) {
 		singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.2, rarity = Rarity.RARE),
 		singleRandomizedItem(MItems.ExopackUpgrades.INVENTORY_UPGRADE_PROCEDURAL, chance = 0.15, rarity = Rarity.EPIC),
 	))
-}
-
-fun addLootModifiers(it: LootModifiers) {
-	exosuitModifiers(it)
 
 	it.add("dungeon_pill", PlainLootAppender(
 		arrayOf(LootTableIdCondition(BuiltInLootTables.SIMPLE_DUNGEON)),
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/Codec2Serializer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/Codec2Serializer.kt
new file mode 100644
index 000000000..d6bc931c5
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/Codec2Serializer.kt
@@ -0,0 +1,21 @@
+package ru.dbotthepony.mc.otm.data
+
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonObject
+import com.google.gson.JsonSerializationContext
+import com.google.gson.JsonSyntaxException
+import com.mojang.serialization.Codec
+import net.minecraft.world.level.storage.loot.Serializer
+import ru.dbotthepony.mc.otm.core.fromJsonStrict
+import ru.dbotthepony.mc.otm.core.set
+import ru.dbotthepony.mc.otm.core.toJsonStrict
+
+class Codec2Serializer<T : Any>(val codec: Codec<T>) : Serializer<T> {
+	override fun serialize(p_79325_: JsonObject, p_79326_: T, p_79327_: JsonSerializationContext) {
+		p_79325_["value"] = codec.toJsonStrict(p_79326_)
+	}
+
+	override fun deserialize(p_79323_: JsonObject, p_79324_: JsonDeserializationContext): T {
+		return codec.fromJsonStrict(p_79323_["value"] ?: throw JsonSyntaxException("Missing 'value' element"))
+	}
+}
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/DecimalCodec.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/DecimalCodec.kt
new file mode 100644
index 000000000..4b600cb78
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/DecimalCodec.kt
@@ -0,0 +1,23 @@
+package ru.dbotthepony.mc.otm.data
+
+import com.mojang.datafixers.util.Pair
+import com.mojang.serialization.Codec
+import com.mojang.serialization.DataResult
+import com.mojang.serialization.DynamicOps
+import ru.dbotthepony.mc.otm.core.math.Decimal
+
+object DecimalCodec : Codec<Decimal> {
+	override fun <T : Any> encode(input: Decimal, ops: DynamicOps<T>, prefix: T): DataResult<T> {
+		return DataResult.success(ops.createString(input.toString()))
+	}
+
+	override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<Decimal, T>> {
+		return ops.getStringValue(input).flatMap {
+			try {
+				DataResult.success(Pair(Decimal(it), ops.empty()))
+			} catch (err: NumberFormatException) {
+				DataResult.error { "Not a number: $it" }
+			}
+		}
+	}
+}
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/data/DecimalProvider.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/data/DecimalProvider.kt
new file mode 100644
index 000000000..172e6b07e
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/data/DecimalProvider.kt
@@ -0,0 +1,117 @@
+package ru.dbotthepony.mc.otm.data
+
+import com.mojang.datafixers.util.Either
+import com.mojang.serialization.Codec
+import com.mojang.serialization.codecs.RecordCodecBuilder
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.util.RandomSource
+import net.minecraftforge.eventbus.api.IEventBus
+import net.minecraftforge.registries.DeferredRegister
+import ru.dbotthepony.mc.otm.OverdriveThatMatters
+import ru.dbotthepony.mc.otm.core.math.Decimal
+import ru.dbotthepony.mc.otm.core.math.nextDecimal
+import ru.dbotthepony.mc.otm.registry.RegistryDelegate
+
+fun interface SampledDecimal {
+	fun sample(source: RandomSource): Decimal
+}
+
+abstract class DecimalProvider : SampledDecimal {
+	interface Type<T : DecimalProvider> {
+		val codec: Codec<T>
+	}
+
+	abstract val minValue: Decimal
+	abstract val maxValue: Decimal
+	abstract val type: Type<*>
+
+	companion object {
+		private val registryHolder = RegistryDelegate<Type<*>>("decimal_provider_type") {
+			setDefaultKey(ResourceLocation(OverdriveThatMatters.MOD_ID, "zero"))
+		}
+
+		val CODEC: Codec<DecimalProvider> by lazy {
+			Codec
+				.either(DecimalCodec, registry.codec.dispatch({ it.type }, { it.codec }))
+				.xmap(
+					{ c -> c.map(::ConstantDecimal, { it }) },
+					{ if (it.type === ConstantDecimal.Companion) Either.left(it.minValue) else Either.right(it) }
+				)
+		}
+
+		val registry by registryHolder
+		val registryKey get() = registryHolder.key
+
+		private val registror = DeferredRegister.create(registryKey, OverdriveThatMatters.MOD_ID)
+
+		init {
+			registror.register("zero") { ConstantDecimal.Zero }
+			registror.register("constant") { ConstantDecimal.Companion }
+			registror.register("uniform") { UniformDecimal.Companion }
+		}
+
+		internal fun register(bus: IEventBus) {
+			bus.addListener(registryHolder::build)
+			registror.register(bus)
+		}
+	}
+}
+
+class ConstantDecimal(val value: Decimal) : DecimalProvider() {
+	object Zero : DecimalProvider(), Type<Zero> {
+		override fun sample(source: RandomSource): Decimal {
+			return Decimal.ZERO
+		}
+
+		override val codec: Codec<Zero> = Codec.unit(this)
+
+		override val minValue: Decimal
+			get() = Decimal.ZERO
+		override val maxValue: Decimal
+			get() = Decimal.ZERO
+		override val type: Type<*>
+			get() = this
+	}
+
+	override fun sample(source: RandomSource): Decimal {
+		return value
+	}
+
+	override val minValue: Decimal
+		get() = value
+	override val maxValue: Decimal
+		get() = value
+	override val type: Type<*>
+		get() = Companion
+
+	companion object : Type<ConstantDecimal> {
+		override val codec: Codec<ConstantDecimal> = RecordCodecBuilder.create {
+			it.group(DecimalCodec.fieldOf("value").forGetter(ConstantDecimal::value)).apply(it, ::ConstantDecimal)
+		}
+	}
+}
+
+class UniformDecimal(override val minValue: Decimal, override val maxValue: Decimal, val round: Boolean = true) : DecimalProvider() {
+	constructor(range: ClosedRange<Decimal>, round: Boolean = true) : this(range.start, range.endInclusive, round)
+
+	init {
+		require(minValue <= maxValue) { "Invalid range provided: $minValue .. $maxValue" }
+	}
+
+	override fun sample(source: RandomSource): Decimal {
+		return source.nextDecimal(minValue, maxValue, round = round)
+	}
+
+	override val type: Type<*>
+		get() = Companion
+
+	companion object : Type<UniformDecimal> {
+		override val codec: Codec<UniformDecimal> = RecordCodecBuilder.create {
+			it.group(
+				DecimalCodec.fieldOf("minValue").forGetter(UniformDecimal::minValue),
+				DecimalCodec.fieldOf("maxValue").forGetter(UniformDecimal::maxValue),
+				Codec.BOOL.optionalFieldOf("round", true).forGetter(UniformDecimal::round)
+			).apply(it, ::UniformDecimal)
+		}
+	}
+}
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/item/ProceduralBatteryItem.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ProceduralBatteryItem.kt
new file mode 100644
index 000000000..42c68d400
--- /dev/null
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/item/ProceduralBatteryItem.kt
@@ -0,0 +1,126 @@
+package ru.dbotthepony.mc.otm.item
+
+import com.mojang.serialization.codecs.RecordCodecBuilder
+import net.minecraft.ChatFormatting
+import net.minecraft.nbt.CompoundTag
+import net.minecraft.network.chat.Component
+import net.minecraft.world.item.Item
+import net.minecraft.world.item.ItemStack
+import net.minecraft.world.item.TooltipFlag
+import net.minecraft.world.level.Level
+import net.minecraft.world.level.storage.loot.LootContext
+import net.minecraft.world.level.storage.loot.functions.LootItemFunction
+import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType
+import net.minecraftforge.common.capabilities.ICapabilityProvider
+import ru.dbotthepony.mc.otm.capability.FlowDirection
+import ru.dbotthepony.mc.otm.capability.energy.ItemEnergyStorageImpl
+import ru.dbotthepony.mc.otm.capability.energy.batteryLevel
+import ru.dbotthepony.mc.otm.capability.matteryEnergy
+import ru.dbotthepony.mc.otm.core.TranslatableComponent
+import ru.dbotthepony.mc.otm.core.math.Decimal
+import ru.dbotthepony.mc.otm.core.math.set
+import ru.dbotthepony.mc.otm.core.nbt.mapPresent
+import ru.dbotthepony.mc.otm.core.tagNotNull
+import ru.dbotthepony.mc.otm.data.Codec2Serializer
+import ru.dbotthepony.mc.otm.data.DecimalProvider
+import ru.dbotthepony.mc.otm.registry.MItemFunctionTypes
+import java.util.Optional
+
+class ProceduralBatteryItem : Item(Properties().stacksTo(1)) {
+	class Cap(stack: ItemStack) : ItemEnergyStorageImpl(stack) {
+		override var maxInput: Decimal
+			get() = itemStack.tag?.mapPresent("maxInput", Decimal.Companion::deserializeNBT) ?: Decimal.ZERO
+			set(value) { itemStack.tagNotNull["maxInput"] = value }
+
+		override var maxOutput: Decimal
+			get() = itemStack.tag?.mapPresent("maxOutput", Decimal.Companion::deserializeNBT) ?: Decimal.ZERO
+			set(value) { itemStack.tagNotNull["maxOutput"] = value }
+
+		override var maxBatteryLevel: Decimal
+			get() = itemStack.tag?.mapPresent("maxBatteryLevel", Decimal.Companion::deserializeNBT) ?: Decimal.ZERO
+			set(value) { itemStack.tagNotNull["maxBatteryLevel"] = value }
+
+		override val energyFlow: FlowDirection
+			get() = FlowDirection.BI_DIRECTIONAL
+
+		override val initialBatteryLevel: Decimal
+			get() = maxBatteryLevel
+	}
+
+	override fun appendHoverText(p_41421_: ItemStack, p_41422_: Level?, p_41423_: MutableList<Component>, p_41424_: TooltipFlag) {
+		super.appendHoverText(p_41421_, p_41422_, p_41423_, p_41424_)
+
+		val energy = p_41421_.matteryEnergy
+
+		if (energy is Cap) {
+			if (energy.maxInput.isZero && energy.maxOutput.isZero && energy.maxBatteryLevel.isZero) {
+				p_41423_.add(TranslatableComponent("$descriptionId.desc").withStyle(ChatFormatting.GRAY))
+			} else {
+				batteryLevel(energy, p_41423_)
+			}
+		}
+	}
+
+	data class Randomizer(
+		val maxBatteryLevel: DecimalProvider,
+		val batteryLevel: Optional<DecimalProvider>,
+		val maxInput: DecimalProvider,
+		val maxOutput: Optional<DecimalProvider>
+	) : LootItemFunction, LootItemFunction.Builder {
+		constructor(
+			maxBatteryLevel: DecimalProvider,
+			batteryLevel: DecimalProvider? = null,
+			maxInput: DecimalProvider,
+			maxOutput: DecimalProvider? = null
+		) : this(maxBatteryLevel, Optional.ofNullable(batteryLevel), maxInput, Optional.ofNullable(maxOutput))
+
+		override fun apply(t: ItemStack, u: LootContext): ItemStack {
+			val data = Cap(t)
+
+			if (maxOutput.isPresent) {
+				data.maxInput = maxInput.sample(u.random)
+				data.maxOutput = maxOutput.get().sample(u.random)
+			} else {
+				data.maxInput = maxInput.sample(u.random)
+				data.maxOutput = data.maxInput
+			}
+
+			data.maxBatteryLevel = maxBatteryLevel.sample(u.random)
+
+			if (batteryLevel.isPresent) {
+				data.batteryLevel = batteryLevel.get().sample(u.random).coerceAtMost(data.maxBatteryLevel)
+			} else {
+				data.batteryLevel = data.maxBatteryLevel
+			}
+
+			return t
+		}
+
+		override fun getType(): LootItemFunctionType {
+			return MItemFunctionTypes.PROCEDURAL_BATTERY
+		}
+
+		override fun build(): LootItemFunction {
+			return this
+		}
+
+		companion object {
+			val SERIALIZER by lazy {
+				Codec2Serializer<Randomizer>(
+					RecordCodecBuilder.create {
+						it.group(
+							DecimalProvider.CODEC.fieldOf("maxBatteryLevel").forGetter(Randomizer::maxBatteryLevel),
+							DecimalProvider.CODEC.optionalFieldOf("batteryLevel").forGetter(Randomizer::batteryLevel),
+							DecimalProvider.CODEC.fieldOf("maxInput").forGetter(Randomizer::maxInput),
+							DecimalProvider.CODEC.optionalFieldOf("maxOutput").forGetter(Randomizer::maxOutput),
+						).apply(it, ::Randomizer)
+					}
+				)
+			}
+		}
+	}
+
+	override fun initCapabilities(stack: ItemStack, nbt: CompoundTag?): ICapabilityProvider {
+		return Cap(stack)
+	}
+}
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt
index 2e5645ad5..d30b97e29 100644
--- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItemFunctionTypes.kt
@@ -1,6 +1,5 @@
 package ru.dbotthepony.mc.otm.registry
 
-import net.minecraft.core.Registry
 import net.minecraft.core.registries.Registries
 import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType
 import net.minecraftforge.eventbus.api.IEventBus
@@ -8,12 +7,14 @@ import net.minecraftforge.registries.DeferredRegister
 import ru.dbotthepony.mc.otm.OverdriveThatMatters
 import ru.dbotthepony.mc.otm.data.loot.CopyTileNbtFunction
 import ru.dbotthepony.mc.otm.data.loot.RandomizerFunction
+import ru.dbotthepony.mc.otm.item.ProceduralBatteryItem
 
 object MItemFunctionTypes {
 	private val registry = DeferredRegister.create(Registries.LOOT_FUNCTION_TYPE, OverdriveThatMatters.MOD_ID)
 
 	val RANDOMIZER: LootItemFunctionType by registry.register("randomizer") { LootItemFunctionType(RandomizerFunction.Companion) }
 	val COPY_TILE_NBT: LootItemFunctionType by registry.register("copy_tile_nbt") { LootItemFunctionType(CopyTileNbtFunction.Companion) }
+	val PROCEDURAL_BATTERY: LootItemFunctionType by registry.register(MNames.PROCEDURAL_BATTERY) { LootItemFunctionType(ProceduralBatteryItem.Randomizer.SERIALIZER) }
 
 	internal fun register(bus: IEventBus) {
 		registry.register(bus)
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt
index e9a81c914..f24e37f4d 100644
--- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MItems.kt
@@ -289,10 +289,11 @@ object MItems {
 	val BATTERY_CAPACITOR: Item by registry.register(MNames.BATTERY_CAPACITOR) { BatteryItem(ItemsConfig.Batteries.CAPACITOR) }
 	val BATTERY_CREATIVE: Item by registry.register(MNames.BATTERY_CREATIVE) { BatteryItem() }
 
-	val QUANTUM_BATTERY: Item by registry.register(MNames.QUANTUM_BATTERY) { QuantumBatteryItem(MNames.QUANTUM_BATTERY, ItemsConfig.Batteries.QUANTUM_BATTERY) }
-	val QUANTUM_CAPACITOR: Item by registry.register(MNames.QUANTUM_CAPACITOR) { QuantumBatteryItem(MNames.QUANTUM_CAPACITOR, ItemsConfig.Batteries.QUANTUM_CAPACITOR) }
-	val QUANTUM_BATTERY_CREATIVE: Item by registry.register(MNames.QUANTUM_BATTERY_CREATIVE) { QuantumBatteryItem(MNames.QUANTUM_BATTERY_CREATIVE) }
-	val ZPM_BATTERY: Item by registry.register(MNames.ZPM_BATTERY) { ZPMItem() }
+	val QUANTUM_BATTERY: QuantumBatteryItem by registry.register(MNames.QUANTUM_BATTERY) { QuantumBatteryItem(MNames.QUANTUM_BATTERY, ItemsConfig.Batteries.QUANTUM_BATTERY) }
+	val QUANTUM_CAPACITOR: QuantumBatteryItem by registry.register(MNames.QUANTUM_CAPACITOR) { QuantumBatteryItem(MNames.QUANTUM_CAPACITOR, ItemsConfig.Batteries.QUANTUM_CAPACITOR) }
+	val QUANTUM_BATTERY_CREATIVE: QuantumBatteryItem by registry.register(MNames.QUANTUM_BATTERY_CREATIVE) { QuantumBatteryItem(MNames.QUANTUM_BATTERY_CREATIVE) }
+	val ZPM_BATTERY: ZPMItem by registry.register(MNames.ZPM_BATTERY) { ZPMItem() }
+	val PROCEDURAL_BATTERY: ProceduralBatteryItem by registry.register(MNames.PROCEDURAL_BATTERY) { ProceduralBatteryItem() }
 
 	val BATTERIES = SupplierList(
 		::BATTERY_CRUDE,
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt
index 2f36a7932..1f8e0b1ac 100644
--- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MNames.kt
@@ -111,6 +111,7 @@ object MNames {
 	const val PATTERN_DRIVE_CREATIVE2 = "pattern_drive_creative2"
 
 	const val ZPM_BATTERY = "zpm_battery"
+	const val PROCEDURAL_BATTERY = "procedural_battery"
 
 	const val NUTRIENT_PASTE = "nutrient_paste"
 
diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt
index 906d056d7..6444c44eb 100644
--- a/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt
+++ b/src/main/kotlin/ru/dbotthepony/mc/otm/registry/MRegistry.kt
@@ -27,6 +27,7 @@ import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
 import ru.dbotthepony.mc.otm.block.decorative.TritaniumPressurePlate
 import ru.dbotthepony.mc.otm.capability.matteryEnergy
 import ru.dbotthepony.mc.otm.core.math.Decimal
+import ru.dbotthepony.mc.otm.data.DecimalProvider
 import ru.dbotthepony.mc.otm.item.weapon.EnergySwordItem
 import ru.dbotthepony.mc.otm.registry.objects.ColoredDecorativeBlock
 import ru.dbotthepony.mc.otm.registry.objects.DecorativeBlock
@@ -193,6 +194,8 @@ object MRegistry {
 		bus.addListener(this::initializeCommon)
 		bus.addListener(MStats::registerVanilla)
 
+		DecimalProvider.register(bus)
+
 		MBlocks.register(bus)
 		MBlockEntities.register(bus)
 		MEntityTypes.register(bus)