Files
fantasysmp_fabric/src/main/kotlin/dev/zxq5/items/sets/Dragonite.kt
T

140 lines
5.4 KiB
Kotlin

package dev.zxq5.items.sets
import dev.zxq5.items.template.ArmorSet
import dev.zxq5.items.template.GenericGearSet
import dev.zxq5.items.ModItems.register
import dev.zxq5.items.template.registerItem
import dev.zxq5.items.template.provideDelegate
import net.minecraft.core.component.DataComponents
import net.minecraft.core.particles.ParticleTypes
import net.minecraft.core.particles.PowerParticleOption
import net.minecraft.server.level.ServerLevel
import net.minecraft.sounds.SoundEvents
import net.minecraft.sounds.SoundSource
import net.minecraft.util.Unit
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.Item
import net.minecraft.world.item.Items
import net.minecraft.world.item.ToolMaterial
import net.minecraft.world.item.component.UseCooldown
import net.minecraft.world.item.equipment.*
import net.minecraft.world.level.Level
import kotlin.getValue
object Dragonite: GenericGearSet() {
override val materialName = "dragonite"
override val materialDefinition
get() = super.materialDefinition.copy(assetId = materialKey)
val SCALE by registerItem("dragon_scale", ::Item)
val INGOT by registerItem("dragonite_ingot", ::Item) {
shapedRecipe("SBS", "CXC", "SBS", key=mapOf<Char, Item>(
'S' to Items.SHULKER_SHELL,
'X' to SCALE,
'B' to Items.DRAGON_BREATH,
'C' to Items.CHORUS_FRUIT
))
}
val SWORD by registerItem("dragonite_sword", ::DragoniteSword) {
properties {
enchantable(armorMaterial.enchantmentValue)
.component(DataComponents.USE_COOLDOWN, UseCooldown(2f))
.sword(ToolMaterial.NETHERITE, 3F, -2.4F)
}
smithingUpgrade(Items.END_CRYSTAL, Items.NETHERITE_SWORD, INGOT)
}
val HELMET by registerItem("dragonite_helmet", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.HELMET)
}
smithingUpgrade(Items.DRAGON_HEAD, Items.NETHERITE_HELMET, INGOT)
}
val CHESTPLATE by registerItem("dragonite_chestplate", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.CHESTPLATE)
.component(DataComponents.GLIDER, Unit.INSTANCE)
.component(DataComponents.UNBREAKABLE, Unit.INSTANCE)
}
smithingUpgrade(Items.ELYTRA, Items.NETHERITE_CHESTPLATE, INGOT)
}
val LEGGINGS by registerItem("dragonite_leggings", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.LEGGINGS)
}
smithingUpgrade(Items.CRYING_OBSIDIAN, Items.NETHERITE_LEGGINGS, INGOT)
}
val BOOTS by registerItem("dragonite_boots", ::Item) {
properties {
humanoidArmor(armorMaterial, ArmorType.BOOTS)
}
smithingUpgrade(Items.CRYING_OBSIDIAN, Items.NETHERITE_BOOTS, INGOT)
}
override val armorSet: ArmorSet = ArmorSet(HELMET, CHESTPLATE, LEGGINGS, BOOTS)
override val items = listOf(SWORD, HELMET, CHESTPLATE, LEGGINGS, BOOTS, SCALE, INGOT)
override fun onLoad() {}
}
class DragoniteSword(properties: Properties) : Item(properties) {
override fun use(level: Level, user: Player, hand: InteractionHand): InteractionResult {
if (level.isClientSide || !Dragonite.fullSetEquippedBy(user)) return InteractionResult.PASS
val direction = user.lookAngle
val scale = if (user.isFallFlying) { 4.0 } else { 1.5 }
user.deltaMovement = direction.scale(scale)
user.hurtMarked = true
level.playSound(null, user.x, user.y, user.z,
SoundEvents.ENDER_DRAGON_FLAP, SoundSource.PLAYERS, 1.0f, 1.0f)
(level as? ServerLevel)?.sendParticles(
PowerParticleOption.create(ParticleTypes.DRAGON_BREATH, 1.0f),
user.x, user.y, user.z,
100, 0.5, 0.5, 0.5, 0.5
)
return InteractionResult.SUCCESS
}
override fun getAttackDamageBonus(victim: Entity, damage: Float, damageSource: DamageSource): Float {
val superBonus = super.getAttackDamageBonus(victim, damage, damageSource) // 0f from vanilla, but respect it anyway
val attacker = damageSource.entity as? Player ?: return superBonus
if (Dragonite.fullSetEquippedBy(attacker)) return superBonus
if (attacker.level().isClientSide) return superBonus
if (!attacker.isFallFlying) return superBonus
val speed = attacker.deltaMovement.length()
if (speed < MIN_DIVE_SPEED) return superBonus
val clampedSpeed = speed.coerceAtMost(MAX_DIVE_SPEED)
val t = (clampedSpeed - MIN_DIVE_SPEED) / (MAX_DIVE_SPEED - MIN_DIVE_SPEED)
val multiplier = 1.0f + (t * MAX_BONUS_MULTIPLIER).toFloat()
// damage is the current total (base + crit + whatever ran before this hook).
// We want final = damage * multiplier, and this method adds its return value on top of damage,
// so the bonus we need to return is exactly (damage * multiplier) - damage.
val extraBonus = damage * (multiplier - 1f)
println("base: $damage bonus: ${superBonus + extraBonus}")
return superBonus + extraBonus
}
companion object {
const val MIN_DIVE_SPEED = 0.3
const val MAX_DIVE_SPEED = 1.1
const val MAX_BONUS_MULTIPLIER = 2.0f
}
}