aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features/event
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal00212@users.noreply.github.com>2022-10-03 02:37:49 +0200
committerhannibal2 <24389977+hannibal00212@users.noreply.github.com>2022-10-03 02:37:49 +0200
commit2f54732951a7d9b3a64b38f11a39a9e00b6aa02f (patch)
treed23f887c2c07c4283961a08a65c5e1adac24b77d /src/main/java/at/hannibal2/skyhanni/features/event
parent525cf8bb9d86739bb1c1f81e892f79429b2df045 (diff)
downloadskyhanni-2f54732951a7d9b3a64b38f11a39a9e00b6aa02f.tar.gz
skyhanni-2f54732951a7d9b3a64b38f11a39a9e00b6aa02f.tar.bz2
skyhanni-2f54732951a7d9b3a64b38f11a39a9e00b6aa02f.zip
added diana features
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features/event')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt10
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt157
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt224
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt276
4 files changed, 667 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt
new file mode 100644
index 000000000..b7d589440
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/BurrowType.kt
@@ -0,0 +1,10 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.utils.LorenzColor
+
+enum class BurrowType(val text: String, val color: LorenzColor) {
+ START("§aStart",LorenzColor.GREEN),
+ MOB("§cMob",LorenzColor.RED),
+ TREASURE("§6Treasure",LorenzColor.GOLD),
+ UNKNOWN("§fUnknown?!",LorenzColor.WHITE),
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt
new file mode 100644
index 000000000..6c284f255
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt
@@ -0,0 +1,157 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.BurrowDetectEvent
+import at.hannibal2.skyhanni.events.BurrowDugEvent
+import at.hannibal2.skyhanni.events.SoopyGuessBurrowEvent
+import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt
+import at.hannibal2.skyhanni.utils.LocationUtils
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.RenderUtils.drawColor
+import at.hannibal2.skyhanni.utils.RenderUtils.drawString
+import net.minecraft.init.Blocks
+import net.minecraftforge.client.event.RenderWorldLastEvent
+import net.minecraftforge.event.world.WorldEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class GriffinBurrowHelper {
+
+ private var guessLocation: LorenzVec? = null
+ private var particleBurrows = mutableMapOf<LorenzVec, BurrowType>()
+ private var animationLocation: LorenzVec? = null
+ private var lastDug: LorenzVec? = null
+
+ @SubscribeEvent
+ fun onSoopyGuessBurrow(event: SoopyGuessBurrowEvent) {
+// if (!SkyHanniMod.feature.diana.burrowsSoopyGuess) return
+
+ if (SkyHanniMod.feature.diana.burrowsSoopyGuess) {
+ if (guessLocation == null) {
+ animationLocation = lastDug ?: LocationUtils.playerLocation()
+ }
+ }
+ guessLocation = event.guessLocation
+ if (SkyHanniMod.feature.diana.burrowsNearbyDetection) {
+ checkRemoveGuess(false)
+ }
+ }
+
+ @SubscribeEvent
+ fun onBurrowDetect(event: BurrowDetectEvent) {
+ particleBurrows[event.burrowLocation] = event.type
+
+ if (SkyHanniMod.feature.diana.burrowsNearbyDetection) {
+ checkRemoveGuess(true)
+ }
+ }
+
+ private fun checkRemoveGuess(animation: Boolean) {
+ guessLocation?.let { guessRaw ->
+ val guess = findBlock(guessRaw)
+ if (particleBurrows.any { guess.distance(it.key) < 20 }) {
+ if (animation) {
+ animationLocation = guess
+ }
+ guessLocation = null
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onBurrowDug(event: BurrowDugEvent) {
+ val location = event.burrowLocation
+ particleBurrows.remove(location)
+ if (particleBurrows.isNotEmpty()) {
+ animationLocation = location
+ }
+ lastDug = location
+ }
+
+ @SubscribeEvent
+ fun onWorldChange(event: WorldEvent.Load) {
+ guessLocation = null
+ animationLocation = null
+ lastDug = null
+ particleBurrows.clear()
+ }
+
+ private fun findBlock(point: LorenzVec): LorenzVec {
+ var gY = 131.0
+
+ var searchGrass = true
+ while ((if (searchGrass) LorenzVec(point.x, gY, point.z).getBlockAt() != Blocks.grass else LorenzVec(
+ point.x,
+ gY,
+ point.z
+ ).getBlockAt() == Blocks.air)
+ ) {
+ gY--
+ if (gY < 70) {
+ if (!searchGrass) {
+ break
+ } else {
+ searchGrass = false
+ gY = 131.0
+ }
+ }
+ }
+ return LorenzVec(point.x, gY, point.z)
+ }
+
+ @SubscribeEvent
+ fun onRenderWorld(event: RenderWorldLastEvent) {
+ val playerLocation = LocationUtils.playerLocation()
+ if (SkyHanniMod.feature.diana.burrowsSoopyGuess) {
+ guessLocation?.let {
+ val guessLocation = findBlock(it)
+ val distance = guessLocation.distance(playerLocation)
+ event.drawColor(guessLocation, LorenzColor.WHITE, distance > 10)
+ if (distance < 10) {
+ event.drawString(guessLocation.add(0.5, 1.5, 0.5), "§fSoopy Guess", true)
+ }
+ }
+ }
+
+ if (SkyHanniMod.feature.diana.burrowSmoothTransition) {
+ animationLocation?.let {
+ event.drawColor(it, LorenzColor.WHITE)
+ animationLocation = moveAnimation(it)
+ }
+ }
+
+ if (SkyHanniMod.feature.diana.burrowsNearbyDetection) {
+ for (burrow in particleBurrows) {
+ val location = burrow.key
+ val distance = location.distance(playerLocation)
+ val burrowType = burrow.value
+ event.drawColor(location, burrowType.color, distance > 10)
+ if (distance < 10) {
+ event.drawString(location.add(0.5, 1.5, 0.5), burrowType.text, true)
+ }
+ }
+ }
+ }
+
+ private fun moveAnimation(animation: LorenzVec): LorenzVec? {
+ val list = mutableListOf<LorenzVec>()
+ list.addAll(particleBurrows.keys)
+ guessLocation?.let {
+ val loc = findBlock(it)
+ if (loc.y > 200) {
+ list.add(LorenzVec(loc.x, LocationUtils.playerLocation().y, loc.z))
+ } else {
+ list.add(loc)
+ }
+ }
+ val target = list.minByOrNull { it.distance(animation) } ?: return null
+ val distance = target.distance(animation)
+ if (distance < 0.20) return null
+
+ var vector = target.subtract(animation)
+
+ vector = vector.multiply(1 / vector.length())
+ vector = vector.multiply(0.18)
+ return animation.add(vector)
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt
new file mode 100644
index 000000000..72862c7e2
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowParticleFinder.kt
@@ -0,0 +1,224 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.events.BurrowDetectEvent
+import at.hannibal2.skyhanni.events.BurrowDugEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.events.PacketEvent
+import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.toLorenzVec
+import net.minecraft.client.Minecraft
+import net.minecraft.init.Blocks
+import net.minecraft.item.ItemStack
+import net.minecraft.network.play.client.C07PacketPlayerDigging
+import net.minecraft.network.play.client.C08PacketPlayerBlockPlacement
+import net.minecraft.network.play.server.S2APacketParticles
+import net.minecraftforge.event.world.WorldEvent
+import net.minecraftforge.fml.common.eventhandler.EventPriority
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class GriffinBurrowParticleFinder {
+
+ private val recentlyDugParticleBurrows = mutableListOf<LorenzVec>()
+ private val burrows = mutableMapOf<LorenzVec, Burrow>()
+ var lastDugParticleBurrow: LorenzVec? = null
+
+ // private enum class ParticleType(val check: ReceiveParticleEvent.() -> Boolean) {
+// EMPTY({
+// type == net.minecraft.util.EnumParticleTypes.CRIT_MAGIC && count == 4 && speed == 0.01f && offset.x == 0.5 && offset.y == 0.1 && offset.z == 0.5
+// }),
+// MOB({
+// type == net.minecraft.util.EnumParticleTypes.CRIT && count == 3 && speed == 0.01f && offset.x == 0.5 && offset.y == 0.1 && offset.z == 0.5
+//
+// }),
+// TREASURE({
+// type == net.minecraft.util.EnumParticleTypes.DRIP_LAVA && count == 2 && speed == 0.01f && offset.x == 0.35 && offset.y == 0.1 && offset.z == 0.35
+// }),
+// FOOTSTEP({
+// type == net.minecraft.util.EnumParticleTypes.FOOTSTEP && count == 1 && speed == 0.0f && offset.x == 0.05 && offset.y == 0.0 && offset.z == 0.05
+// }),
+// ENCHANT({
+// type == net.minecraft.util.EnumParticleTypes.ENCHANTMENT_TABLE && count == 5 && speed == 0.05f && offset.x == 0.5 && offset.y == 0.4 && offset.z == 0.5
+// });
+//
+// companion object {
+// fun getParticleType(packet: ReceiveParticleEvent): ParticleType? {
+// if (!packet.longDistance) return null
+// for (type in values()) {
+// if (type.check(packet)) {
+// return type
+// }
+// }
+// return null
+// }
+// }
+// }
+//
+// @SubscribeEvent
+// fun onChatPacket(event: ReceiveParticleEvent) {
+// if (!LorenzUtils.inSkyblock) return
+// if (!SkyHanniMod.feature.dev.debugEnabled) return
+//
+// val particleType = getParticleType(event)
+// if (particleType != null) {
+//
+// val location = event.location.toBlocPos().down().toLorenzVec()
+// if (recentlyDugParticleBurrows.contains(location)) return
+// val burrow = particleBurrows.getOrPut(location) { ParticleBurrow(location) }
+//
+// when (particleType) {
+// ParticleType.FOOTSTEP -> burrow.hasFootstep = true
+// ParticleType.ENCHANT -> burrow.hasEnchant = true
+// ParticleType.EMPTY -> burrow.type = 0
+// ParticleType.MOB -> burrow.type = 1
+// ParticleType.TREASURE -> burrow.type = 2
+// }
+//
+// }
+//
+// }
+
+ @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true)
+ fun onChatPacket(event: PacketEvent.ReceiveEvent) {
+ if (!LorenzUtils.inSkyblock) return
+ val packet = event.packet
+
+ if (packet is S2APacketParticles) {
+
+ val particleType = ParticleType.getParticleType(packet)
+ if (particleType != null) {
+
+ val location = packet.toLorenzVec().toBlocPos().down().toLorenzVec()
+ if (recentlyDugParticleBurrows.contains(location)) return
+ val burrow = burrows.getOrPut(location) { Burrow(location) }
+
+ when (particleType) {
+ ParticleType.FOOTSTEP -> burrow.hasFootstep = true
+ ParticleType.ENCHANT -> burrow.hasEnchant = true
+ ParticleType.EMPTY -> burrow.type = 0
+ ParticleType.MOB -> burrow.type = 1
+ ParticleType.TREASURE -> burrow.type = 2
+ }
+
+ if (burrow.hasEnchant && burrow.hasFootstep && burrow.type != -1) {
+ if (!burrow.found) {
+ BurrowDetectEvent(burrow.location, burrow.getType()).postAndCatch()
+ }
+ burrow.found = true
+ }
+ }
+ }
+ }
+
+ private enum class ParticleType(val check: S2APacketParticles.() -> Boolean) {
+ EMPTY({
+ particleType == net.minecraft.util.EnumParticleTypes.CRIT_MAGIC && particleCount == 4 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f
+ }),
+ MOB({
+ particleType == net.minecraft.util.EnumParticleTypes.CRIT && particleCount == 3 && particleSpeed == 0.01f && xOffset == 0.5f && yOffset == 0.1f && zOffset == 0.5f
+
+ }),
+ TREASURE({
+ particleType == net.minecraft.util.EnumParticleTypes.DRIP_LAVA && particleCount == 2 && particleSpeed == 0.01f && xOffset == 0.35f && yOffset == 0.1f && zOffset == 0.35f
+ }),
+ FOOTSTEP({
+ particleType == net.minecraft.util.EnumParticleTypes.FOOTSTEP && particleCount == 1 && particleSpeed == 0.0f && xOffset == 0.05f && yOffset == 0.0f && zOffset == 0.05f
+ }),
+ ENCHANT({
+ particleType == net.minecraft.util.EnumParticleTypes.ENCHANTMENT_TABLE && particleCount == 5 && particleSpeed == 0.05f && xOffset == 0.5f && yOffset == 0.4f && zOffset == 0.5f
+ });
+
+ companion object {
+
+ fun getParticleType(packet: S2APacketParticles): ParticleType? {
+ if (!packet.isLongDistance) return null
+ for (type in values()) {
+ if (type.check(packet)) {
+ return type
+ }
+ }
+ return null
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onWorldChange(event: WorldEvent.Load) {
+ burrows.clear()
+ recentlyDugParticleBurrows.clear()
+ }
+
+ @SubscribeEvent
+ fun onChatMessage(event: LorenzChatEvent) {
+ val message = event.message
+ if (message.startsWith("§eYou dug out a Griffin Burrow!") ||
+ message == "§eYou finished the Griffin burrow chain! §r§7(4/4)"
+ ) {
+ val burrow = lastDugParticleBurrow
+ if (burrow != null) {
+ recentlyDugParticleBurrows.add(burrow)
+ lastDugParticleBurrow = null
+ burrows.remove(burrow)?.let {
+ if (it.found) {
+ BurrowDugEvent(it.location).postAndCatch()
+ }
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onSendPacket(event: PacketEvent.SendEvent) {
+ if (!LorenzUtils.inSkyblock) return
+ val packet = event.packet
+ val pos = when {
+ packet is C07PacketPlayerDigging && packet.status == C07PacketPlayerDigging.Action.START_DESTROY_BLOCK -> {
+ packet.position
+ }
+
+ packet is C08PacketPlayerBlockPlacement && packet.stack != null -> packet.position
+ else -> return
+ }.toLorenzVec()
+ if (Minecraft.getMinecraft().thePlayer.heldItem?.isSpade != true || pos.getBlockAt() !== Blocks.grass) return
+ if (burrows.containsKey(pos)) {
+ lastDugParticleBurrow = pos
+ }
+ }
+
+ private val ItemStack.isSpade
+ get() = this.getInternalName() == "ANCESTRAL_SPADE"
+
+ class Burrow(
+ var location: LorenzVec,
+ var hasFootstep: Boolean = false,
+ var hasEnchant: Boolean = false,
+ var type: Int = -1,
+ var found: Boolean = false,
+ ) {
+
+ fun getType(): BurrowType {
+ return when (this.type) {
+ 0 -> BurrowType.START
+ 1 -> BurrowType.MOB
+ 2 -> BurrowType.TREASURE
+ else -> BurrowType.UNKNOWN
+ }
+ }
+
+// private fun getWaypointText(): String {
+// var type = "Burrow"
+// when (this.type) {
+// 0 -> type = "§aStart"
+// 1 -> type = "§cMob"
+// 2 -> type = "§6Treasure"
+// }
+// return "$type §a(Particle)"
+// }
+ }
+}
+
+private fun S2APacketParticles.toLorenzVec(): LorenzVec {
+ return LorenzVec(xCoordinate, yCoordinate, zCoordinate)
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt
new file mode 100644
index 000000000..467cc9f81
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/SoopyGuessBurrow.kt
@@ -0,0 +1,276 @@
+package at.hannibal2.skyhanni.features.event.diana
+
+import at.hannibal2.skyhanni.events.PlaySoundEvent
+import at.hannibal2.skyhanni.events.ReceiveParticleEvent
+import at.hannibal2.skyhanni.events.SoopyGuessBurrowEvent
+import at.hannibal2.skyhanni.utils.LorenzVec
+import at.hannibal2.skyhanni.utils.toLorenzVec
+import net.minecraft.util.EnumParticleTypes
+import net.minecraftforge.event.world.WorldEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.math.*
+
+/**
+ * Taken and ported from Soopyboo32's javascript module SoopyV2
+ */
+class SoopyGuessBurrow {
+
+ var dingIndex = 0
+ var lastDing = 0L
+ var lastDingPitch = 0f
+ var firstPitch = 0f
+ var lastParticlePoint: LorenzVec? = null
+ var lastParticlePoint2: LorenzVec? = null
+ var firstParticlePoint: LorenzVec? = null
+ var particlePoint: LorenzVec? = null
+ var guessPoint: LorenzVec? = null
+
+ var lastSoundPoint: LorenzVec? = null
+ var locs = mutableListOf<LorenzVec>()
+
+ var dingSlope = mutableListOf<Float>()
+
+ var distance: Double? = null
+ var distance2: Double? = null
+
+ @SubscribeEvent
+ fun onWorldChange(event: WorldEvent.Load) {
+ lastDing = 0L
+ lastDingPitch = 0f
+ firstPitch = 0f
+ lastParticlePoint = null
+ lastParticlePoint2 = null
+ lastSoundPoint = null
+ firstParticlePoint = null
+ particlePoint = null
+ guessPoint = null
+ distance = null
+ dingIndex = 0
+ dingSlope.clear()
+ }
+
+ @SubscribeEvent
+ fun onPlaySound(event: PlaySoundEvent) {
+ if (event.soundName != "note.harp") return
+
+ val pitch = event.pitch
+ if (lastDing == 0L) {
+ firstPitch = pitch
+ }
+
+ lastDing = System.currentTimeMillis()
+
+ if (pitch < lastDingPitch) {
+ firstPitch = pitch
+ dingIndex = 0
+ dingSlope.clear()
+ lastDingPitch = pitch
+ lastParticlePoint = null
+ lastParticlePoint2 = null
+ lastSoundPoint = null
+ firstParticlePoint = null
+ distance = null
+ locs.clear()
+ }
+
+ if (lastDingPitch == 0f) {
+ lastDingPitch = pitch
+ distance = null
+ lastParticlePoint = null
+ lastParticlePoint2 = null
+ lastSoundPoint = null
+ firstParticlePoint = null
+ locs.clear()
+ return
+ }
+
+ dingIndex++
+
+ if (dingIndex > 1) dingSlope.add(pitch - lastDingPitch)
+ if (dingSlope.size > 20) dingSlope.removeFirst()
+ val slope = if (dingSlope.isNotEmpty()) dingSlope.reduce { a, b -> a + b }.toDouble() / dingSlope.size else 0.0
+ val pos = event.location
+ lastSoundPoint = pos
+ lastDingPitch = pitch
+
+ if (lastParticlePoint2 == null || particlePoint == null || firstParticlePoint == null) {
+ return
+ }
+
+ distance2 = (Math.E / slope) - firstParticlePoint?.distance(pos)!!
+
+ if (distance2!! > 1000) {
+ distance2 = null
+ guessPoint = null
+ }
+
+ val lineDist = lastParticlePoint2?.distance(particlePoint!!)!!
+
+ distance = distance2!!
+ val changesHelp = particlePoint?.subtract(lastParticlePoint2!!)!!
+ var changes = listOf(changesHelp.x, changesHelp.y, changesHelp.z)
+ changes = changes.map { o -> o / lineDist }
+
+ lastSoundPoint?.let {
+ guessPoint =
+ LorenzVec(
+ it.x + changes[0] * distance!!,
+ it.y + changes[1] * distance!!,
+ it.z + changes[2] * distance!!
+ )
+ }
+ }
+
+ private fun solveEquationThing(x: LorenzVec, y: LorenzVec): LorenzVec {
+ val a =
+ (-y.x * x.y * x.x - y.y * x.y * x.z + y.y * x.y * x.x + x.y * x.z * y.z + x.x * x.z * y.x - x.x * x.z * y.z) / (x.y * y.x - x.y * y.z + x.x * y.z - y.x * x.z + y.y * x.z - y.y * x.x)
+ val b = (y.x - y.y) * (x.x + a) * (x.y + a) / (x.y - x.x)
+ val c = y.x - b / (x.x + a)
+ return LorenzVec(a, b, c)
+ }
+
+ @SubscribeEvent
+ fun onReceiveParticle(event: ReceiveParticleEvent) {
+ val type = event.type
+ if (type != EnumParticleTypes.DRIP_LAVA) return
+ val currLoc = event.location
+
+ var run = false
+ lastSoundPoint?.let {
+ if (abs(currLoc.x - it.x) < 2 && abs(currLoc.y - it.y) < 0.5 && abs(currLoc.z - it.z) < 2) {
+ run = true
+ }
+ }
+ if (run) {
+ if (locs.size < 100 && locs.isEmpty() || locs.last().distance(currLoc) != 0.0) {
+ var distMultiplier = 1.0
+ if (locs.size > 2) {
+ val predictedDist = 0.06507 * locs.size + 0.259
+ val lastPos = locs.last()
+ val actualDist = currLoc.distance(lastPos)
+ distMultiplier = actualDist / predictedDist
+ }
+ locs.add(currLoc)
+
+ if (locs.size > 5 && guessPoint != null) {
+
+ val slopeThing = locs.zipWithNext { a, b ->
+ atan((a.x - b.x) / (a.z - b.z))
+ }
+
+// val slopeThing = mutableListOf<Double>()
+// for ((index, current) in locs.withIndex()) {
+// if (index != 0) {
+// val last = locs[index - 1]
+// slopeThing.add(atan((current.x - last.x) / (current.z - last.z)))
+// }
+// }
+
+ val (a, b, c) = solveEquationThing(
+ LorenzVec(slopeThing.size - 5, slopeThing.size - 3, slopeThing.size - 1), LorenzVec(
+ slopeThing[slopeThing.size - 5],
+ slopeThing[slopeThing.size - 3],
+ slopeThing[slopeThing.size - 1]
+ )
+ )
+
+ val pr1 = mutableListOf<LorenzVec>()
+ val pr2 = mutableListOf<LorenzVec>()
+
+ val start = slopeThing.size - 1
+ val lastPos = locs[start].multiply(1).toDoubleArray()
+ val lastPos2 = locs[start].multiply(1).toDoubleArray()
+
+ var distCovered = 0.0
+
+ val ySpeed = locs[locs.size - 1].x - locs[locs.size - 2].x / hypot(
+ locs[locs.size - 1].x - locs[locs.size - 2].x,
+ locs[locs.size - 1].z - locs[locs.size - 2].x
+ )
+
+ var i = start + 1
+ while (distCovered < distance2!! && i < 10000) {
+ val y = b / (i + a) + c
+ val dist = distMultiplier * (0.06507 * i + 0.259)
+
+ val xOff = dist * sin(y)
+ val zOff = dist * cos(y)
+
+ val dencity = 5
+
+ for (o in 0..dencity) {
+ lastPos[0] += xOff / dencity
+ lastPos[2] += zOff / dencity
+
+ lastPos[1] += ySpeed * dist / dencity
+ lastPos2[1] += ySpeed * dist / dencity
+
+ lastPos2[0] -= xOff / dencity
+ lastPos2[2] -= zOff / dencity
+
+ pr1.add(lastPos.toLorenzVec())
+ pr2.add(lastPos2.toLorenzVec())
+
+
+ lastSoundPoint?.let {
+ distCovered = hypot(lastPos[0] - it.x, lastPos[2] - it.z)
+ }
+
+ if (distCovered > distance2!!) break
+ }
+ i++
+ }
+
+ //Why does this happen?
+ if (pr1.isEmpty()) return
+
+ val p1 = pr1.last()
+ val p2 = pr2.last()
+
+
+ guessPoint?.let {
+ val d1 = ((p1.x - it.x).times(2 + (p1.z - it.z))).pow(2)
+ val d2 = ((p2.x - it.x).times(2 + (p2.z - it.z))).pow(2)
+
+ val finalLocation = if (d1 < d2) {
+ LorenzVec(floor(p1.x), 255.0, floor(p1.z))
+ } else {
+ LorenzVec(floor(p2.x), 255.0, floor(p2.z))
+ }
+ SoopyGuessBurrowEvent(finalLocation).postAndCatch()
+ }
+ }
+ }
+
+ if (lastParticlePoint == null) {
+ firstParticlePoint = currLoc.clone()
+ }
+
+ lastParticlePoint2 = lastParticlePoint
+ lastParticlePoint = particlePoint
+
+ particlePoint = currLoc.clone()
+
+ if (lastParticlePoint2 == null || firstParticlePoint == null || distance2 == null || lastSoundPoint == null) return
+
+
+ val lineDist = lastParticlePoint2?.distance(particlePoint!!)!!
+
+ distance = distance2!!
+
+ val changesHelp = particlePoint?.subtract(lastParticlePoint2!!)!!
+
+ var changes = listOf(changesHelp.x, changesHelp.y, changesHelp.z)
+ changes = changes.map { o -> o / lineDist }
+
+ lastParticlePoint?.let {
+ guessPoint =
+ LorenzVec(
+ it.x + changes[0] * distance!!,
+ it.y + changes[1] * distance!!,
+ it.z + changes[2] * distance!!
+ )
+ }
+ }
+ }
+} \ No newline at end of file