111 lines
4 KiB
Kotlin
111 lines
4 KiB
Kotlin
package at.petrak.hexcasting.common.casting.operators.spells.great
|
|
|
|
import at.petrak.hexcasting.api.casting.ParticleSpray
|
|
import at.petrak.hexcasting.api.casting.RenderedSpell
|
|
import at.petrak.hexcasting.api.casting.castables.SpellAction
|
|
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
|
|
import at.petrak.hexcasting.api.casting.getPlayer
|
|
import at.petrak.hexcasting.api.casting.getPositiveDouble
|
|
import at.petrak.hexcasting.api.casting.iota.Iota
|
|
import at.petrak.hexcasting.api.misc.MediaConstants
|
|
import at.petrak.hexcasting.api.player.FlightAbility
|
|
import at.petrak.hexcasting.xplat.IXplatAbstractions
|
|
import net.minecraft.server.level.ServerLevel
|
|
import net.minecraft.server.level.ServerPlayer
|
|
import net.minecraft.world.entity.LivingEntity
|
|
import net.minecraft.world.phys.Vec3
|
|
import kotlin.math.roundToInt
|
|
|
|
object OpFlight : SpellAction {
|
|
override val argc = 3
|
|
override fun execute(
|
|
args: List<Iota>,
|
|
ctx: CastingEnvironment
|
|
): Triple<RenderedSpell, Int, List<ParticleSpray>> {
|
|
val target = args.getPlayer(0, argc)
|
|
val timeRaw = args.getPositiveDouble(1, argc)
|
|
val radiusRaw = args.getPositiveDouble(2, argc)
|
|
ctx.assertEntityInRange(target)
|
|
|
|
// Convert to ticks
|
|
val time = (timeRaw * 20.0).roundToInt()
|
|
return Triple(
|
|
Spell(target, time, radiusRaw, ctx.position),
|
|
(MediaConstants.DUST_UNIT * 0.25 * (timeRaw * radiusRaw + 1.0)).roundToInt(),
|
|
listOf(ParticleSpray(target.position(), Vec3(0.0, 2.0, 0.0), 0.0, 0.1))
|
|
)
|
|
}
|
|
|
|
data class Spell(val target: ServerPlayer, val time: Int, val radius: Double, val origin: Vec3) : RenderedSpell {
|
|
override fun cast(ctx: CastingEnvironment) {
|
|
if (target.abilities.mayfly) {
|
|
// Don't accidentally clobber someone else's flight
|
|
return
|
|
}
|
|
|
|
IXplatAbstractions.INSTANCE.setFlight(
|
|
target,
|
|
FlightAbility(
|
|
true,
|
|
time,
|
|
target.level.dimension(),
|
|
origin,
|
|
radius
|
|
)
|
|
)
|
|
|
|
target.abilities.mayfly = true
|
|
target.abilities.flying = true
|
|
target.onUpdateAbilities()
|
|
// Launch the player into the air to really emphasize the flight
|
|
target.push(0.0, 1.0, 0.0)
|
|
target.hurtMarked = true // Whyyyyy
|
|
}
|
|
}
|
|
|
|
fun tickDownFlight(entity: LivingEntity) {
|
|
if (entity !is ServerPlayer) return
|
|
|
|
val flight = IXplatAbstractions.INSTANCE.getFlight(entity)
|
|
|
|
if (flight.allowed) {
|
|
val flightTime = flight.timeLeft - 1
|
|
if (flightTime < 0 || flight.origin.distanceToSqr(entity.position()) > flight.radius * flight.radius || flight.dimension != entity.level.dimension()) {
|
|
if (!entity.isOnGround) {
|
|
entity.fallDistance = 1_000_000f
|
|
}
|
|
IXplatAbstractions.INSTANCE.setFlight(entity, FlightAbility.deny())
|
|
|
|
if (!entity.isCreative && !entity.isSpectator) {
|
|
val abilities = entity.abilities
|
|
abilities.flying = false
|
|
abilities.mayfly = false
|
|
entity.onUpdateAbilities()
|
|
}
|
|
} else {
|
|
if (!entity.abilities.mayfly) {
|
|
entity.abilities.mayfly = true
|
|
entity.onUpdateAbilities()
|
|
}
|
|
IXplatAbstractions.INSTANCE.setFlight(
|
|
entity,
|
|
FlightAbility(
|
|
true,
|
|
flightTime,
|
|
flight.dimension,
|
|
flight.origin,
|
|
flight.radius
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
fun tickAllPlayers(world: ServerLevel) {
|
|
for (player in world.players()) {
|
|
tickDownFlight(player)
|
|
}
|
|
}
|
|
}
|