forked from mirrors/cobblemon
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1af1569f63 | ||
|
|
8a0c98c9ab | ||
|
|
36c5fe2419 | ||
|
|
0c79d102cf | ||
|
|
bd8f644b9a | ||
|
|
7c84cdb05d | ||
|
|
fd6fb5db47 | ||
|
|
a80ada8590 |
@@ -13,6 +13,8 @@
|
||||
- Added `visibility/hidden`, `visibility/hat` and `visibility/face` tags to control where and how certain items are rendered.
|
||||
- Added Pokémon markings, toggleable within the summary.
|
||||
- Added `/boxcount` command to change PC boxes amount
|
||||
- Added `/transformmodelpart (position|rotation|scale) <modelPart> <transform: x y z>` command that can add transformations to a pokemon's model part.
|
||||
- The player executing the command must be facing the target pokemon entity. Transformations are not persistent and will revert when resources are reloaded.
|
||||
|
||||
### Changes
|
||||
- Renamed `chargeGainedPerTick` config to `secondsToChargeHealingMachine`.
|
||||
|
||||
@@ -563,6 +563,8 @@ object Cobblemon {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("wallpaper"), UnlockablePCBoxWallpaperArgumentType::class, SingletonArgumentInfo.contextFree(UnlockablePCBoxWallpaperArgumentType::wallpaper))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("mark"), MarkArgumentType::class, SingletonArgumentInfo.contextFree(MarkArgumentType::mark))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ object CobblemonCommands {
|
||||
ChangeEyeHeight.register(dispatcher)
|
||||
ChangeScaleAndSize.register(dispatcher)
|
||||
ChangeWalkSpeed.register(dispatcher)
|
||||
ChangeJointScaleCommand.register(dispatcher)
|
||||
TransformModelPartCommand.register(dispatcher)
|
||||
TestCommand.register(dispatcher)
|
||||
ReloadShowdownCommand.register(dispatcher)
|
||||
ClickTextCommand.register(dispatcher)
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ object CobblemonPermissions {
|
||||
@JvmStatic
|
||||
val CHANGE_WALK_SPEED = this.create("${COMMAND_PREFIX}changewalkspeed", PermissionLevel.ALL_COMMANDS)
|
||||
@JvmStatic
|
||||
val CHANGE_JOINT_SCALE = this.create("${COMMAND_PREFIX}changejointscale", PermissionLevel.ALL_COMMANDS)
|
||||
val TRANSFORM_MODEL_PART = this.create("${COMMAND_PREFIX}transformmodelpart", PermissionLevel.ALL_COMMANDS)
|
||||
@JvmStatic
|
||||
val CHECKSPAWNS = this.create("${COMMAND_PREFIX}checkspawns", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
@JvmStatic
|
||||
|
||||
+32
-43
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
+25
-32
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-1
@@ -78,8 +78,15 @@ class JsonPose(model: PosableModel, json: JsonObject) {
|
||||
it[2].asDouble
|
||||
)
|
||||
} ?: Vec3.ZERO
|
||||
val scale = it.get("scale")?.asJsonArray?.let {
|
||||
Vec3(
|
||||
it[0].asDouble,
|
||||
it[1].asDouble,
|
||||
it[2].asDouble
|
||||
)
|
||||
} ?: Vec3(1.0,1.0,1.0)
|
||||
val isVisible = it.get("isVisible")?.asString?.asExpressionLike()
|
||||
return@map part.withPosition(position.x, position.y, position.z).withRotationDegrees(rotation.x, rotation.y, rotation.z).also { if (isVisible != null) it.withVisibility(isVisible) }
|
||||
return@map part.withPosition(position.x, position.y, position.z).withRotationDegrees(rotation.x, rotation.y, rotation.z).withScale(scale.x, scale.y, scale.z).also { if (isVisible != null) it.withVisibility(isVisible) }
|
||||
}?.toTypedArray() ?: arrayOf()
|
||||
|
||||
val idleAnimations = (json.get("animations")?.asJsonArray ?: JsonArray()).asJsonArray.mapNotNull {
|
||||
|
||||
+8
-2
@@ -532,7 +532,7 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
/** Puts the model back to its original location and rotations. */
|
||||
fun setDefault() {
|
||||
defaultPositions.forEach { it.set() }
|
||||
transformedParts.forEach { it.set() }
|
||||
transformedParts.forEach { it.apply() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
+2
-2
@@ -46,7 +46,7 @@ class ModelPartTransformation(val modelPart: ModelPart) {
|
||||
var visibility: ExpressionLike? = null
|
||||
|
||||
/** Applies the transformation to the model part. */
|
||||
fun apply(state: PosableState, intensity: Float) {
|
||||
fun apply(state: PosableState? = null, intensity: Float = 1f) {
|
||||
modelPart.x += position[0] * intensity
|
||||
modelPart.y += position[1] * intensity
|
||||
modelPart.z += position[2] * intensity
|
||||
@@ -56,7 +56,7 @@ class ModelPartTransformation(val modelPart: ModelPart) {
|
||||
modelPart.xScale *= ((1 - scale[0]).absoluteValue * intensity) * (scale[0] - 1).sign + 1
|
||||
modelPart.yScale *= ((1 - scale[1]).absoluteValue * intensity) * (scale[1] - 1).sign + 1
|
||||
modelPart.zScale *= ((1 - scale[2]).absoluteValue * intensity) * (scale[2] - 1).sign + 1
|
||||
visibility?.let { modelPart.visible = state.runtime.resolveBoolean(it) }
|
||||
visibility?.let { modelPart.visible = state?.runtime?.resolveBoolean(it)?: defaultRuntime.resolveBoolean(it) }
|
||||
}
|
||||
|
||||
fun set() {
|
||||
|
||||
+2
-1
@@ -76,12 +76,13 @@ object MountedPlayerRenderer {
|
||||
//Rotates player
|
||||
if (player is OrientationControllable && player.orientationController.active && !disableRollableRenderDebug) {
|
||||
val center = Vector3f(0f, player.bbHeight / 2, 0f)
|
||||
val yaw = Mth.rotLerp(partialTicks, entity.yBodyRotO, entity.yBodyRot)
|
||||
val transformationMatrix = Matrix4f()
|
||||
transformationMatrix.translate(center)
|
||||
transformationMatrix.rotate(player.orientationController.getRenderOrientation(partialTicks))
|
||||
transformationMatrix.translate(center.negate(Vector3f()))
|
||||
//Pre-Undo Yaw
|
||||
transformationMatrix.rotate(Axis.YP.rotationDegrees(yBodyRot+180f))
|
||||
transformationMatrix.rotate(Axis.YP.rotationDegrees(yaw+180f))
|
||||
matrix.mul(transformationMatrix)
|
||||
}
|
||||
matrix.translate(0f, 0.25f, 0f)
|
||||
|
||||
+5
-1
@@ -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()
|
||||
@@ -198,6 +198,10 @@ class PokemonRenderer(
|
||||
//Pre-undo yaw rotation
|
||||
transformationMatrix.rotate(Axis.YP.rotationDegrees(yaw+180f))
|
||||
matrix.mul(transformationMatrix)
|
||||
} else {
|
||||
//Align rotation for non rollable pokemon
|
||||
entity.yBodyRot = driver.yRot
|
||||
entity.yBodyRotO = driver.yRotO
|
||||
}
|
||||
|
||||
super.render(entity, 0f, partialTicks, poseMatrix, buffer, packedLight)
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.cobblemon.mod.common.util.traceFirstEntityCollision
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType
|
||||
import com.mojang.brigadier.arguments.StringArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
|
||||
object ChangeJointScaleCommand {
|
||||
fun register(dispatcher : CommandDispatcher<CommandSourceStack>) {
|
||||
val command = Commands.literal("changejointscale")
|
||||
.permission(CobblemonPermissions.CHANGE_JOINT_SCALE)
|
||||
.then(
|
||||
Commands.argument("joint", StringArgumentType.string())
|
||||
.then(
|
||||
Commands.argument("x", FloatArgumentType.floatArg())
|
||||
.then(Commands.argument("y", FloatArgumentType.floatArg())
|
||||
.then(
|
||||
Commands.argument("z", FloatArgumentType.floatArg())
|
||||
.executes(::execute)
|
||||
)
|
||||
)
|
||||
)
|
||||
.executes(::execute))
|
||||
dispatcher.register(command)
|
||||
}
|
||||
|
||||
private fun execute(context: CommandContext<CommandSourceStack>) : Int {
|
||||
val jointName = StringArgumentType.getString(context, "joint")
|
||||
val x = FloatArgumentType.getFloat(context, "x")
|
||||
val y = FloatArgumentType.getFloat(context, "y")
|
||||
val z = FloatArgumentType.getFloat(context, "z")
|
||||
|
||||
val player = context.source.playerOrException
|
||||
val targetEntity = player.traceFirstEntityCollision(entityClass = PokemonEntity::class.java)
|
||||
if (targetEntity == null) {
|
||||
player.sendSystemMessage("No pokemon".red())
|
||||
return 0
|
||||
}
|
||||
|
||||
val state = FloatingState()
|
||||
state.currentAspects = targetEntity.aspects
|
||||
val model = VaryingModelRepository.getPoser(name = targetEntity.exposedSpecies.resourceIdentifier, state = state)
|
||||
|
||||
val part = model.relevantPartsByName[jointName]
|
||||
?: run {
|
||||
player.sendSystemMessage("No joint named $jointName".red())
|
||||
return 0
|
||||
}
|
||||
val existing = model.transformedParts.find { it.modelPart == part }
|
||||
if (existing == null) {
|
||||
model.transformedParts = model.transformedParts + part.createTransformation().withScale(x, y, z)
|
||||
} else {
|
||||
existing.withScale(x, y, z)
|
||||
}
|
||||
|
||||
player.sendSystemMessage("Changed scale of $jointName to $x, $y, $z".text())
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
|
||||
import com.cobblemon.mod.common.command.argument.ModelPartArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.TransformTypeArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.TransformTypeArgumentType.Companion.TransformType
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
|
||||
object TransformModelPartCommand {
|
||||
|
||||
fun register(dispatcher : CommandDispatcher<CommandSourceStack>) {
|
||||
val command = Commands.literal("transformmodelpart")
|
||||
.permission(CobblemonPermissions.TRANSFORM_MODEL_PART)
|
||||
.then(Commands.argument("transform", TransformTypeArgumentType.transformType())
|
||||
.then(Commands.argument("part", ModelPartArgumentType.modelPart())
|
||||
.then(Commands.argument("x", FloatArgumentType.floatArg())
|
||||
.then(Commands.argument("y", FloatArgumentType.floatArg())
|
||||
.then(Commands.argument("z", FloatArgumentType.floatArg())
|
||||
.executes(::execute)
|
||||
)
|
||||
)
|
||||
)
|
||||
.executes(::execute))
|
||||
.executes(::execute))
|
||||
dispatcher.register(command)
|
||||
}
|
||||
|
||||
private fun execute(context: CommandContext<CommandSourceStack>) : Int {
|
||||
val transformType = TransformTypeArgumentType.getTransform(context, "transform")
|
||||
val targetModelPart = ModelPartArgumentType.getModelPart(context, "part")?: return 0
|
||||
val x = FloatArgumentType.getFloat(context, "x")
|
||||
val y = FloatArgumentType.getFloat(context, "y")
|
||||
val z = FloatArgumentType.getFloat(context, "z")
|
||||
|
||||
val model = ModelPartArgumentType.getModel(context)?: return 0
|
||||
|
||||
val existing = model.transformedParts.find { it.modelPart == targetModelPart }
|
||||
when (transformType) {
|
||||
TransformType.POSITION -> {
|
||||
if (existing != null) existing.withPosition(x, y, z)
|
||||
else model.transformedParts += targetModelPart.createTransformation().withPosition(x, y, z)
|
||||
}
|
||||
TransformType.ROTATION -> {
|
||||
if (existing != null) existing.withRotation(x, y, z)
|
||||
else model.transformedParts += targetModelPart.createTransformation().withRotation(x, y, z)
|
||||
}
|
||||
TransformType.SCALE -> {
|
||||
if (existing != null) existing.withScale(x, y, z)
|
||||
else model.transformedParts += targetModelPart.createTransformation().withScale(x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
context.source.playerOrException.sendSystemMessage("Changed ${transformType.name.lowercase()} of ${context.getArgument("part", String::class.java )} to $x, $y, $z".text())
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.command.argument
|
||||
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.mojang.brigadier.StringReader
|
||||
import com.mojang.brigadier.arguments.ArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.suggestion.Suggestions
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.SharedSuggestionProvider
|
||||
import net.minecraft.world.phys.EntityHitResult
|
||||
import net.minecraft.world.phys.HitResult.Type
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class ModelPartArgumentType(): ArgumentType<String> {
|
||||
override fun parse(reader: StringReader): String {
|
||||
return reader.readString()
|
||||
}
|
||||
|
||||
override fun <S : Any> listSuggestions(
|
||||
context: CommandContext<S>,
|
||||
builder: SuggestionsBuilder
|
||||
): CompletableFuture<Suggestions> {
|
||||
return SharedSuggestionProvider.suggest(getModelParts(context).keys.toList(),builder)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun modelPart() = ModelPartArgumentType()
|
||||
|
||||
fun <S: Any> getModel(context: CommandContext<S> ): PosableModel? {
|
||||
if (context.source is SharedSuggestionProvider) {
|
||||
val targetEntity = (Minecraft.getInstance().hitResult as? EntityHitResult)
|
||||
?.takeIf { it.type == Type.ENTITY }
|
||||
?.entity
|
||||
//Could probably work for NPCs too with some changes
|
||||
if (targetEntity is PokemonEntity) {
|
||||
val state = FloatingState()
|
||||
state.currentAspects = targetEntity.aspects
|
||||
return VaryingModelRepository.getPoser(name = targetEntity.exposedSpecies.resourceIdentifier, state = state)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun <S: Any> getModelParts(context: CommandContext<S>): MutableMap<String, ModelPart> {
|
||||
val modelParts = getModel(context)?.relevantPartsByName?:mutableMapOf()
|
||||
return modelParts
|
||||
}
|
||||
|
||||
fun getModelPart(context: CommandContext<CommandSourceStack>, name: String): ModelPart? {
|
||||
val partName = context.getArgument(name, String::class.java )
|
||||
val part = getModelParts(context)[partName]
|
||||
?: run {
|
||||
context.source.playerOrException.sendSystemMessage("No joint named $partName".red())
|
||||
return null
|
||||
}
|
||||
return part
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.command.argument
|
||||
|
||||
import com.mojang.brigadier.StringReader
|
||||
import com.mojang.brigadier.arguments.ArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException
|
||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.SharedSuggestionProvider
|
||||
|
||||
class TransformTypeArgumentType: ArgumentType<TransformTypeArgumentType.Companion.TransformType>
|
||||
{
|
||||
override fun parse(reader: StringReader): TransformType {
|
||||
try {
|
||||
reader.readString()?.let { return TransformType.valueOf(it.uppercase()) }
|
||||
}
|
||||
catch (_: Exception) { }
|
||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherParseException().create(reader)
|
||||
}
|
||||
|
||||
override fun getExamples() = EXAMPLES
|
||||
|
||||
override fun <S : Any> listSuggestions(context: CommandContext<S>, builder: SuggestionsBuilder) = SharedSuggestionProvider.suggest(EXAMPLES, builder)
|
||||
|
||||
companion object {
|
||||
enum class TransformType {
|
||||
POSITION,
|
||||
ROTATION,
|
||||
SCALE
|
||||
}
|
||||
|
||||
fun transformType() = TransformTypeArgumentType()
|
||||
|
||||
fun getTransform(context: CommandContext<CommandSourceStack>, name: String): TransformType {
|
||||
return context.getArgument(name, TransformType::class.java )
|
||||
}
|
||||
|
||||
private val EXAMPLES = TransformType.entries.map { it.name.lowercase() }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
+8
-1
@@ -43,7 +43,14 @@ object ModelPartTransformationAdapter : JsonDeserializer<ModelPartTransformation
|
||||
it[2].asDouble
|
||||
)
|
||||
} ?: Vec3.ZERO
|
||||
val scale = json.get("scale")?.asJsonArray?.let {
|
||||
Vec3(
|
||||
it[0].asDouble,
|
||||
it[1].asDouble,
|
||||
it[2].asDouble
|
||||
)
|
||||
} ?: Vec3(1.0,1.0,1.0)
|
||||
val isVisible = json.get("isVisible")?.asString?.asExpressionLike()
|
||||
return part.withPosition(position.x, position.y, position.z).withRotationDegrees(rotation.x, rotation.y, rotation.z).also { if (isVisible != null) it.withVisibility(isVisible) }
|
||||
return part.withPosition(position.x, position.y, position.z).withRotationDegrees(rotation.x, rotation.y, rotation.z).withScale(scale.x, scale.y, scale.z).also { if (isVisible != null) it.withVisibility(isVisible) }
|
||||
}
|
||||
}
|
||||
+32
-59
@@ -15,6 +15,14 @@
|
||||
"name": "lapras",
|
||||
"pivot": [0, 0, 0]
|
||||
},
|
||||
{
|
||||
"name": "locator_root",
|
||||
"parent": "lapras",
|
||||
"pivot": [0, 0, 0],
|
||||
"locators": {
|
||||
"root": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"parent": "lapras",
|
||||
@@ -29,11 +37,11 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_middle",
|
||||
"name": "locator_body",
|
||||
"parent": "body",
|
||||
"pivot": [0, 0, 0],
|
||||
"locators": {
|
||||
"middle": [0, 14, 0]
|
||||
"body": [0, 14, 0]
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -60,14 +68,6 @@
|
||||
{"origin": [-15.25, 13.5, -7], "size": [3, 3, 3], "pivot": [-12.5, 13.5, -4.5], "rotation": [0, -15, 5], "uv": [12, 120], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "shell",
|
||||
"pivot": [0, 24, 0],
|
||||
"locators": {
|
||||
"seat_1": [0, 24, 0]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "shell2",
|
||||
"parent": "shell",
|
||||
@@ -138,31 +138,6 @@
|
||||
{"origin": [-5.5, 30, -14.5], "size": [11, 10, 8], "inflate": 0.01, "uv": [0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_item_face",
|
||||
"parent": "head_angle",
|
||||
"pivot": [0, 37.25, -21],
|
||||
"rotation": [-22.5, 0, 0],
|
||||
"locators": {
|
||||
"item_face": [0, 37.25, -21]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_face",
|
||||
"parent": "head_angle",
|
||||
"pivot": [0, 36, -24.1],
|
||||
"locators": {
|
||||
"face": [0, 36, -24.1]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_item_hat",
|
||||
"parent": "head_angle",
|
||||
"pivot": [0, 40, -12],
|
||||
"locators": {
|
||||
"item_hat": [0, 40, -12]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_head",
|
||||
"parent": "head_angle",
|
||||
@@ -185,6 +160,14 @@
|
||||
"parent": "head_angle",
|
||||
"pivot": [0, 30.75, -11.15]
|
||||
},
|
||||
{
|
||||
"name": "locator_face",
|
||||
"parent": "eyes",
|
||||
"pivot": [0, 36, -24.1],
|
||||
"locators": {
|
||||
"face": [0, 36, -24.1]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "eye_right",
|
||||
"parent": "eyes",
|
||||
@@ -323,14 +306,6 @@
|
||||
"jaw_lower": [0, 32.15, -21.5]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_item",
|
||||
"parent": "jaw",
|
||||
"pivot": [0, 32, -22.5],
|
||||
"locators": {
|
||||
"item": [0, 32, -22.5]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tongue",
|
||||
"parent": "jaw",
|
||||
@@ -370,15 +345,6 @@
|
||||
{"origin": [-6.5, 1.5, 11], "size": [13, 10, 7], "uv": [78, 40]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_tail",
|
||||
"parent": "tail",
|
||||
"pivot": [0, 5, 17],
|
||||
"rotation": [0, 180, 0],
|
||||
"locators": {
|
||||
"tail": [0, 5, 17]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "tail2",
|
||||
"parent": "tail",
|
||||
@@ -533,19 +499,26 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_root",
|
||||
"parent": "lapras",
|
||||
"name": "bone2",
|
||||
"pivot": [0, 0, 0]
|
||||
},
|
||||
{
|
||||
"name": "bone4",
|
||||
"parent": "bone2",
|
||||
"pivot": [0, 0, 0]
|
||||
},
|
||||
{
|
||||
"name": "bone",
|
||||
"pivot": [0, 0, 0],
|
||||
"locators": {
|
||||
"root": [0, 0, 0]
|
||||
"locator5": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_top",
|
||||
"parent": "lapras",
|
||||
"pivot": [0, 45.2, -6],
|
||||
"name": "bone5",
|
||||
"pivot": [0, 0, 0],
|
||||
"locators": {
|
||||
"top": [0, 45.2, -6]
|
||||
"locator6": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -51,16 +51,24 @@
|
||||
"fixed": false
|
||||
},
|
||||
"riding": {
|
||||
"behaviour": {
|
||||
"key": "cobblemon:swim/generic"
|
||||
},
|
||||
"behaviour": null,
|
||||
"seats": [
|
||||
{
|
||||
"offset": {
|
||||
"x": 0.0,
|
||||
"y": 0.4,
|
||||
"z": 0.0
|
||||
}
|
||||
},
|
||||
"poseAnimations": [
|
||||
{
|
||||
"animations": [
|
||||
{
|
||||
"fileName": "trainer_generic",
|
||||
"animationName": "animation.trainer_generic.idle"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"offset": {
|
||||
|
||||
Reference in New Issue
Block a user