Compare commits

...
12 changed files with 337 additions and 170 deletions

No files matched your search

@@ -39,8 +39,13 @@ class RidingController<Settings : RidingBehaviourSettings, State : RidingBehavio
return behaviour.speed(settings, state, vehicle, driver)
}
override fun clampPassengerRotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity) {
if (!isActive(settings, state, vehicle)) return
return behaviour.clampPassengerRotation(settings, state, vehicle, driver)
}
override fun rotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity): Vec2 {
if (!isActive(settings, state, vehicle)) return vehicle.rotationVector
if (!isActive(settings, state, vehicle)) return driver.rotationVector
return behaviour.rotation(settings, state, vehicle, driver)
}
@@ -35,7 +35,7 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
override val key: ResourceLocation = KEY
val poseProvider = PoseProvider<BirdAirSettings, BirdAirState>(PoseType.HOVER)
.with(PoseOption(PoseType.FLY) { _, state, _ -> state.rideVel.get().z > 0.1 })
.with(PoseOption(PoseType.FLY) { _, state, _ -> state.rideVel.get().z > 0.2 })
override fun isActive(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
return true
@@ -96,7 +96,7 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
upForce -= 0.3
}
val altitudeLimit = vehicle.runtime.resolveDouble(settings.altitudeExpr)
val altitudeLimit = vehicle.runtime.resolveDouble(settings.jumpExpr)
//Only limit altitude if altitude is not infinite
if (!vehicle.runtime.resolveBoolean(settings.infiniteAltitude)) {
@@ -113,9 +113,9 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
*/
fun calculateRideSpaceVel(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity, driver: Player) {
//retrieve stats
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glideTopSpeedExpr)
val accel = vehicle.runtime.resolveDouble(settings.accelExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glidespeedExpr)
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr)
val staminaStat = vehicle.runtime.resolveDouble(settings.staminaExpr)
var glideSpeedChange = 0.0
@@ -237,11 +237,9 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
}
//air resistance
newVelocity = Vec3(
newVelocity.x,
newVelocity.y,
lerp( newVelocity.z,0.0, topSpeed / ( 20.0 * 30.0))
)
if( abs(newVelocity.z) > 0) {
newVelocity = newVelocity.subtract(0.0, 0.0, min(0.003 * newVelocity.z.sign, newVelocity.z))
}
state.rideVel.set(newVelocity)
}
@@ -257,8 +255,8 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
//TODO: Tie into handling
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val rotationChangeRate = 10.0
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val rotationChangeRate = 10.0
var yawForce = rotationChangeRate * sin(Math.toRadians(controller.roll.toDouble()))
//for a bit of correction on the rolls limit it to a quarter the amount
@@ -287,14 +285,16 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
val controller = (driver as OrientationControllable).orientationController
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
//Smooth out mouse input.
val smoothingSpeed = 4
val smoothingSpeed = 4.0
val invertRoll = if (Cobblemon.config.invertRoll) -1 else 1
val invertPitch = if (Cobblemon.config.invertPitch) -1 else 1
val xInput = mouseXSmoother.getNewDeltaValue(mouseX * 0.1 * invertRoll, deltaTime * smoothingSpeed);
val yInput = mouseYSmoother.getNewDeltaValue(mouseY * 0.1 * invertPitch, deltaTime * smoothingSpeed);
val mouseXc = (mouseX).coerceIn(-60.0, 60.0)
val mouseYc = (mouseY).coerceIn(-60.0, 60.0)
val xInput = mouseXSmoother.getNewDeltaValue(mouseXc * 0.1 * invertRoll, deltaTime * smoothingSpeed);
val yInput = mouseYSmoother.getNewDeltaValue(mouseYc * 0.1 * invertPitch, deltaTime * smoothingSpeed);
//limit rolling based on handling and current speed.
//modulated by speed so that when flapping idle in air you are ont wobbling around to look around
@@ -374,8 +374,8 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
vehicle: PokemonEntity,
driver: Player
): Float {
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glideTopSpeedExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glidespeedExpr)
//Must I ensure that topspeed is greater than minimum?
val normalizedGlideSpeed = normalizeVal(state.rideVel.get().length(), topSpeed, glideTopSpeed)
@@ -440,52 +440,41 @@ class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
class BirdAirSettings : RidingBehaviourSettings {
override val key = BirdAirBehaviour.KEY
//max y level for the ride
var altitudeExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 200.0, 128.0)".asExpression()
private set
var infiniteAltitude: Expression = "false".asExpression()
private set
var infiniteStamina: Expression = "false".asExpression()
private set
//max y level for the ride
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 200.0, 128.0)".asExpression()
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 135.0, 45.0)".asExpression()
private set
var topSpeedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 1.0, 0.35)".asExpression()
private set
var glideTopSpeedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 2.0, 1.0)".asExpression()
private set
// Max accel is a whole 1.0 in 3 seconds. The conversion in the function below is to convert seconds to ticks
var accelExpr: Expression = "q.get_ride_stats('ACCELERATION', 'AIR', (1.0 / (20.0 * 3.0)), (1.0 / (20.0 * 8.0)))".asExpression()
private set
//Seconds self propelled flight (glide is not self propelled in this case)
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 1.0, 0.35)".asExpression()
var accelerationExpr: Expression = "q.get_ride_stats('ACCELERATION', 'AIR', (1.0 / (20.0 * 3.0)), (1.0 / (20.0 * 8.0)))".asExpression()
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 120.0, 20.0)".asExpression()
var glidespeedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 2.0, 1.0)".asExpression()
private set
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeExpression(altitudeExpr)
buffer.writeExpression(infiniteAltitude)
buffer.writeExpression(infiniteStamina)
buffer.writeExpression(glidespeedExpr)
buffer.writeExpression(jumpExpr)
buffer.writeExpression(handlingExpr)
buffer.writeExpression(topSpeedExpr)
buffer.writeExpression(glideTopSpeedExpr)
buffer.writeExpression(accelExpr)
buffer.writeExpression(speedExpr)
buffer.writeExpression(accelerationExpr)
buffer.writeExpression(staminaExpr)
}
override fun decode(buffer: RegistryFriendlyByteBuf) {
altitudeExpr = buffer.readExpression()
infiniteAltitude = buffer.readExpression()
infiniteStamina = buffer.readExpression()
glidespeedExpr = buffer.readExpression()
jumpExpr = buffer.readExpression()
handlingExpr = buffer.readExpression()
topSpeedExpr = buffer.readExpression()
glideTopSpeedExpr = buffer.readExpression()
accelExpr = buffer.readExpression()
speedExpr = buffer.readExpression()
accelerationExpr = buffer.readExpression()
staminaExpr = buffer.readExpression()
}
}
@@ -9,7 +9,7 @@
package com.cobblemon.mod.common.api.riding.behaviour.types
import com.bedrockk.molang.Expression
import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.MoLangMath.lerp
import com.cobblemon.mod.common.api.riding.behaviour.*
import com.cobblemon.mod.common.api.riding.posing.PoseOption
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
@@ -17,15 +17,14 @@ import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.*
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.util.Mth
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec2
import net.minecraft.world.phys.Vec3
import net.minecraft.world.phys.shapes.Shapes
import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.*
class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandState> {
companion object {
@@ -36,7 +35,7 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
val poseProvider = PoseProvider<GenericLandSettings, GenericLandState>(PoseType.STAND)
.with(PoseOption(PoseType.WALK) { _, state, _ ->
return@PoseOption state.rideVel.get().z > 0.1
return@PoseOption abs(state.rideVel.get().z) > 0.2
})
override fun isActive(
@@ -75,15 +74,99 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
return state.rideVel.get().length().toFloat()
}
override fun updatePassengerRotation(
settings: GenericLandSettings,
state: GenericLandState,
vehicle: PokemonEntity,
driver: LivingEntity
) {
//Take the inverse so that it cancels out how
//much the entity rotates.
val turnAmount = calcRotAmount(settings, state, vehicle, driver)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val maxYawDiff = 90.0f
//Normalize the current rotation diff
val rotMod = Mth.wrapDegrees(driver.yRot - vehicle.yRot) / maxYawDiff
val rotAmount = 10.0f
//Take the inverse so that you turn more at higher speeds
val normSpeed = 1.0f - 0.5f*normalizeVal(state.rideVel.get().length(), 0.0, topSpeed).toFloat()
//driver.yRot += (entity.riding.deltaRotation.y - turnAmount)
//driver.setYHeadRot(driver.yHeadRot + (entity.riding.deltaRotation.y) - turnAmount)
}
override fun clampPassengerRotation(
settings: GenericLandSettings,
state: GenericLandState,
vehicle: PokemonEntity,
driver: LivingEntity
) {
val f = Mth.wrapDegrees(driver.yRot - vehicle.yRot)
val lookYawLimit = 90.0f
val g = Mth.clamp(f, -lookYawLimit, lookYawLimit)
driver.yRotO += g - f
driver.yRot = driver.yRot + g - f
driver.setYHeadRot(driver.yRot)
}
override fun rotation(
settings: GenericLandSettings,
state: GenericLandState,
vehicle: PokemonEntity,
driver: LivingEntity
): Vec2 {
return Vec2(driver.xRot * 0.5f, driver.yRot)
val turnAmount = calcRotAmount(settings, state, vehicle, driver)
return Vec2(driver.xRot, vehicle.yRot + turnAmount )
}
/*
* Calculates the rotation amount given the difference between
* the current player y rot and entity y rot. This gives the
* affect of influencing a rides rotation through the mouse
* without it being instant.
*/
fun calcRotAmount(
settings: GenericLandSettings,
state: GenericLandState,
vehicle: PokemonEntity,
driver: LivingEntity
): Float {
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
//In degrees per second
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
val maxYawDiff = 90.0f
//Normalize the current rotation diff
val rotDiff = Mth.wrapDegrees(driver.yRot - vehicle.yRot)
val rotDiffNorm = rotDiff / maxYawDiff
//Take the square root so that the ride levels out quicker when at lower differences between entity
//y and driver y
//This influences the speed of the turn based on how far in one direction you're looking
val rotDiffMod = (sqrt(abs(rotDiffNorm)) * rotDiffNorm.sign)
//Take the inverse so that you turn less at higher speeds
val normSpeed = 1.0f // = 1.0f - 0.5f*normalizeVal(state.rideVel.length(), 0.0, topSpeed).toFloat()
// TODO: This needs to be tweaked with in game results and testing
val turnRate = (handling.toFloat() / 20.0f) * 2
//Ensure you only ever rotate as much difference as there is between the angles.
val turnSpeed = turnRate * rotDiffMod * normSpeed
val rotAmount = turnSpeed.coerceIn(-abs(rotDiff), abs(rotDiff))
return rotAmount
}
override fun velocity(
settings: GenericLandSettings,
state: GenericLandState,
@@ -91,24 +174,15 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
driver: Player,
input: Vec3
): Vec3 {
val runtime = vehicle.runtime
val driveFactor = runtime.resolveFloat(settings.driveFactor)
val strafeFactor = runtime.resolveFloat(settings.strafeFactor)
val strafeFactor = 0.2
val f = driver.xxa * strafeFactor
var g = driver.zza * driveFactor
var g = driver.zza
if (g <= 0.0f) {
g *= runtime.resolveFloat(settings.reverseDriveFactor)
g *= -1.0f
}
val gravity = -1.0
val newVelocity = calculateRideSpaceVel(settings, state, vehicle, driver)
//Jump the thang!
if (driver.jumping && vehicle.onGround()) {
state.rideVel.set(Vec3(newVelocity.x, 2.0, newVelocity.z))
} else {
state.rideVel.set(newVelocity)
}
state.rideVel.set(calculateRideSpaceVel(settings, state, vehicle, driver))
//This is cheap.
//Also make it stop quicker the slower it is.
@@ -118,7 +192,10 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
//entity.deltaMovement = entity.deltaMovement.lerp(velocity, 1.0)
//state.currVel = state.currVel.add( f.toDouble() / 20.0, gravity / 20.0 , g.toDouble() / 20.0)
//println("Z speed: %.2f".format(state.rideVel.z) + "->" + "Z speed: %.2f".format(entity.deltaMovement.horizontalDistance()))
return state.rideVel.get()
}
private fun calculateRideSpaceVel(
@@ -127,35 +204,82 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
vehicle: PokemonEntity,
driver: Player
): Vec3 {
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val accel = vehicle.runtime.resolveDouble(settings.accelExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr)
val speed = state.rideVel.get().length()
//Flag for determining if player is actively inputting
var activeInput = false
val minSpeed = 0.0
var newVelocity = Vec3(state.rideVel.get().x, state.rideVel.get().y, state.rideVel.get().z)
//speed up and slow down based on input
if (driver.zza > 0.0 && speed <= topSpeed && state.stamina.get() > 0.0f) {
//modify acceleration to be slower when at closer speeds to top speed
val accelMod = max((normalizeSpeed(speed, minSpeed, topSpeed) - 1).pow(2), 0.1)
newVelocity = Vec3(newVelocity.x, newVelocity.y, min(newVelocity.z + (accel * accelMod), topSpeed))
} else if (driver.zza >= 0.0 && state.stamina.get() == 0.0f || speed > topSpeed) {
newVelocity = Vec3(newVelocity.x, newVelocity.y, max(newVelocity.z - ((accel) / 4), minSpeed))
} else if (driver.zza < 0.0 && speed > minSpeed) {
//modify deccel to be slower when at closer speeds to minimum speed
val deccelMod = max(-(normalizeSpeed(speed, minSpeed, topSpeed)) + 1, 0.0)
var jumpVec = Vec3.ZERO
//Decelerate currently always a constant half of max acceleration.
newVelocity =
Vec3(newVelocity.x, newVelocity.y, max(newVelocity.z - ((accel * deccelMod) / 2), minSpeed))
//speed up and slow down based on input
// if (driver.zza > 0.0 && speed <= topSpeed && state.stamina.get() > 0.0f) {
// //modify acceleration to be slower when at closer speeds to top speed
// val accelMod = max((normalizeVal(speed, minSpeed, topSpeed) - 1).pow(2), 0.1)
// newVelocity = Vec3(newVelocity.x, newVelocity.y, min(newVelocity.z + (accel * accelMod), topSpeed))
// activeInput = true
// jumpVec.add(0.0, 0.0, 1.0)
// } else if (driver.zza >= 0.0 && state.stamina.get() == 0.0f || speed > topSpeed) {
// newVelocity = Vec3(newVelocity.x, newVelocity.y, max(newVelocity.z - ((accel) / 4), minSpeed))
// } else if (driver.zza < 0.0 && speed > minSpeed) {
// //modify deccel to be slower when at closer speeds to minimum speed
// val deccelMod = max(-(normalizeVal(speed, minSpeed, topSpeed)) + 1, 0.0)
//
// //Decelerate currently always a constant half of max acceleration.
// newVelocity =
// Vec3(newVelocity.x, newVelocity.y, max(newVelocity.z - ((accel * deccelMod) / 2), minSpeed))
// activeInput = true
// }
//speed up and slow down based on input
if (driver.zza != 0.0f && state.stamina.get() > 0.0) {
//make sure it can't exceed top speed
val forwardInput = when {
driver.zza > 0 && newVelocity.z > topSpeed -> 0.0
driver.zza < 0 && newVelocity.z < (-topSpeed / 3.0) -> 0.0
else -> driver.zza.sign
}
newVelocity = Vec3(
newVelocity.x,
newVelocity.y,
(newVelocity.z + (accel * forwardInput.toDouble())))
activeInput = true
jumpVec = jumpVec.add(0.0, 0.0, forwardInput.toDouble())
}
//Gravity logic
if (vehicle.onGround()) {
newVelocity = Vec3(newVelocity.x, 0.0, newVelocity.z)
} else {
newVelocity = Vec3(newVelocity.x, max(newVelocity.y - 0.2, -1.0), newVelocity.z)
val gravity = (9.8 / ( 20.0)) * 0.2
val terminalVel = 2.0
val fallingForce = gravity - ( newVelocity.z.sign *gravity *(abs(newVelocity.z) / 2.0))
newVelocity = Vec3(newVelocity.x, max(newVelocity.y - fallingForce, -terminalVel), newVelocity.z)
}
//ground Friction
if( abs(newVelocity.z) > 0 && vehicle.onGround() && !activeInput) {
newVelocity = newVelocity.subtract(0.0, 0.0, min(0.01 * newVelocity.z.sign, newVelocity.z))
}
//Jump the thang!
if (driver.jumping && vehicle.onGround()) {
val jumpVel = 1.0
//Scale current movement direction influence
jumpVec = jumpVec.scale(0.2)
jumpVec = jumpVec.add(0.0, jumpVel, 0.0)
newVelocity = newVelocity.add(0.0, 1.0, 0.0)
}
return newVelocity
}
@@ -163,7 +287,7 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
* Normalizes the current speed between minSpeed and maxSpeed.
* The result is clamped between 0.0 and 1.0, where 0.0 represents minSpeed and 1.0 represents maxSpeed.
*/
private fun normalizeSpeed(currSpeed: Double, minSpeed: Double, maxSpeed: Double): Double {
private fun normalizeVal(currSpeed: Double, minSpeed: Double, maxSpeed: Double): Double {
require(maxSpeed > minSpeed) { "maxSpeed must be greater than minSpeed" }
return ((currSpeed - minSpeed) / (maxSpeed - minSpeed)).coerceIn(0.0, 1.0)
}
@@ -227,10 +351,7 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
driver: Player,
jumpStrength: Int
): Vec3 {
val runtime = vehicle.runtime
runtime.environment.query.addFunction("jump_strength") { DoubleValue(jumpStrength.toDouble()) }
val jumpVector = settings.jumpVector.map { runtime.resolveFloat(it) }
return Vec3(jumpVector[0].toDouble(), jumpVector[1].toDouble(), jumpVector[2].toDouble())
return Vec3.ZERO
}
override fun gravity(
@@ -322,26 +443,17 @@ class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandSta
class GenericLandSettings : RidingBehaviourSettings {
override val key = GenericLandBehaviour.KEY
var driveFactor = "1.0".asExpression()
var canJump = "true".asExpression()
private set
var strafeFactor = "0.2".asExpression()
private set
var reverseDriveFactor = "0.25".asExpression()
private set
var topSpeedExpr: Expression = "q.get_ride_stats('SPEED', 'LAND', 1.0, 0.3)".asExpression()
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'LAND', 1.0, 0.3)".asExpression()
private set
// Max accel is a whole 1.0 in 1 second. The conversion in the function below is to convert seconds to ticks
var accelExpr: Expression =
var accelerationExpr: Expression =
"q.get_ride_stats('ACCELERATION', 'LAND', (1.0 / (20.0 * 0.5)), (1.0 / (20.0 * 5.0)))".asExpression()
private set
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
private set
// Between 30 seconds and 10 seconds at the lowest when at full speed.
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'LAND', 30.0, 10.0)".asExpression()
private set
@@ -354,30 +466,16 @@ class GenericLandSettings : RidingBehaviourSettings {
private set
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeExpression(driveFactor)
buffer.writeExpression(strafeFactor)
buffer.writeExpression(reverseDriveFactor)
buffer.writeExpression(topSpeedExpr)
buffer.writeExpression(accelExpr)
buffer.writeExpression(jumpVector[0])
buffer.writeExpression(jumpVector[1])
buffer.writeExpression(jumpVector[2])
buffer.writeExpression(speedExpr)
buffer.writeExpression(accelerationExpr)
buffer.writeExpression(staminaExpr)
buffer.writeExpression(jumpExpr)
buffer.writeExpression(handlingExpr)
}
override fun decode(buffer: RegistryFriendlyByteBuf) {
driveFactor = buffer.readExpression()
strafeFactor = buffer.readExpression()
reverseDriveFactor = buffer.readExpression()
topSpeedExpr = buffer.readExpression()
accelExpr = buffer.readExpression()
jumpVector = listOf(
buffer.readExpression(),
buffer.readExpression(),
buffer.readExpression()
)
speedExpr = buffer.readExpression()
accelerationExpr = buffer.readExpression()
staminaExpr = buffer.readExpression()
jumpExpr = buffer.readExpression()
handlingExpr = buffer.readExpression()
@@ -388,7 +486,6 @@ class GenericLandSettings : RidingBehaviourSettings {
class GenericLandState : RidingBehaviourState {
var rideVel = ridingState(Vec3.ZERO, Side.CLIENT)
var stamina = ridingState(1.0f, Side.CLIENT)
var currSpeed = ridingState(0.0, Side.BOTH)
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeVec3(rideVel.get())
@@ -403,17 +500,15 @@ class GenericLandState : RidingBehaviourState {
override fun reset() {
rideVel.set(Vec3.ZERO, forced = true)
stamina.set(1.0f, forced = true)
currSpeed.set(0.0, forced = true)
}
override fun toString(): String {
return "GenericLandState(rideVel=${rideVel.get()}, stamina=${stamina.get()}, currSpeed=${currSpeed.get()})"
return "GenericLandState(rideVel=${rideVel.get()}, stamina=${stamina.get()})"
}
override fun copy() = GenericLandState().also {
it.rideVel.set(this.rideVel.get(), forced = true)
it.stamina.set(this.stamina.get(), forced = true)
it.currSpeed.set(this.currSpeed.get(), forced = true)
}
override fun shouldSync(previous: RidingBehaviourState): Boolean {
@@ -46,7 +46,7 @@ class JetAirBehaviour : RidingBehaviour<JetAirSettings, JetAirState> {
override fun speed(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity, driver: Player): Float {
//retrieve stats
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val staminaStat = vehicle.runtime.resolveDouble(settings.staminaExpr)
//retrieve minSpeed
@@ -137,8 +137,8 @@ class JetAirBehaviour : RidingBehaviour<JetAirSettings, JetAirState> {
vehicle: PokemonEntity,
driver: Player
) {
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val accel = vehicle.runtime.resolveDouble(settings.accelExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr)
val altitudeLimit = vehicle.runtime.resolveDouble(settings.jumpExpr)
val minSpeed = vehicle.runtime.resolveDouble(settings.minSpeed)
val speed = state.rideVel.get().length()
@@ -281,7 +281,7 @@ class JetAirBehaviour : RidingBehaviour<JetAirSettings, JetAirState> {
vehicle: PokemonEntity,
driver: Player
): Float {
val topSpeed = vehicle.runtime.resolveDouble(settings.topSpeedExpr)
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
val minSpeed = vehicle.runtime.resolveDouble(settings.minSpeed)
//Must I ensure that topspeed is greater than minimum?
@@ -345,27 +345,9 @@ class JetAirSettings : RidingBehaviourSettings {
var minSpeed: Expression = "1.2".asExpression()
private set
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 140.0, 20.0)".asExpression()
private set
var handlingYawExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 25.0, 8.0)".asExpression()
private set
var topSpeedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 2.5, 1.0)".asExpression()
private set
// Max accel is a whole 1.0 in 1 second. The conversion in the function below is to convert seconds to ticks
var accelExpr: Expression =
"q.get_ride_stats('ACCELERATION', 'AIR', (1.0 / (20.0 * 1.0)), (1.0 / (20.0 * 5.0)))".asExpression()
private set
// Between 60 seconds and 10 seconds at the lowest when at full speed.
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 60.0, 10.0)".asExpression()
private set
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 300.0, 128.0)".asExpression()
private set
// Make configurable by json
var infiniteStamina: Expression = "false".asExpression()
private set
@@ -373,30 +355,41 @@ class JetAirSettings : RidingBehaviourSettings {
var infiniteAltitude: Expression = "false".asExpression()
private set
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 300.0, 128.0)".asExpression()
private set
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 140.0, 20.0)".asExpression()
private set
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 2.5, 1.0)".asExpression()
private set
var accelerationExpr: Expression = "q.get_ride_stats('ACCELERATION', 'AIR', (1.0 / (20.0 * 1.0)), (1.0 / (20.0 * 5.0)))".asExpression()
private set
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 60.0, 10.0)".asExpression()
private set
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeExpression(gravity)
buffer.writeExpression(minSpeed)
buffer.writeExpression(handlingExpr)
buffer.writeExpression(handlingYawExpr)
buffer.writeExpression(topSpeedExpr)
buffer.writeExpression(accelExpr)
buffer.writeExpression(staminaExpr)
buffer.writeExpression(jumpExpr)
buffer.writeExpression(infiniteStamina)
buffer.writeExpression(infiniteAltitude)
buffer.writeExpression(jumpExpr)
buffer.writeExpression(handlingExpr)
buffer.writeExpression(speedExpr)
buffer.writeExpression(accelerationExpr)
buffer.writeExpression(staminaExpr)
}
override fun decode(buffer: RegistryFriendlyByteBuf) {
gravity = buffer.readExpression()
minSpeed = buffer.readExpression()
handlingExpr = buffer.readExpression()
handlingYawExpr = buffer.readExpression()
topSpeedExpr = buffer.readExpression()
accelExpr = buffer.readExpression()
staminaExpr = buffer.readExpression()
jumpExpr = buffer.readExpression()
infiniteStamina = buffer.readExpression()
infiniteAltitude = buffer.readExpression()
jumpExpr = buffer.readExpression()
handlingExpr = buffer.readExpression()
speedExpr = buffer.readExpression()
accelerationExpr = buffer.readExpression()
staminaExpr = buffer.readExpression()
}
}
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.util.readExpression
import com.cobblemon.mod.common.util.writeExpression
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.util.SmoothDouble
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
@@ -114,6 +115,31 @@ class JumpToFlightCompositeBehaviour : RidingBehaviour<JumpToFlightCompositeSett
}
}
override fun clampPassengerRotation(
settings: JumpToFlightCompositeSettings,
state: JumpToFlightCompositeState,
vehicle: PokemonEntity,
driver: LivingEntity
) {
when (state.activeController.get()) {
GenericLandBehaviour.KEY -> landBehaviour.clampPassengerRotation(
settings.land,
state.landState,
vehicle,
driver
)
BirdAirBehaviour.KEY -> birdBehaviour.clampPassengerRotation(
settings.bird,
state.flightState,
vehicle,
driver
)
else -> error("Invalid controller: ${state.activeController.get()}")
}
}
override fun rotation(
settings: JumpToFlightCompositeSettings,
state: JumpToFlightCompositeState,
@@ -45,7 +45,6 @@ class RunToJetCompositeBehaviour : RidingBehaviour<RunToJetCompositeSettings, Ru
val flightState = state.flightState
val groundState = state.landState
if (shouldTransitionToGround(state, vehicle, driver)) {
groundState.currSpeed = flightState.currSpeed
groundState.stamina = flightState.stamina
groundState.rideVel = flightState.rideVel
@@ -53,7 +52,6 @@ class RunToJetCompositeBehaviour : RidingBehaviour<RunToJetCompositeSettings, Ru
vehicle.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
state.timeTransitioned.set(vehicle.level().gameTime)
} else if (shouldTransitionToAir(state, vehicle, driver, input)) {
flightState.currSpeed = groundState.currSpeed
flightState.stamina = groundState.stamina
flightState.rideVel = groundState.rideVel
@@ -117,6 +115,31 @@ class RunToJetCompositeBehaviour : RidingBehaviour<RunToJetCompositeSettings, Ru
}
}
override fun clampPassengerRotation(
settings: RunToJetCompositeSettings,
state: RunToJetCompositeState,
vehicle: PokemonEntity,
driver: LivingEntity
) {
when (state.activeController.get()) {
GenericLandBehaviour.KEY -> landBehaviour.clampPassengerRotation(
settings.land,
state.landState,
vehicle,
driver
)
JetAirBehaviour.KEY -> jetBehaviour.clampPassengerRotation(
settings.jet,
state.flightState,
vehicle,
driver
)
else -> error("Invalid controller: ${state.activeController.get()}")
}
}
override fun rotation(
settings: RunToJetCompositeSettings,
state: RunToJetCompositeState,
@@ -36,11 +36,13 @@ class MarksScrollingWidget(val pX: Int, val pY: Int, val setSelectedMark: () ->
fun createEntries(marks: List<Mark?>) {
marks.chunked(6).forEachIndexed { index, listChunk ->
addEntry(ScrollSlotRow(listChunk, setSelectedMark, setHoveredMark))
addEntry(ScrollSlotRow(this, listChunk, setSelectedMark, setHoveredMark))
}
}
override fun getScrollbarPosition(): Int = pX + width - 3
override fun getRowLeft(): Int = if (children().size > 5) (left + 1) else left
override fun getScrollbarPosition(): Int = rowLeft + width - 3
override fun renderScrollbar(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
// Do not render scrollbar if all rows are already visible
@@ -57,8 +59,8 @@ class MarksScrollingWidget(val pX: Int, val pY: Int, val setSelectedMark: () ->
yTop = this.y
}
context.fill(xLeft, this.y, xRight, this.bottom, FastColor.ARGB32.color(255, 47, 47, 47)) // background
context.fill(xLeft,yTop, xRight, yTop + yBottom, FastColor.ARGB32.color(255, 198, 198, 198)) // base
context.fill(xLeft, this.y, xRight, this.bottom, FastColor.ARGB32.color(255, 75, 75, 75)) // background
context.fill(xLeft,yTop, xRight, yTop + yBottom, FastColor.ARGB32.color(255, 141, 141, 141)) // base
}
}
@@ -72,7 +74,7 @@ class MarksScrollingWidget(val pX: Int, val pY: Int, val setSelectedMark: () ->
override fun getEntry(index: Int): ScrollSlotRow = children()[index] as ScrollSlotRow
override fun renderListItems(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
val rowX = this.rowLeft
val rowX = rowLeft
var anyHovered = false
for (index in 0 until this.itemCount) {
@@ -96,6 +98,7 @@ class MarksScrollingWidget(val pX: Int, val pY: Int, val setSelectedMark: () ->
}
class ScrollSlotRow(
val parent: MarksScrollingWidget,
val markList: List<Mark?>,
val setSelectedMark : () -> Unit,
val setHoveredMark: (Mark?) -> Unit
@@ -109,10 +112,11 @@ class MarksScrollingWidget(val pX: Int, val pY: Int, val setSelectedMark: () ->
fun renderRow(context: GuiGraphics, y: Int, x: Int, mouseX: Int, mouseY: Int): Boolean {
var anyHovered = false
val horizontalSpacing = if (isScrollVisible()) SLOT_SPACING else (SLOT_SPACING + 1)
markList.forEachIndexed { index, mark ->
val matrices = context.pose()
val startPosX = x + ((SLOT_SPACING + SLOT_SIZE) * index)
val startPosX = x + ((horizontalSpacing + SLOT_SIZE) * index)
val startPosY = y + SLOT_SPACING
val slotHovered = mark != null && getHoveredSlotIndex(mouseX, mouseY) == index
@@ -156,9 +160,12 @@ class MarksScrollingWidget(val pX: Int, val pY: Int, val setSelectedMark: () ->
return true
}
private fun isScrollVisible(): Boolean = parent.children().size > 5
private fun getHoveredSlotIndex(mouseX: Int, mouseY: Int): Int {
val horizontalSpacing = if (isScrollVisible()) SLOT_SPACING else (SLOT_SPACING + 1)
markList.forEachIndexed { index, _ ->
val startPosX = x + ((SLOT_SPACING + SLOT_SIZE) * index)
val startPosX = x + ((horizontalSpacing + SLOT_SIZE) * index)
val startPosY = y + SLOT_SPACING + 1
if (mouseX in startPosX..(startPosX + SLOT_SIZE)
@@ -42,7 +42,7 @@ class MarksWidget(
var hoveredMark: Mark? = null
val marksScrollList = MarksScrollingWidget(
pX = pX + 10,
pX = pX + 9,
pY = pY + 45,
setSelectedMark = {
if (hoveredMark != null) {
@@ -733,8 +733,14 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
transformationMatrix.rotate(controller.getRenderOrientation(state.getPartialTicks()))
transformationMatrix.translate(center.negate())
matrixStack.mulPose(transformationMatrix)
// } else if( entity.passengers.isNotEmpty()) {
// // rotate a ridden but non rollable pokemon correctly
// val driver = entity.controllingPassenger ?: entity
// var yRot = Mth.lerp(state.getPartialTicks(), driver.yRotO, driver.yRot)
// yRot = Mth.wrapDegrees(yRot)
// matrixStack.mulPose(Axis.YP.rotationDegrees(180 - yRot))
} else {
var yRot = Mth.lerp(state.getPartialTicks(), entity.yBodyRotO, entity.yBodyRot)
var yRot = Mth.lerp(state.getPartialTicks(), entity.yRotO, entity.yRot)
yRot = Mth.wrapDegrees(yRot)
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - yRot))
}
@@ -178,7 +178,7 @@ class PokemonRenderer(
buffer: MultiBufferSource,
packedLight: Int
) {
val driver = entity.firstPassenger ?: return
val driver = entity.controllingPassenger ?: return
val rollable = driver as? OrientationControllable ?: return
val controller = rollable.orientationController
poseMatrix.pushPose()
@@ -146,7 +146,9 @@ import net.minecraft.world.level.material.FluidState
import net.minecraft.world.level.pathfinder.PathType
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import org.joml.AxisAngle4f
import org.joml.Matrix3f
import org.joml.Quaternionf
import org.joml.Vector3f
@Suppress("unused")
@@ -252,7 +254,6 @@ open class PokemonEntity(
var enablePoseTypeRecalculation = true
// override var ridingController: RideController? = null
var previousRidingState: RidingBehaviourState? = null
var ridingState: RidingBehaviourState? = null
@@ -1536,6 +1537,7 @@ open class PokemonEntity(
}
// TODO: jackowes look over this so I don't accidentally break anything
// TODO: Talk to landon about why this was needed
this.deltaMovement = this.deltaMovement.lerp(v, inertia)
var pos = this.deltaMovement.scale(this.speed.toDouble())
if (super.onGround() && this.deltaMovement.y == 0.0) {
@@ -1563,14 +1565,35 @@ open class PokemonEntity(
if (beamMode != 3) { // Don't let Pokémon move during recall
//Prevent current travel logic when riding a pokemon.
/*
val riders = this.passengers.filterIsInstance<LivingEntity>()
if ( riders.isEmpty() ) {
if ( riders.isEmpty() || this.controllingPassenger == null) {
super.travel(movementInput)
}
*/
else {
val inp = ifRidingAvailableSupply(fallback = Vec3.ZERO) { behaviour, settings, state ->
behaviour.velocity(settings, state, this, this.controllingPassenger as Player, deltaMovement)
}
// Rotate velocity vector to face the current y rotation
val f = Mth.sin(this.getYRot() * 0.017453292f)
val g = Mth.cos(this.getYRot() * 0.017453292f)
val v = Vec3(
inp.x * g.toDouble() - inp.z * f.toDouble(),
inp.y,
inp.z * g.toDouble() + inp.x * f.toDouble()
)
val diff = v.subtract(this.deltaMovement)
val inertia = ifRidingAvailableSupply(fallback = 0.5) { behaviour, settings, state ->
behaviour.inertia(settings, state,this)
}
this.deltaMovement = this.deltaMovement.add( diff.scale(inertia) )
this.move(MoverType.SELF, this.deltaMovement)
}
super.travel(movementInput)
this.updateBlocksTraveled(prevBlockPos)
}
@@ -1855,10 +1878,10 @@ open class PokemonEntity(
}
val rotation = behaviour.rotation(settings, state, this, driver)
this.yRotO = this.yRot
setRot(rotation.y, rotation.x)
this.yHeadRot = this.yRot
this.yBodyRot = this.yRot
this.yRotO = this.yRot
val riders = this.passengers.filterIsInstance<LivingEntity>()
if (behaviour.isActive(settings, state, this) && behaviour.canJump(settings, state, this, driver)) {
@@ -1919,7 +1942,7 @@ open class PokemonEntity(
// }
override fun onPassengerTurned(entityToUpdate: Entity) {
if (entityToUpdate !is LivingEntity) return
if (entityToUpdate !is LivingEntity) return
ifRidingAvailable { behaviour, settings, state ->
behaviour.clampPassengerRotation(settings, state, this, entityToUpdate)
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 469 B

After

Width:  |  Height:  |  Size: 459 B