Compare commits

..
Author SHA1 Message Date
jackowes ea99b339ea smoothening camera 2025-11-08 22:49:47 -06:00
1026 changed files with 33258 additions and 173481 deletions
-42
View File
@@ -49,7 +49,6 @@
- Berries can now be smelted into their respective dyes.
- Added Syrupy Apples.
- Added `/runmolang <molang> [<npc>|<player>|<pokemon>]` command that executes a MoLang expression with the provided options as environment variables, as well as the entity (as `q.entity`) that executed the command.
- Added new 69th berry, Eggant.
- Added bubble quirk to Kingler; like Krabby, Kingler will blows bubbles during dusk.
- Added `.Pre` and `.Post` to the following events:
- `PokemonRecallEvent`
@@ -57,7 +56,6 @@
- Added a new gamerule, 'healerHealsPC', when set to true a successful use of a healer will also heal all of the Pokemon in that player's PC.
- Mooshtanks will switch between their red and brown variant when hit by lightning
- Smeargle spawns with differing tail colour depending on its [Characteristic](https://bulbapedia.bulbagarden.net/wiki/Characteristic) stat
- Added smooth level-up animations to the party overlay to replace chat messages.
### Pokémon Added
@@ -89,8 +87,6 @@
- Altaria
- Snorunt
- Glalie
- Shuppet
- Banette
- Latias
- Latios
@@ -139,11 +135,6 @@
- Swadloon
- Leavanny
- Druddigon
- Minccino
- Cinccino
- Vanillite
- Vanillish
- Vanilluxe
#### Gen 6
- Skiddo
@@ -306,23 +297,6 @@
- Tauros - Paldea Combat
- Dewgong
- Exeggutor - Kanto
- Corphish (updated placeholders for crustaceous tripod gait legs)
- Crawdaunt (updated placeholders for crustaceous bipedal legs)
- Dragapult
- Camerupt
- Relicanth
- Heracross
- Salamence
- Staraptor
- Dusknoir
- Arcanine
- Carvanha
- Sharpedo
- Mimikyu
- Dewgong
- Mime Jr
- Gyarados
- Lapras
### Model updates for the following Pokémon
- Cleffa
@@ -350,8 +324,6 @@
- Nosepass
- Probopass
- Kangaskhan
- Scorbunny
- Raboot
- Cinderace
- Magnemite
- Magneton
@@ -438,18 +410,6 @@
- Litwick
- Lampent
- Chandelure
- Rayquaza
- Aerodactyl
- Basculin
- Basculegion
- Shroodle
- Grafaiai
- Steelix
- Dratini
- Dragonair
- Dragonite
- Cutiefly
- Ribombee
### Changes
- Changed pokemon caught and seen count to update based on the current pokedex being looked
@@ -603,9 +563,7 @@
- Fixed species additions not being able to properly mark a species as implemented.
- Fixed Pokémon item models not showing a glint when enchanted.
- Fixed some specific bag items not being dropped when used in battle.
- The Corphish line will now sink in water.
- Fixed the "use all berry bait" achievement not being progressed
- Fixed bobber hook and berry sprouts texture sizes causing mipmap issues.
### Developer
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.AbstractArrow;
@@ -25,9 +24,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(AbstractArrow.class)
public abstract class AbstractArrowMixin {
// Target the constructor that takes a LivingEntity owner
@Inject(
method = "<init>(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V",
at = @At("TAIL")
at = @At("TAIL") // Inject at the very end of the constructor
)
private void cobblemon$adjustSpawnPosition(
EntityType<? extends AbstractArrow> entityType,
@@ -39,12 +39,11 @@ public abstract class AbstractArrowMixin {
) {
AbstractArrow arrow = (AbstractArrow)(Object)this;
if(!(owner.getVehicle() instanceof OrientationControllable vehicle)) return;
if(!(vehicle instanceof PokemonEntity)) return;
var vehicleController = vehicle.getOrientationController();
// If this is a pokemon ride passenger then use the rider eye position to set the arrow spawn position.
if (owner instanceof RidePassenger ridePassenger && vehicleController != null ) {
var eyePos = ridePassenger.cobblemon$getRideEyePos(); //.add(0.0, -2.0, 0.0);
// If this is a rolling ride passenger then use the rider eye position to set the arrow spawn position.
if (owner instanceof RidePassenger ridePassenger && vehicleController != null && vehicleController.getActive()) {
var eyePos = ridePassenger.cobblemon$getRideEyePos().add(0.0, -2.0, 0.0);
arrow.setPos(eyePos);
}
}
@@ -28,10 +28,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@Mixin(BeehiveBlockEntity.Occupant.class)
public abstract class BeeOccupantMixin {
@@ -92,11 +88,8 @@ public abstract class BeeOccupantMixin {
@Inject(method = "of", at = @At("HEAD"), cancellable = true)
private static void cobblemon$of(Entity entity, CallbackInfoReturnable<BeehiveBlockEntity.Occupant> cir) {
if (entity instanceof PokemonEntity pokemonEntity) {
List<String> IGNORED_BEE_TAGS = Arrays.asList("Air", "ArmorDropChances", "ArmorItems", "Brain", "CanPickUpLoot", "DeathTime", "FallDistance", "FallFlying", "Fire", "HandDropChances", "HandItems", "HurtByTimestamp", "HurtTime", "LeftHanded", "Motion", "NoGravity", "OnGround", "PortalCooldown", "Pos", "Rotation", "Passengers", "leash", "UUID");
CompoundTag compoundTag = new CompoundTag();
entity.save(compoundTag);
Objects.requireNonNull(compoundTag);
IGNORED_BEE_TAGS.forEach(compoundTag::remove);
Boolean hasNectar = pokemonEntity.getBrain().getMemory(CobblemonMemories.INSTANCE.getHAS_NECTAR()).orElse(false);
cir.setReturnValue(new BeehiveBlockEntity.Occupant(CustomData.of(compoundTag), 0, hasNectar ? 2400 : 600));
cir.cancel();
@@ -19,8 +19,6 @@ import com.cobblemon.mod.common.client.entity.PokemonClientDelegate;
import com.cobblemon.mod.common.client.render.MatrixWrapper;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.net.messages.server.orientation.ServerboundUpdateOrientationPacket;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
@@ -63,14 +61,6 @@ public abstract class LivingEntityMixin extends Entity implements OrientationCon
}
}
@WrapOperation(method = "baseTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isInWall()Z"))
public boolean cobblemon$preventMountSuffocation(LivingEntity instance, Operation<Boolean> original) {
if (instance.getVehicle() instanceof PokemonEntity) {
return false;
}
return original.call(instance);
}
@Override
public @NotNull HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
Entity vehicle = this.getVehicle();
@@ -115,7 +105,7 @@ public abstract class LivingEntityMixin extends Entity implements OrientationCon
@Inject(method = "tick", at = @At("HEAD"))
private void cobblemon$updateRenderOrientation(CallbackInfo ci) {
this.cobblemon$orientationController.tick();
//this.cobblemon$orientationController.tick();
}
@Override
@@ -25,7 +25,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix3f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@@ -62,10 +61,6 @@ public abstract class CameraMixin {
@Unique private double cobblemon$lastHandledRotationTime = Double.MIN_VALUE;
@Unique private double cobblemon$frameTime = 0.0;
// Used to as the render rotation for the motion sick camera.
@Unique @Nullable private Quaternionf cobblemon$smoothRotation = null;
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
public void cobblemon$setRotation(float f, float g, CallbackInfo ci) {
// Calculate the current frametime
@@ -73,9 +68,6 @@ public abstract class CameraMixin {
this.cobblemon$frameTime = (this.cobblemon$lastHandledRotationTime != Double.MIN_VALUE) ? d - this.cobblemon$lastHandledRotationTime : 0.0;
this.cobblemon$lastHandledRotationTime = d;
// Do no camera rotations if the game is paused
if(Minecraft.getInstance().isPaused()) return;
// Don't assume the camera to be attached to an entity. Ponder Scenes from create et.al. for example aren't.
if (this.entity == null) return;
var vehicle = this.entity.getVehicle();
@@ -124,8 +116,6 @@ public abstract class CameraMixin {
}
}
// reset the rotation values if it is now not being ridden.
cobblemon$smoothRotation = null;
original.call(instance, x, y, z);
}
@@ -153,26 +143,17 @@ public abstract class CameraMixin {
newRotation = vehicleController.getRenderOrientation(this.partialTickTime);
}
// Unroll the current rotation if no roll is requested and not currently freelooking.
// Unroll the current rotation if no roll is requested
if (Cobblemon.config.getDisableRoll()) {
// Init the smooth rotation if it has not been set yet.
if (cobblemon$smoothRotation == null) {
cobblemon$smoothRotation = new Quaternionf().set(this.rotation);
}
var rideAngs = newRotation.getEulerAnglesYXZ(new Vector3f());
var cameraAngs = cobblemon$smoothRotation.getEulerAnglesYXZ(new Vector3f());
var eulerAngs = newRotation.getEulerAnglesYXZ(new Vector3f());
var currAngs = this.rotation.getEulerAnglesYXZ(new Vector3f());
var vehicle = (PokemonEntity)driver.getVehicle();
var vel = vehicle.getRidingAnimationData().getVelocitySpring().getInterpolated(this.partialTickTime, 0);
// var vehicle = (PokemonEntity)driver.getVehicle();
// var vel = vehicle.getRidingAnimationData().getVelocitySpring().getInterpolated(this.partialTickTime, 0);
// // Grab the target yaw as the current rides yaw. If the horizontal velocity is high enough to be used to
// // derive a yaw then use it.
// var targetYaw = (double) rideAngs.y();
// if ( vel.horizontalDistance() > 0.01) {
// // lerp the new rotation towards this y rot at a rate proportional to the horizontal movement speed?
// targetYaw = Mth.wrapDegrees(Math.toDegrees(Mth.atan2(vel.x(), vel.z())) + 180.0f);
// }
// lerp the new rotation towards this y rot at a rate proportional to the horizontal movement speed?
var yaw = Mth.wrapDegrees(Math.toDegrees(Mth.atan2(vel.x(), vel.z())) + 180.0f);
var degDiff = Mth.degreesDifference((float)Math.toDegrees(cameraAngs.y()), (float)Math.toDegrees(rideAngs.y));
var degDiff = Mth.degreesDifference((float)Math.toDegrees(currAngs.y()), (float)yaw);
var pitchDeadzoneDeg = 15.0; // x degrees of deadzone about +-90 degrees of pitch.
var pitchDeg = vehicleController.getPitch();
// ConsiderPitch to be already 90 if within the deadzone around it.
@@ -180,20 +161,11 @@ public abstract class CameraMixin {
var lerpRateMod = Mth.cos((float)Math.toRadians(cutoffPitch));
// Apply smoothing from the cameras current yaw to the yaw of the velocity vector of the ride.
var k = 10.0f; // Some smoothing constant k
var k = 5.0f; // Some smoothing constant k
var smoothingFactor = lerpRateMod * cobblemon$frameTime * k;
var newYaw = cameraAngs.y() + (Math.toRadians(degDiff) * smoothingFactor);
var newPitch = (float)Mth.lerp(cobblemon$frameTime * k, cameraAngs.x(), rideAngs.x());
//var newYaw = (float)Mth.lerp(smoothingFactor, cameraAngs.y(), rideAngs.y());
var maxRoll = Math.toRadians(15.0f);
var newRoll = (float)Mth.lerp(cobblemon$frameTime * k / 2.0, cameraAngs.z(), Math.abs(lerpRateMod) * Math.sin(rideAngs.z()) * maxRoll);
// Set rotations
var smoothedRot = new Quaternionf().rotateYXZ((float)newYaw, newPitch, newRoll);
cobblemon$smoothRotation.set(smoothedRot);
newRotation.set(smoothedRot);
var newYaw = currAngs.y() + (Math.toRadians(degDiff) * smoothingFactor);
newRotation.set(new Quaternionf().rotateYXZ((float)newYaw, eulerAngs.x(), 0.0f));
}
var rotationOffset = 0;
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
import com.cobblemon.mod.common.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.geom.ModelPart;
@@ -69,13 +68,6 @@ public class HumanoidModelMixin {
behaviour.shouldRotateRiderHead(settings, state, pokemonEntity)
);
if (entity instanceof RidePassenger playerRotater) {
//this.head.yRot = playerRotater.cobblemon$getRideYRot();
this.head.xRot = playerRotater.cobblemon$getRideXRot();
headPitch = playerRotater.cobblemon$getRideXRot();
}
if (!shouldRotatePlayerHead) {
netHeadYaw = 0f;
headPitch = 0f;
@@ -129,6 +129,10 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
if (Minecraft.getInstance().player != (Object)this) return;
if (!(this.getVehicle() instanceof PokemonEntity pokemonEntity)) return;
// Only send rotation updates if the player is riding a vehicle that is currently rollable
if (!(this.getVehicle() instanceof OrientationControllable controllableVehicle)) return;
if (!controllableVehicle.getOrientationController().getActive()) return;
var passenger = (LocalPlayer)(Object)this;
var playerRotater = (RidePassenger)passenger;
@@ -200,7 +204,7 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
this.cobblemon$survivalJumpTriggerTime = 0;
}
else {
this.cobblemon$survivalJumpTriggerTime = 12;
this.cobblemon$survivalJumpTriggerTime = 7;
}
}
else if (this.cobblemon$survivalJumpTriggerTime > 0) {
@@ -227,17 +231,33 @@ public abstract class LocalPlayerMixin extends AbstractClientPlayer implements O
public HitResult pick(double hitDistance, float partialTicks, boolean hitFluids) {
Entity vehicle = this.getVehicle();
if (vehicle instanceof PokemonEntity pokemonEntity) {
PokemonClientDelegate delegate = (PokemonClientDelegate) pokemonEntity.getDelegate();
String locatorName = delegate.getSeatLocator(this);
MatrixWrapper locator = delegate.getLocatorStates().get(locatorName);
// Get player object
var passenger = (LocalPlayer)(Object)this;
var playerRotater = (RidePassenger)passenger;
if (locator == null) {
return super.pick(hitDistance, partialTicks, hitFluids);
}
// Gather eye position from stored 1st person camera position calculation
var eyePosition = playerRotater.cobblemon$getRideEyePos();
Vec3 locatorOffset = locator != null ? new Vec3(locator.getMatrix().getTranslation(new Vector3f())) : Vec3.ZERO;
OrientationController controller = this.getOrientationController();
float currEyeHeight = this.getEyeHeight();
Vector3f offset = new Vector3f(new Vector3f(0f, currEyeHeight - (this.getBbHeight() / 2), 0f));
if (Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON) {
PosableModel model = VaryingModelRepository.INSTANCE.getPoser(pokemonEntity.getPokemon().getSpecies().getResourceIdentifier(), new FloatingState());
offset.add(cobblemon$getFirstPersonOffset(model, locatorName));
}
Matrix3f orientation = controller.isActive() && controller.getOrientation() != null ? controller.getOrientation() : new Matrix3f();
Vec3 rotatedEyeHeight = new Vec3(orientation.transform(offset));
Vec3 eyePosition = locatorOffset.add(pokemonEntity.position()).add(rotatedEyeHeight);
Vec3 viewVector = this.getViewVector(partialTicks);
Vec3 viewDistanceVector = eyePosition.add(viewVector.x * hitDistance, viewVector.y * hitDistance, viewVector.z * hitDistance);
return this.level()
.clip(
new ClipContext(
@@ -1,45 +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.mixin.client;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.OrientationControllable;
import net.minecraft.client.CameraType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Options;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(Options.class)
public abstract class OptionsMixin {
/**
* Only allow third person on rollables when motion sick cam is enabled
*/
@Inject(
method = "getCameraType",
at = @At("HEAD"),
cancellable = true
)
private void cobblemon$forceThirdPerson(CallbackInfoReturnable<CameraType> cir) {
var mc = Minecraft.getInstance();
if(!(mc.player instanceof Player player)) return;
if(!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
if(vehicle.getOrientationController() == null) return;
// Force third person if on an active rollable vehicle and roll is disabled.
if (Cobblemon.config.getDisableRoll() && vehicle.getOrientationController().isActive()) {
cir.setReturnValue(CameraType.THIRD_PERSON_BACK);
cir.cancel();
}
}
}
@@ -74,11 +74,12 @@ public abstract class EntityMixin {
var vehicleController = vehicle.getOrientationController();
if (vehicleController == null) return;
// TODO: Determine if it needs partialtick involved.
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
cir.setReturnValue(customEyePos);
// If Orientation is currently being controlled then use the stored eye position from camera positioning.
if (vehicleController.getActive() && vehicleController.getOrientation() != null) {
// TODO: Determine if it needs partialtick involved.
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
cir.setReturnValue(customEyePos);
}
}
@Inject(
@@ -94,9 +95,12 @@ public abstract class EntityMixin {
var vehicleController = vehicle.getOrientationController();
if (vehicleController == null) return;
// TODO: Determine if it needs partialtick involved.
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
cir.setReturnValue(customEyePos);
// If Orientation is currently being controlled then use the stored eye position from camera positioning.
if (vehicleController.getActive() && vehicleController.getOrientation() != null) {
// TODO: Determine if it needs partialtick involved.
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
cir.setReturnValue(customEyePos);
}
}
}
@@ -593,7 +593,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val CORNN_BERRY = this.berryBlock("cornn")
val CUSTAP_BERRY = this.berryBlock("custap")
val DURIN_BERRY = this.berryBlock("durin")
val EGGANT_BERRY = this.berryBlock("eggant")
val ENIGMA_BERRY = this.berryBlock("enigma")
val FIGY_BERRY = this.berryBlock("figy")
val GANLON_BERRY = this.berryBlock("ganlon")
@@ -51,11 +51,6 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
.networkSynchronized(FlavourComponent.PACKET_CODEC)
.build())
val RIDE_BOOST: DataComponentType<RideBoostsComponent> = create("ride_boosts", DataComponentType.builder<RideBoostsComponent>()
.persistent(RideBoostsComponent.CODEC)
.networkSynchronized(RideBoostsComponent.PACKET_CODEC)
.build())
val FOOD_COLOUR: DataComponentType<FoodColourComponent> = create("food_colour", DataComponentType.builder<FoodColourComponent>()
.persistent(FoodColourComponent.CODEC)
.networkSynchronized(FoodColourComponent.PACKET_CODEC)
@@ -87,7 +82,6 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:cooking_pot_item"), POT_DATA)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait_effects"), BAIT_EFFECTS)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:flavour"), FLAVOUR)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ride_boosts"), RIDE_BOOST)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food_colour"), FOOD_COLOUR)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:ingredient"), INGREDIENT)
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:food"), FOOD)
@@ -36,7 +36,7 @@ import com.cobblemon.mod.common.item.berry.PPRestoringBerryItem
import com.cobblemon.mod.common.item.berry.PortionHealingBerryItem
import com.cobblemon.mod.common.item.berry.StatusCuringBerryItem
import com.cobblemon.mod.common.item.berry.VolatileCuringBerryItem
import com.cobblemon.mod.common.item.interactive.PonigiriItem
import com.cobblemon.mod.common.item.food.PonigiriItem
import com.cobblemon.mod.common.item.food.SinisterTeaItem
import com.cobblemon.mod.common.item.interactive.*
import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
@@ -517,7 +517,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField val RAWST_BERRY = berryItem("rawst", StatusCuringBerryItem(CobblemonBlocks.RAWST_BERRY, Statuses.BURN))
@JvmField val ASPEAR_BERRY = berryItem("aspear", StatusCuringBerryItem(CobblemonBlocks.ASPEAR_BERRY, Statuses.FROZEN))
@JvmField val PERSIM_BERRY = berryItem("persim", VolatileCuringBerryItem(CobblemonBlocks.PERSIM_BERRY, "confusion"))
@JvmField val EGGANT_BERRY = berryItem("eggant", VolatileCuringBerryItem(CobblemonBlocks.EGGANT_BERRY, "attract"))
@JvmField val RAZZ_BERRY = berryItem("razz", CobblemonBlocks.RAZZ_BERRY)
@JvmField val BLUK_BERRY = berryItem("bluk", CobblemonBlocks.BLUK_BERRY)
@JvmField val NANAB_BERRY = berryItem("nanab", CobblemonBlocks.NANAB_BERRY)
@@ -12,7 +12,6 @@ import com.bedrockk.molang.Expression
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.mechanics.AprijuicesMechanic
import com.cobblemon.mod.common.mechanics.BerriesMechanic
import com.cobblemon.mod.common.mechanics.PotionsMechanic
import com.cobblemon.mod.common.mechanics.RemediesMechanic
@@ -38,7 +37,6 @@ object CobblemonMechanics : DataRegistry {
var remedies = RemediesMechanic()
var berries = BerriesMechanic()
var potions = PotionsMechanic()
var aprijuices = AprijuicesMechanic()
override fun sync(player: ServerPlayer) {}
@@ -46,7 +44,6 @@ object CobblemonMechanics : DataRegistry {
remedies = loadMechanic(manager, "remedies", RemediesMechanic::class.java)
berries = loadMechanic(manager, "berries", BerriesMechanic::class.java)
potions = loadMechanic(manager, "potions", PotionsMechanic::class.java)
aprijuices = loadMechanic(manager, "aprijuices", AprijuicesMechanic::class.java)
}
private fun <T> loadMechanic(manager: ResourceManager, name: String, clazz: Class<T>): T {
@@ -28,7 +28,6 @@ import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
import com.cobblemon.mod.common.client.net.effect.SaccharineLogBlockParticlesHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.gui.ExpGainedDataPacketHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
@@ -133,7 +132,6 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotification
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
@@ -349,7 +347,6 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
list.add(PacketRegisterInfo(PokedexUIPacket.ID, PokedexUIPacket::decode, PokedexUIPacketHandler))
list.add(PacketRegisterInfo(ExpGainedDataPacket.ID, ExpGainedDataPacket::decode, ExpGainedDataPacketHandler))
// Starter packets
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
@@ -103,11 +103,6 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
@JvmField
val EVOLUTION = this.create("evolution.full")
@JvmField
val LEVELUP_START = this.create("gui.levelup_start")
@JvmField
val LEVELUP = this.create("gui.levelup")
@JvmField
val PVN_BATTLE = this.create("battle.pvn.default")
@JvmField
@@ -47,23 +47,12 @@ class ApplyBehaviours : BehaviourConfig {
override fun configure(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) {
if (!checkCondition(behaviourConfigurationContext, condition)) return
val applicableBehaviours = behaviours.mapNotNull {
val resolvedBehaviour = CobblemonBehaviours.behaviours[it]
if (resolvedBehaviour == null) {
Cobblemon.LOGGER.warn("Behaviour $it not found while configuring entity of type ${entity.type}")
} else if (!resolvedBehaviour.canBeApplied(entity)) {
Cobblemon.LOGGER.warn("Behaviour $it cannot be applied to entity ${entity.id}")
} else {
return@mapNotNull resolvedBehaviour
}
null
}
val configurations = behaviours.map { CobblemonBehaviours.behaviours[it]?.takeIf { it.canBeApplied(entity) } ?: return Cobblemon.LOGGER.warn("Behaviour $it not found") }
// Why not just add the presets to the context directly?
// Nested preset application is a thing, and I only want to track the top level presets.
// i.e. if a preset applies another preset, I don't want to track the inner preset, since it's redundant if we track the top one.
val originalContextBehaviours = behaviourConfigurationContext.appliedBehaviours.toMutableSet()
applicableBehaviours.forEach {
configurations.forEach {
it.configure(entity, behaviourConfigurationContext)
}
originalContextBehaviours.addAll(behaviours)
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.apricorn
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.block.ApricornBlock
import com.cobblemon.mod.common.block.ApricornSaplingBlock
import com.cobblemon.mod.common.item.ApricornItem
@@ -27,14 +28,43 @@ import net.minecraft.world.level.material.MapColor
* @author Licious
* @since October 29th, 2022
*/
enum class Apricorn : StringRepresentable {
enum class Apricorn(
/** A value of true means it buffs that flavour, a value of false means it weakens that flavour. */
val flavourStrength: Map<Flavour, Boolean> = emptyMap()
) : StringRepresentable {
BLACK,
BLUE,
GREEN,
PINK,
RED,
BLUE(
mapOf(
Flavour.DRY to true,
Flavour.BITTER to false
)
),
GREEN(
mapOf(
Flavour.BITTER to true,
Flavour.SWEET to false
)
),
PINK(
mapOf(
Flavour.SWEET to true,
Flavour.SPICY to false
)
),
RED(
mapOf(
Flavour.SPICY to true,
Flavour.SOUR to false
)
),
WHITE,
YELLOW;
YELLOW(
mapOf(
Flavour.SOUR to true,
Flavour.DRY to false
)
);
fun item(): ApricornItem = when(this) {
BLACK -> CobblemonItems.BLACK_APRICORN
@@ -101,4 +131,5 @@ enum class Apricorn : StringRepresentable {
companion object {
val CODEC: Codec<Apricorn> = StringRepresentable.fromValues(::values)
}
}
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.api.cooking
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import net.minecraft.util.FastColor
import net.minecraft.world.item.ItemStack
@@ -66,10 +65,6 @@ fun getColourMixFromFlavours(dominantFlavours: List<Flavour>, forBubbles: Boolea
)
}
fun getColourMixFromRideStatBoosts(dominantBoosts: Iterable<RidingStat>, forBubbles: Boolean = false): Int? {
return getColourMixFromFlavours(dominantBoosts.map { it.flavour }, forBubbles)
}
fun getColourMixFromColors(colors: List<Int>): Int? {
if (colors.isEmpty()) return null
@@ -10,13 +10,17 @@ package com.cobblemon.mod.common.api.orientation
import com.cobblemon.mod.common.util.math.geometry.toDegrees
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.mojang.blaze3d.Blaze3D
import net.minecraft.util.Mth
import net.minecraft.world.entity.LivingEntity
import org.joml.AxisAngle4f
import org.joml.Matrix3f
import org.joml.Quaternionf
import org.joml.Vector3f
import kotlin.math.abs
import kotlin.math.asin
import kotlin.math.max
import kotlin.math.min
import kotlin.math.sign
open class OrientationController(val entity: LivingEntity) {
@@ -35,6 +39,11 @@ open class OrientationController(val entity: LivingEntity) {
private var renderOrientationO: Matrix3f? = null
private var renderOrientation: Matrix3f? = null
private var angularVelocity: Vector3f = Vector3f(0.0f, 0.0f, 0.0f)
private var lastHandledRotationTime = Double.MIN_VALUE
private var frameTime = 0.0
/** Adding this simply because it irritates me seeing `getActive` when most of this is Java. */
fun isActive() = active
@@ -72,18 +81,93 @@ open class OrientationController(val entity: LivingEntity) {
}
fun tick() {
if (!active || orientation == null) return
renderOrientationO = renderOrientation
val current = orientation
val renderMatrix = this.renderOrientation ?: current
val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
val targetQuat = Quaternionf().setFromUnnormalized(current)
val dampingFactor = 0.66f // We can change this factor for faster transitions
renderQuat.slerp(targetQuat, dampingFactor)
// val d = Blaze3D.getTime();
// this.frameTime =
// if (this.lastHandledRotationTime != Double.MIN_VALUE) d - this.lastHandledRotationTime else 0.0;
// this.lastHandledRotationTime = d;
//
// if (!active || orientation == null) return
//
// // Find the desired angular velocity
// // lerp the current ang vel towards the desired at a set rate (does this need to take into account frametime?
// val current = orientation
// val renderMatrix = this.renderOrientation ?: Matrix3f()
// val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
// val targetQuat = Quaternionf().setFromUnnormalized(current)
//
// // Max rate of angular change in radians per second
// val maxAngVel = Math.toRadians(180.0).toFloat()
//
// // Find the difference between the current render orientation and the target orientation
// val qDiff: Quaternionf = targetQuat.mul(renderQuat.invert())
//
// // Construct the target rate of change from the difference quat
// val axAng = qDiff.get(AxisAngle4f())
// val capdRate = axAng.angle.coerceIn(-maxAngVel, maxAngVel)
// val targetAngVel = Vector3f(
// axAng.x,
// axAng.y,
// axAng.z
// ).mul(capdRate)
//
// // lerp the current angular velocity towards the target
// val k = 10.0f // Some smoothing constant k
// val smoothingFactor = Math.min(1.0f, this.frameTime.toFloat() * k)
// angularVelocity = angularVelocity.lerp(targetAngVel, smoothingFactor)
//
// // Use the angular velocity to slerp the renderQuat toward the targetQuat
// val frameDisplacement =
// angularVelocity.mul(this.frameTime.toFloat()) // Angular displacement happening on this frame
//
// val fAng = frameDisplacement.length() // Angle of displacement for this given pass/frame
// if (fAng > 0.0001f) { // Ensure that the angle is significant enough that its worth normalizing and carrying out rotation
// val fAx = frameDisplacement.normalize()
// // Construct a rotation quat from the
// val rotQuat = Quaternionf().fromAxisAngleRad(fAx, fAng)
//
// // Set the new orientation post frame stepped rotation.
// renderOrientation = Matrix3f().set(renderQuat.mul(rotQuat))
// }
//
//// this.renderOrientation = orientation
//
// // apply the new current angular velocity to the current render orientation
// // construct a quat out of the angular velocity
// // slerp the quat with a value of frametime
val newRenderOrientation = Matrix3f()
renderQuat.get(newRenderOrientation)
renderOrientation = newRenderOrientation
val d = Blaze3D.getTime();
this.frameTime = if (this.lastHandledRotationTime != Double.MIN_VALUE) d - this.lastHandledRotationTime else 0.0;
this.lastHandledRotationTime = d;
if (!active || orientation == null) return
val current = orientation
val renderMatrix = this.renderOrientation ?: Matrix3f()
// Create mutable copies for manipulation
val renderQuat = Quaternionf().setFromUnnormalized(renderMatrix)
var targetQuat = Quaternionf().setFromUnnormalized(current)
// --- Shortest Path Check (Still mandatory for Slerp) ---
if (renderQuat.dot(targetQuat) < 0) {
targetQuat = targetQuat.invert()
}
// --------------------------------------------------------
// K is the speed (rad/s) we want to close the gap at.
val k_rate = 10.0f // E.g., target 10 units/second closing rate.
// Calculate the frame-rate independent alpha (t) for Slerp.
// This makes the smoothing constant 'k_rate' a rate of change, not an arbitrary alpha value.
val slerpAlpha = 1.0f - Math.exp(-(k_rate * this.frameTime)).toFloat()
// Use Slerp to interpolate the renderQuat towards the targetQuat
val newRenderQuat = renderQuat.slerp(targetQuat, slerpAlpha, Quaternionf())
// Set the new orientation
renderOrientation = Matrix3f().set(newRenderQuat)
// Angular velocity is now redundant for rendering, but could be used for particle effects, etc.
}
val forwardVector: Vector3f
@@ -39,6 +39,7 @@ import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
import com.cobblemon.mod.common.api.spawning.TimeRange
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
@@ -128,6 +129,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.registerTypeAdapter(RidingBehaviourSettings::class.java, RidingBehaviourSettingsAdapter)
.registerTypeAdapter(RidingStatDefinition::class.java, RidingStatDefinitionAdapter)
.registerTypeAdapter(RideSoundSettingsList::class.java, RideSoundSettingsListAdapter)
.registerTypeAdapter(ObtainableItemCondition::class.java, ObtainableItemConditionAdapter)
.disableHtmlEscaping()
@@ -19,9 +19,7 @@ import net.minecraft.world.entity.LivingEntity
import kotlin.collections.get
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec3
import kotlin.collections.get
import kotlin.math.max
/**
* Small wrapper around a RidingBehaviour to provide sane defaults in the event that the behaviour is not active.
@@ -51,11 +49,6 @@ class RidingController(
fun tick() {
if (entity.ticksLived - lastTransitionAge < 10) return
val newTransition = checkForNewTransition(entity.controllingPassenger)
// If transitioning to air then give an upward boost
if (newTransition == RidingStyle.AIR && context?.style != RidingStyle.AIR && context?.state != null) {
val currVel = context!!.state.rideVelocity.get()
context!!.state.rideVelocity.set(Vec3(currVel.x, max(0.4, currVel.y), currVel.z))
}
val behaviourSettings = entity.pokemon.riding.behaviours?.get(newTransition)
if (newTransition != context?.style) {
if (newTransition != null && behaviourSettings != null) {
@@ -291,10 +291,10 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalBird.handlingExpr!!)
val yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble()))
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble()))).coerceIn(-1.0, 1.0)
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble()))*2).coerceIn(-1.0, 1.0)
// Dampen yaw when upside down
val yawDampen = (1 - abs(min(cos(controller.roll.toRadians()),0.0f)))
val yawDampen = (1 - abs(min(cos(controller.roll.toRadians()),0.0f)).pow(2))
controller.applyGlobalYaw(trueYawDelt.toFloat() * yawDampen)
// Correct orientation when at low speeds
@@ -591,7 +591,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
state: BirdState,
vehicle: PokemonEntity
): Boolean {
return true
return false
}
override fun damageOnCollision(
@@ -31,7 +31,6 @@ import com.cobblemon.mod.common.util.resolveDouble
import com.cobblemon.mod.common.util.resolveFloat
import com.cobblemon.mod.common.util.writeNullableExpression
import com.cobblemon.mod.common.util.writeRidingStats
import net.minecraft.client.Minecraft
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
@@ -66,7 +65,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
val poseProvider = PoseProvider<HorseSettings, HorseState>(PoseType.STAND)
.with(PoseOption(PoseType.WALK) { _, state, vehicle ->
return@PoseOption state.walking.get()
return@PoseOption abs(state.rideVelocity.get().horizontalDistance()) > 0.0
})
override fun isActive(
@@ -112,12 +111,9 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
driver: Player,
input: Vec3
) {
if (vehicle.level().isClientSide) {
handleSprinting(state)
inAirCheck(state, vehicle)
tickStamina(settings, state, vehicle)
state.walking.set(state.rideVelocity.get().horizontalDistance() > 0.01)
}
handleSprinting(state, driver)
inAirCheck(state, vehicle)
tickStamina(settings, state, vehicle)
}
fun inAirCheck(
@@ -138,22 +134,15 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
}
fun handleSprinting(
state: HorseState
state: HorseState,
driver: Player
) {
val tryingToSprint = Minecraft.getInstance().options.keySprint.isDown() && Minecraft.getInstance().options.keyUp.isDown()
if (state.stamina.get() <= 0.0f || !Minecraft.getInstance().options.keyUp.isDown()) {
// If stamina runs out or the player is not holding forward then stop sprinting
state.sprinting.set(false)
if (state.stamina.get() <= 0.0f) {
state.sprintToggleable.set(false)
}
} else if (!state.sprinting.get() && !state.sprintToggleable.get() && state.stamina.get() > 0.33f) {
// If you are not sprinting and sprint is not toggleable and you're not trying to sprint and stamina is above 0.3 then enable the toggle
state.sprintToggleable.set(true)
} else if (tryingToSprint && state.sprintToggleable.get()) {
// If you are trying to sprint and the toggle allows it then start sprinting and disable toggle
state.sprinting.set(true)
if (state.sprinting.get()) {
state.sprinting.set(driver.isSprinting && state.stamina.get() > 0.0f)
} else {
// Only allow sprinting to start if over x percentage of stamina left
val stamSprintPerc = 25.0f
state.sprinting.set(driver.isSprinting && state.stamina.get() > stamSprintPerc / 100.0f)
}
}
@@ -613,16 +602,12 @@ class HorseSettings : RidingBehaviourSettings {
class HorseState : RidingBehaviourState() {
var sprinting = ridingState(false, Side.CLIENT)
var walking = ridingState(false, Side.BOTH)
var sprintToggleable = ridingState(false, Side.CLIENT)
var inAir = ridingState(false, Side.CLIENT)
var jumpTicks = ridingState(0, Side.CLIENT)
override fun encode(buffer: FriendlyByteBuf) {
super.encode(buffer)
buffer.writeBoolean(sprinting.get())
buffer.writeBoolean(walking.get())
buffer.writeBoolean(sprintToggleable.get())
buffer.writeBoolean(inAir.get())
buffer.writeInt(jumpTicks.get())
}
@@ -630,8 +615,6 @@ class HorseState : RidingBehaviourState() {
override fun decode(buffer: FriendlyByteBuf) {
super.decode(buffer)
sprinting.set(buffer.readBoolean(), forced = true)
walking.set(buffer.readBoolean(), forced = true)
sprintToggleable.set(buffer.readBoolean(), forced = true)
inAir.set(buffer.readBoolean(), forced = true)
jumpTicks.set(buffer.readInt(), forced = true)
}
@@ -639,8 +622,6 @@ class HorseState : RidingBehaviourState() {
override fun reset() {
super.reset()
sprinting.set(false, forced = true)
walking.set(false, forced = true)
sprintToggleable.set(false, forced = true)
inAir.set(false, forced = true)
jumpTicks.set(0, forced = true)
}
@@ -649,8 +630,6 @@ class HorseState : RidingBehaviourState() {
it.rideVelocity.set(this.rideVelocity.get(), forced = true)
it.stamina.set(this.stamina.get(), forced = true)
it.sprinting.set(this.sprinting.get(), forced = true)
it.walking.set(this.sprinting.get(), forced = true)
it.sprintToggleable.set(this.sprintToggleable.get(), forced = true)
it.inAir.set(this.inAir.get(), forced = true)
it.jumpTicks.set(this.jumpTicks.get(), forced = true)
}
@@ -658,8 +637,6 @@ class HorseState : RidingBehaviourState() {
override fun shouldSync(previous: RidingBehaviourState): Boolean {
if (previous !is HorseState) return false
if (previous.sprinting.get() != sprinting.get()) return true
if (previous.walking.get() != walking.get()) return true
if (previous.sprintToggleable.get() != sprintToggleable.get()) return true
if (previous.inAir.get() != inAir.get()) return true
return super.shouldSync(previous)
}
@@ -57,9 +57,9 @@ class SubmarineBehaviour : RidingBehaviour<SubmarineSettings, SubmarineState> {
}
val poseProvider = PoseProvider<SubmarineSettings, SubmarineState>(PoseType.FLOAT)
.with(PoseOption(PoseType.SWIM) { _, state, entity -> state.rideVelocity.get().z > 0.05 && !state.onSurface.get()})
.with(PoseOption(PoseType.STAND) { _, state, entity -> state.rideVelocity.get().z <= 0.05 && state.onSurface.get()})
.with(PoseOption(PoseType.STAND) { _, state, entity -> state.rideVelocity.get().z > 0.05 && state.onSurface.get()})
.with(PoseOption(PoseType.SWIM) { _, state, entity -> abs(state.rideVelocity.get().z) > 0.05 && !state.onSurface.get()})
.with(PoseOption(PoseType.STAND) { _, state, entity -> abs(state.rideVelocity.get().z) <= 0.05 && state.onSurface.get()})
.with(PoseOption(PoseType.STAND) { _, state, entity -> abs(state.rideVelocity.get().z) > 0.05 && state.onSurface.get()})
override fun isActive(settings: SubmarineSettings, state: SubmarineState, vehicle: PokemonEntity): Boolean {
return vehicle.isInWater || !vehicle.onGround()
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.riding.stats
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.util.lang
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
/**
* A stat that is used for riding Pokémon. The exact implementation of each of these depends on the [com.cobblemon.mod.common.api.riding.controller.RideController].
@@ -30,9 +29,10 @@ enum class RidingStat(
companion object {
fun getByName(name: String) = RidingStat.entries.firstOrNull { it.name.equals(name, ignoreCase = true) }
fun getByFlavour(flavour: Flavour) = RidingStat.entries.firstOrNull { it.flavour == flavour }
}
val displayName: MutableComponent
get() = lang("ui.stats.ride.${name.lowercase()}")
val displayName: Component
get() = lang("riding.stat.${name.lowercase()}.name")
val description: Component
get() = lang("riding.stat.${name.lowercase()}.desc")
}
@@ -0,0 +1,70 @@
/*
* 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.api.riding.stats
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.net.IntSize
import com.cobblemon.mod.common.util.readSizedInt
import com.cobblemon.mod.common.util.readText
import com.cobblemon.mod.common.util.writeSizedInt
import com.cobblemon.mod.common.util.writeText
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.chat.Component
/**
* The definition of all the different information related to a specific [RidingStat] on a Pokémon species.
*
* @author Hiroku
* @since February 17th, 2025
*/
class RidingStatDefinition {
// This object gets read from a JSON adapter manually (field-by-field) so don't add fields without updating the adapter.
/** A map from [RidingStyle] to a minimum and maximum value for this stat. */
val ranges = mutableMapOf<RidingStyle, IntRange>()
/** Display name for the stat, if null falls back to [RidingStat.displayName]. */
var displayName: Component? = null
/** Description for the stat, if null falls back to [RidingStat.description]. */
var description: Component? = null
fun calculate(style: RidingStyle, aprijuiceBoost: Int): Float {
val range = ranges[style] ?: ranges[RidingStyle.LAND] ?: return 0F
val boostQuotient = aprijuiceBoost / 255F
return range.first + (range.last - range.first) * boostQuotient
}
fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeNullable(displayName) { _, it -> buffer.writeText(it) }
buffer.writeNullable(description) { _, it -> buffer.writeText(it) }
buffer.writeMap(
ranges,
{ _, it -> buffer.writeEnum(it) },
{ _, it ->
buffer.writeSizedInt(IntSize.U_BYTE, it.first)
buffer.writeSizedInt(IntSize.U_BYTE, it.last)
}
)
}
companion object {
fun decode(buffer: RegistryFriendlyByteBuf): RidingStatDefinition {
val displayName = buffer.readNullable { buffer.readText() }
val description = buffer.readNullable { buffer.readText() }
val ranges = buffer.readMap<RidingStyle, IntRange>(
{ buffer.readEnum<RidingStyle>(RidingStyle::class.java) },
{ IntRange(buffer.readSizedInt(IntSize.U_BYTE), buffer.readSizedInt(IntSize.U_BYTE)) }
)
return RidingStatDefinition().apply {
this.displayName = displayName
this.description = description
this.ranges.putAll(ranges)
}
}
}
}
@@ -23,7 +23,6 @@ import com.cobblemon.mod.common.api.spawning.detail.PokemonHerdSpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.PokemonSpawnDetail
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.influence.BucketMultiplyingInfluence
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
import com.cobblemon.mod.common.api.spawning.position.FishingSpawnablePosition
@@ -142,16 +141,6 @@ object BestSpawner {
fishingSpawner = BasicSpawner(
name = "fishing",
spawnPool = CobblemonSpawnPools.WORLD_SPAWN_POOL
).also {
it.influences.add(
BucketMultiplyingInfluence(
multipliers = mapOf(
"uncommon" to 2.25f,
"rare" to 5.5f,
"ultra-rare" to 5.5f,
)
)
)
}
)
}
}
@@ -34,7 +34,7 @@ import net.minecraft.server.packs.PackType
* A single spawn pool may be used for many different [Spawner]s. Note that changing the
* [details] list will change the spawns for any [Spawner] sharing this pool. If you want
* to make a change for a pool specifically to one spawner, take a copy of the pool using
* [copy], and change that spawner's pool using [Spawner.spawnPool] setters.
* [copy], and change that spawner's pool using [Spawner.setSpawnPool].
*
* @author Hiroku
* @since February 9th, 2022
@@ -51,7 +51,7 @@ open class PokeSnackBlockEntity(pos: BlockPos, state: BlockState) :
companion object {
const val SPAWNS_PER_BITE = 1
const val RADIUS = 8
const val RANDOM_TICKS_BETWEEN_SPAWNS = 2
const val RANDOM_TICKS_BETWEEN_SPAWNS = 4
const val POKE_SNACK_CRUMBED_ASPECT = "poke_snack_crumbed"
}
@@ -23,7 +23,6 @@ import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.block.entity.TintBlockEntity
import com.cobblemon.mod.common.client.battle.ClientBattle
import com.cobblemon.mod.common.client.gui.PartyOverlay
import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
import com.cobblemon.mod.common.client.gui.RideControlsOverlay
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
@@ -66,7 +65,7 @@ import com.cobblemon.mod.common.client.tooltips.CobblemonTooltipGenerator
import com.cobblemon.mod.common.client.tooltips.FishingBaitTooltipGenerator
import com.cobblemon.mod.common.client.tooltips.FishingRodTooltipGenerator
import com.cobblemon.mod.common.client.tooltips.PokePuffTooltipGenerator
import com.cobblemon.mod.common.client.tooltips.RecipeSeasoningAbsorptionTooltipGenerator
import com.cobblemon.mod.common.client.tooltips.RecipeSeasoningAbsorbtionTooltipGenerator
import com.cobblemon.mod.common.client.tooltips.SeasoningTooltipGenerator
import com.cobblemon.mod.common.client.tooltips.TooltipManager
import com.cobblemon.mod.common.client.trade.ClientTrade
@@ -193,13 +192,12 @@ object CobblemonClient {
}
}
ClientPlayerIcon.onTick()
PartyOverlayDataControl.tick(event.client.isPaused)
}
}
private fun registerTooltipManagers() {
TooltipManager.registerTooltipGenerator(CobblemonTooltipGenerator)
TooltipManager.registerTooltipGenerator(RecipeSeasoningAbsorptionTooltipGenerator)
TooltipManager.registerTooltipGenerator(RecipeSeasoningAbsorbtionTooltipGenerator)
TooltipManager.registerTooltipGenerator(FishingBaitTooltipGenerator)
TooltipManager.registerTooltipGenerator(SeasoningTooltipGenerator)
TooltipManager.registerTooltipGenerator(FishingRodTooltipGenerator)
@@ -58,7 +58,7 @@ object MountedCameraTypeHandler {
fun handleTransition(passenger: Entity, fromKey: ResourceLocation, toKey: ResourceLocation) {
val mc = Minecraft.getInstance()
if (passenger != mc.player) {
if (passenger == mc.player) {
return
}
val currentCameraType = mc.options.cameraType
@@ -39,8 +39,6 @@ import net.minecraft.client.gui.components.toasts.Toast
import net.minecraft.client.gui.screens.ChatScreen
import net.minecraft.client.gui.screens.Screen
import net.minecraft.util.Mth
import kotlin.math.ceil
import kotlin.math.floor
class PartyOverlay : Gui(Minecraft.getInstance()) {
@@ -59,35 +57,15 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
private val genderIconMale = cobblemonResource("textures/gui/party/party_gender_male.png")
private val genderIconFemale = cobblemonResource("textures/gui/party/party_gender_female.png")
private val portraitBackground = cobblemonResource("textures/gui/party/party_slot_portrait_background.png")
private val newMovesPopup = cobblemonResource("textures/gui/party/party_slot_notification_new_move.png")
private val newEvoPopup = cobblemonResource("textures/gui/party/party_slot_notification_evolution.png")
private val levelScroll = cobblemonResource("textures/gui/party/party_slot_portrait_level_up.png")
private val screenExemptions: List<Class<out Screen>> = listOf(
ChatScreen::class.java,
BattleGUI::class.java
)
fun canRender(): Boolean {
val minecraft = Minecraft.getInstance()
// Hiding if a Screen is open and not exempt
if (minecraft.screen != null) {
if (!screenExemptions.contains(minecraft.screen?.javaClass as Class<out Screen>))
return false
}
if (minecraft.options.hideGui || minecraft.debugOverlay.showDebugScreen()) {
return false
}
// Hiding if toggled via Keybind
if (HidePartyBinding.shouldHide) {
return false
}
return true
}
}
private val stateAtIndex = hashMapOf<Int, Pair<UUID, FloatingState>>()
private val screenExemptions: List<Class<out Screen>> = listOf(
ChatScreen::class.java,
BattleGUI::class.java
)
val starterToast = CobblemonToast(
Mth.createInsecureUUID(),
CobblemonItems.POKE_BALL.defaultInstance,
@@ -118,11 +96,23 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
}
override fun render(context: GuiGraphics, tickCounter: DeltaTracker) {
if (!canRender()) return
val partialDeltaTicks = tickCounter.realtimeDeltaTicks
val minecraft = Minecraft.getInstance()
// Hiding if a Screen is open and not exempt
if (minecraft.screen != null) {
if (!screenExemptions.contains(minecraft.screen?.javaClass as Class<out Screen>))
return
}
if (minecraft.options.hideGui || minecraft.debugOverlay.showDebugScreen()) {
return
}
// Hiding if toggled via Keybind
if (HidePartyBinding.shouldHide) {
return
}
val panelX = 0
val party = CobblemonClient.storage.party
val matrices = context.pose()
@@ -217,46 +207,6 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
)
if (pokemon != null) {
val expGainedData = PartyOverlayDataControl.getExpGainedData(pokemon.uuid)
//Handling Level Up Scroll / For some reason draw text makes any future blitk render behind our model render, don't ask why
var displayLevelScroll = false
var levelScrollOffset = 0F
var levelScrollPositionOffset = 0F
var levelScrollSize = 17F
if (expGainedData != null && expGainedData.oldLevel != null) {
val ticksWithDelta = (expGainedData.ticks + partialDeltaTicks) - (PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME + PartyOverlayDataControl.BAR_FLASH_TIME)
val transition = ticksWithDelta / PartyOverlayDataControl.LEVEL_UP_PORTRAIT_TIME
if ((0F..<1F).contains(transition)) {
displayLevelScroll = true
var step = ceil(transition * 14)
if (step <= 4) {
levelScrollSize = step * 4
levelScrollPositionOffset = 17 - (levelScrollSize)
} else if (step <= 10) {
step -= 4
levelScrollOffset = -1 + (step * 4)
} else {
step -= 10
levelScrollSize = 20 - (step * 4)
levelScrollOffset = 23 + (step * 4)
}
}
}
if (displayLevelScroll) {
blitk(
matrixStack = matrices,
texture = levelScroll,
x = (panelX + selectedOffsetX + portraitFrameOffsetX + 2),
y = (indexY + portraitFrameOffsetY + 2 + levelScrollPositionOffset),
height = levelScrollSize,
width = 17,
textureHeight = 43,
vOffset = levelScrollOffset
)
}
val stateIcon = pokemon.state.getIcon(pokemon)
if (stateIcon != null) {
blitk(
@@ -280,17 +230,9 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
shadow = true
)
var level = pokemon.level
if (expGainedData?.oldLevel != null) {
val ticksWithDelta = expGainedData.ticks + partialDeltaTicks
if (ticksWithDelta < PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME) {
level = expGainedData.oldLevel!!
}
}
drawScaledText(
context = context,
text = level.toString().text(),
text = pokemon.level.toString().text(),
x = panelX + selectedOffsetX + 6.5F,
y = indexY + 18,
scale = SCALE,
@@ -339,47 +281,9 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
blue = 0.27F
)
val expRatio: Float
val expForThisLevel = pokemon.experience - if (pokemon.level == 1) 0 else pokemon.experienceGroup.getExperience(pokemon.level)
val expToNextLevel = pokemon.experienceGroup.getExperience(pokemon.level + 1) - pokemon.experienceGroup.getExperience(pokemon.level)
var expRed = 0.2
var expGreen = 0.65
var expBlue = 0.84
if (expGainedData != null) {
val ticksWithDelta = expGainedData.ticks + partialDeltaTicks
if (expGainedData.oldLevel != null) {
//Handling Exp Bar
if (ticksWithDelta <= PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME) {
val expForLastLevel = (pokemon.experience - expGainedData.expGained) - if (expGainedData.oldLevel!! == 1) 0 else pokemon.experienceGroup.getExperience(expGainedData.oldLevel!!)
val expNeededForLastLevel = pokemon.experienceGroup.getExperience(expGainedData.oldLevel!! + 1) - pokemon.experienceGroup.getExperience(expGainedData.oldLevel!!)
val transition = (ticksWithDelta / PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME.toFloat()).coerceIn(0F..1F)
val transitionXP = expForLastLevel + ((expNeededForLastLevel - expForLastLevel) * transition)
expRatio = transitionXP / expNeededForLastLevel
} else if (ticksWithDelta <= PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME + PartyOverlayDataControl.BAR_FLASH_TIME) {
expRatio = 1F
expRed = 1.0
expGreen = 1.0
expBlue = 1.0
}
else {
val adjustedTicks = ticksWithDelta - (PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME + PartyOverlayDataControl.BAR_FLASH_TIME)
val transition = (adjustedTicks / PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME.toFloat()).coerceIn(0F..1F)
val transitionXP = expForThisLevel * transition
expRatio = transitionXP / expToNextLevel
}
} else {
//Handling Exp Bar
val transition = (ticksWithDelta / PartyOverlayDataControl.BAR_UPDATE_NO_LEVEL_TIME.toFloat()).coerceIn(0F..1F)
val transitionXP = expForThisLevel - (expGainedData.expGained * (1 - transition))
expRatio = transitionXP / expToNextLevel
}
} else {
expRatio = expForThisLevel / expToNextLevel.toFloat()
}
val expRatio = expForThisLevel / expToNextLevel.toFloat()
val expBarWidth = 1
val expBarHeight = expRatio * barHeightMax
@@ -393,80 +297,11 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
height = expBarHeight,
textureHeight = expBarHeight / expRatio,
vOffset = barHeightMax - expBarHeight,
red = expRed,
green = expGreen,
blue = expBlue
red = 0.2,
green = 0.65,
blue = 0.84
)
var ticksForMove = -1F
var ticksForEvo = -1F
//Handling Popups
if (expGainedData != null) {
val ticksWithDelta = expGainedData.ticks + partialDeltaTicks
val ticks = ticksWithDelta - (PartyOverlayDataControl.BAR_UPDATE_BEFORE_TIME + PartyOverlayDataControl.BAR_FLASH_TIME)
if (expGainedData.countOfMovesLearned > 0) {
ticksForMove = ticks
}
if (expGainedData.countOfEvosUnlocked > 0) {
ticksForEvo = ticks
}
} else {
val evoGainedData = PartyOverlayDataControl.getEvolutionData(pokemon.uuid)
if (evoGainedData != null) {
ticksForEvo = evoGainedData.ticks + partialDeltaTicks
}
val moveGainedData = PartyOverlayDataControl.getMovesData(pokemon.uuid)
if (moveGainedData != null) {
ticksForMove = moveGainedData.ticks + partialDeltaTicks
}
}
fun popupData(ticks: Float) : Pair<Float, Float> {
if (ticks > 0) {
if (ticks <= PartyOverlayDataControl.POPUP_TIME.fadeIn) {
val transition = ticks / PartyOverlayDataControl.POPUP_TIME.fadeIn
val step = (floor(transition * 3)) + 1
return (4 - step) to (step * 0.25F)
} else if (ticks <= PartyOverlayDataControl.POPUP_TIME.fadeIn + PartyOverlayDataControl.POPUP_TIME.hold) {
return 0F to 1F
} else {
val adjustedPopupTicks = ticks - (PartyOverlayDataControl.POPUP_TIME.fadeIn + PartyOverlayDataControl.POPUP_TIME.hold)
val transition = adjustedPopupTicks / PartyOverlayDataControl.POPUP_TIME.fadeIn
val step = (floor(transition * 3)) + 1
return (-step) to (1F - (step * 0.25F))
}
} else return 0F to 0F
}
val (movePopupYOffset, movePopupTransparency) = popupData(ticksForMove)
val (evoPopupYOffset, evoPopupTransparency) = popupData(ticksForEvo)
if (evoPopupTransparency > 0) {
blitk(
matrixStack = matrices,
texture = newEvoPopup,
x = (panelX + selectedOffsetX + 56.5F) / SCALE,
y = (indexY + 4 + evoPopupYOffset) / SCALE,
width = 37,
height = 20,
scale = SCALE,
alpha = evoPopupTransparency
)
}
if (movePopupTransparency > 0) {
blitk(
matrixStack = matrices,
texture = newMovesPopup,
x = (panelX + selectedOffsetX + 56.5F) / SCALE,
y = (indexY + 17 + movePopupYOffset) / SCALE,
width = 37,
height = 20,
scale = SCALE,
alpha = movePopupTransparency
)
}
val ballIcon = cobblemonResource("textures/gui/ball/" + pokemon.caughtBall.name.path + ".png")
val ballHeight = 22
blitk(
@@ -1,227 +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.client.gui
import com.cobblemon.mod.common.CobblemonSounds
import net.minecraft.client.Minecraft
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.client.resources.sounds.SoundInstance
import net.minecraft.sounds.SoundEvent
import java.util.*
object PartyOverlayDataControl {
const val BAR_UPDATE_BEFORE_TIME = 15
const val BAR_UPDATE_AFTER_TIME = 15
const val BAR_FLASH_TIME = 2
val POPUP_TIME = FadeTimings(3, 40, 3)
const val LEVEL_UP_PORTRAIT_TIME = 10
val BAR_UPDATE_NO_LEVEL_TIME = BAR_UPDATE_BEFORE_TIME + BAR_UPDATE_AFTER_TIME + BAR_FLASH_TIME
private enum class RenderTarget {
NONE,
EXP_GAINED,
EVOLUTION,
MOVES
}
private val overlayData = mutableMapOf<UUID, OverlayData>()
private var barFillupSound: SoundInstance? = null
private var levelUpJingleSound: SoundInstance? = null
fun pokemonGainedExp(pokemonUuid : UUID, oldLevel: Int?, expGained: Int, countOfMovesLearned: Int, countOfEvosUnlocked: Int = 0) {
var time = BAR_UPDATE_NO_LEVEL_TIME
if (countOfMovesLearned > 0 || countOfEvosUnlocked > 0) {
time = BAR_UPDATE_BEFORE_TIME + BAR_FLASH_TIME + POPUP_TIME.total()
}
val data = overlayData[pokemonUuid]
val newData = ExpGainedData(oldLevel, expGained, countOfMovesLearned, countOfEvosUnlocked).also { it.ticksMax = time }
if (data != null) {
if (data.movesGainedData != null) {
newData.countOfMovesLearned += data.movesGainedData!!.movesCount
}
if (data.evoGainedData != null) {
newData.countOfEvosUnlocked += data.evoGainedData!!.evolutionCount
}
val expData = data.expGainedData
if (expData != null) {
newData.countOfMovesLearned += expData.countOfMovesLearned
newData.countOfEvosUnlocked += expData.countOfEvosUnlocked
if (expData.oldLevel != null) {
newData.oldLevel = expData.oldLevel
}
newData.expGained += expData.expGained
}
}
overlayData[pokemonUuid] = OverlayData(expGainedData = newData)
stopSound(barFillupSound)
barFillupSound = playSound(CobblemonSounds.LEVELUP_START)
}
fun pokemonGainedEvo(pokemonUuid : UUID, evoCount: Int) {
val data = overlayData[pokemonUuid]
val newData = EvolutionGainedData(evoCount).also { it.ticksMax = POPUP_TIME.total() }
if (data != null) {
if (data.expGainedData != null && data.expGainedData!!.ticks < BAR_UPDATE_BEFORE_TIME + BAR_FLASH_TIME) {
data.expGainedData!!.ticksMax = BAR_UPDATE_BEFORE_TIME + BAR_FLASH_TIME + POPUP_TIME.total()
data.expGainedData!!.countOfEvosUnlocked += evoCount
return
}
if (data.evoGainedData != null) {
data.evoGainedData!!.evolutionCount += evoCount
data.evoGainedData!!.ticks = 0
} else {
data.evoGainedData = newData
}
} else {
overlayData[pokemonUuid] = OverlayData(evoGainedData = newData)
}
}
fun pokemonGainedMoves(pokemonUuid : UUID, movesCount: Int) { //Unused for now I think, until TMs work, as I don't think you can get any other way than level up
val data = overlayData[pokemonUuid]
val newData = MovesGainedData(movesCount).also { it.ticksMax = POPUP_TIME.total() }
if (data != null) {
if (data.expGainedData != null && data.expGainedData!!.ticks < BAR_UPDATE_BEFORE_TIME + BAR_FLASH_TIME) {
data.expGainedData!!.ticksMax = BAR_UPDATE_BEFORE_TIME + BAR_FLASH_TIME + POPUP_TIME.total()
data.expGainedData!!.countOfMovesLearned += movesCount
return
}
if (data.movesGainedData != null) {
data.movesGainedData!!.movesCount += movesCount
data.evoGainedData!!.ticks = 0
} else {
data.movesGainedData = newData
}
} else {
overlayData[pokemonUuid] = OverlayData(movesGainedData = newData)
}
}
private fun getCurrentRenderTarget(uuid: UUID): RenderTarget {
val data = overlayData[uuid] ?: return RenderTarget.NONE
if (data.expGainedData != null) return RenderTarget.EXP_GAINED
if (data.evoGainedData != null) return RenderTarget.EVOLUTION
if (data.movesGainedData != null) return RenderTarget.MOVES
return RenderTarget.NONE
}
fun getExpGainedData(uuid: UUID): ExpGainedData? {
if (getCurrentRenderTarget(uuid) != RenderTarget.EXP_GAINED) return null
return overlayData[uuid]?.expGainedData
}
fun getEvolutionData(uuid: UUID): EvolutionGainedData? {
if (getCurrentRenderTarget(uuid) != RenderTarget.EVOLUTION) return null
return overlayData[uuid]?.evoGainedData
}
fun getMovesData(uuid: UUID): MovesGainedData? {
if (getCurrentRenderTarget(uuid) != RenderTarget.MOVES) return null
return overlayData[uuid]?.movesGainedData
}
fun tick(paused: Boolean) {
val deletion = mutableListOf<UUID>()
if (paused) return
overlayData.forEach { (id, data) ->
if (data.expGainedData != null) { // We update this in order and render these in order, and as such we don't tick others
val expGainedData = data.expGainedData!!
expGainedData.ticks += 1
if (expGainedData.ticks == BAR_UPDATE_BEFORE_TIME && expGainedData.oldLevel != null) {
stopSound(levelUpJingleSound)
levelUpJingleSound = playSound(CobblemonSounds.LEVELUP)
}
if (expGainedData.ticks >= expGainedData.ticksMax) {
data.expGainedData = null
}
} else {
if (data.evoGainedData != null) {
val evoGainedData = data.evoGainedData!!
evoGainedData.ticks += 1
if (evoGainedData.ticks >= evoGainedData.ticksMax) {
data.evoGainedData = null
}
}
if (data.movesGainedData != null) {
val movesGainedData = data.movesGainedData!!
movesGainedData.ticks += 1
if (movesGainedData.ticks >= movesGainedData.ticksMax) {
data.movesGainedData = null
}
}
}
if (getCurrentRenderTarget(id) == RenderTarget.NONE) deletion.add(id)
}
deletion.forEach {
overlayData.remove(it)
}
}
fun clear() {
overlayData.clear()
stopSound(barFillupSound)
stopSound(levelUpJingleSound)
}
open class TickCounter(
var ticksMax: Int,
var ticks: Int = 0
)
class ExpGainedData (
var oldLevel: Int?, //If Null we never leveled up
var expGained: Int,
var countOfMovesLearned: Int, //We don't care what moves we learned, just how many
var countOfEvosUnlocked: Int
) : TickCounter(0)
class EvolutionGainedData (
var evolutionCount: Int
) : TickCounter(0)
class MovesGainedData (
var movesCount: Int
) : TickCounter(0)
data class OverlayData(
var expGainedData: ExpGainedData? = null,
var evoGainedData: EvolutionGainedData? = null,
var movesGainedData: MovesGainedData? = null
)
data class FadeTimings(
val fadeIn: Int,
val hold: Int,
val fadeOut: Int
) {
fun total(): Int {
return fadeIn + hold + fadeOut
}
}
//SOUNDS
private fun playSound(soundEvent: SoundEvent): SoundInstance? {
if (!PartyOverlay.canRender()) return null
val soundInstance = SimpleSoundInstance.forUI(soundEvent, 1F)
Minecraft.getInstance().soundManager.play(soundInstance)
return soundInstance
}
private fun stopSound(soundInstance: SoundInstance?) {
if (soundInstance != null) Minecraft.getInstance().soundManager.stop(soundInstance)
}
}
@@ -1,25 +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.client.net.gui
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
import net.minecraft.client.Minecraft
object ExpGainedDataPacketHandler: ClientNetworkPacketHandler<ExpGainedDataPacket> {
override fun handle(packet: ExpGainedDataPacket, client: Minecraft) {
PartyOverlayDataControl.pokemonGainedExp(
packet.pokemonUUID,
packet.oldLevel,
packet.expGained,
packet.countOfMovesLearned
)
}
}
@@ -14,9 +14,6 @@ import com.cobblemon.mod.common.api.text.yellow
import com.cobblemon.mod.common.util.lang
import net.minecraft.network.chat.Component
/**
* Used for aprijuice quality.
*/
enum class CookingQuality {
LOW {
override fun getLang(): Component = lang("cooking.cooking_quality.low").red()
@@ -18,10 +18,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.repository.Varyi
import com.cobblemon.mod.common.duck.RidePassenger
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.mixin.accessor.CameraAccessor
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.client.Camera
import net.minecraft.client.CameraType
import net.minecraft.client.Minecraft
import net.minecraft.util.Mth
import net.minecraft.world.entity.Entity
import net.minecraft.world.level.ClipContext
@@ -63,24 +60,18 @@ object MountedCameraRenderer
val locator = delegate.locatorStates[locatorName] ?: return null
val currEyeHeight: Double = Mth.lerp(instance.partialTickTime.toDouble(), eyeHeight, eyeHeightOld)
val offset = Vector3f(0f, (currEyeHeight - (driver.bbHeight / 2)).toFloat(), 0f)
val eyeOffset = Vector3f(0f, (currEyeHeight - (driver.bbHeight / 2)).toFloat(), 0f)
var offset = Vector3f(0f, (currEyeHeight - (driver.bbHeight / 2)).toFloat(), 0f)
var eyeOffset = Vector3f(0f, (currEyeHeight - (driver.bbHeight / 2)).toFloat(), 0f)
// Get additional offset from poser and add to the eyeHeight offset
val shouldFlip = !(vehicleController.active && vehicleController.orientation != null) // Do not flip the offset for 3rd person reverse unless we are using normal mc camera rotation.
val isFirstPerson = Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON
val rotMatrix = if (vehicleController.isActive()) vehicleController.getRenderOrientation(instance.partialTickTime)
else Quaternionf()
.rotateY((180f - Mth.lerp(instance.partialTickTime, vehicle.yBodyRotO, vehicle.yBodyRot).toRadians()))
.rotateX(-1 * Mth.lerp(instance.partialTickTime, vehicle.xRotO, vehicle.xRot).toRadians())
eyeOffset.add(getFirstPersonOffset(model, locatorName))
if (isFirstPerson) {
if (!instance.isDetached) {
offset.add(
getFirstPersonOffset(model, locatorName)
)
} else if (Cobblemon.config.thirdPersonViewBobbing) {
} else if( Cobblemon.config.thirdPersonViewBobbing) {
offset.add(
getThirdPersonOffset(thirdPersonReverse, model.thirdPersonCameraOffset, locatorName, shouldFlip)
)
@@ -90,29 +81,22 @@ object MountedCameraRenderer
)
}
// Grab the pokemon's orientation to use as the offset rotation.
rotMatrix.transform(offset)
rotMatrix.transform(eyeOffset)
// Grab the current camera rotation to use as the offset rotation.
val offsetRot = instance.rotation()
offset = offsetRot.transform(offset)
eyeOffset = offsetRot.transform(eyeOffset)
val eyeLocatorOffset = Vec3(locator.matrix.getTranslation(Vector3f()))
val eyePos = eyeLocatorOffset.add(entityPos).toVector3f()
// Get the camera position. If 3rd person viewbobbing is enabled or the player is
// in first person then base the camera position off the seat locator offset
val pos = if (!isFirstPerson || Cobblemon.config.thirdPersonViewBobbing) {
val pos = if (!instance.isDetached || Cobblemon.config.thirdPersonViewBobbing) {
val locatorOffset = Vec3(locator.matrix.getTranslation(Vector3f()))
locatorOffset.add(entityPos).toVector3f()
} else {
val pokemonCenter = Vector3f(0f, driver.bbHeight/2, 0f)
val pivotOffsets = model.thirdPersonPivotOffset
val pivot = Vector3f(pokemonCenter)
val locatorName = delegate.getSeatLocator(driver)
if (pivotOffsets.containsKey(locatorName)) {
val orientation = vehicleController.getRenderOrientation(instance.partialTickTime)
pivot.add(orientation.transform(pivotOffsets[locatorName]!!.toVector3f()))
}
entityPos.toVector3f().add(pivot)
entityPos.toVector3f().add(pokemonCenter)
}
val offsetDistance = offset.length()
@@ -126,7 +110,7 @@ object MountedCameraRenderer
val eyeMaxZoom: Float = getMaxZoom(eyeOffsetDistance, eyeOffsetDirection, eyePos, instance)
val playerRotater = driver as RidePassenger
playerRotater.`cobblemon$setRideEyePos`(Vec3(eyeOffsetDirection.mul(eyeMaxZoom).add(eyePos)))
playerRotater.`cobblemon$setRideEyePos`(Vec3(eyeOffsetDirection.mul(eyeMaxZoom).add(eyePos)).add(0.0, 2.0, 0.0))
return Vec3(offsetDirection.mul(maxZoom).add(pos))
}
@@ -9,8 +9,11 @@
package com.cobblemon.mod.common.client.render.color
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.cooking.getColourMixFromRideStatBoosts
import com.cobblemon.mod.common.api.cooking.getColourMixFromFlavours
import com.cobblemon.mod.common.client.pot.CookingQuality
import net.minecraft.ChatFormatting
import net.minecraft.client.color.item.ItemColor
import net.minecraft.util.FastColor
import net.minecraft.world.item.ItemStack
object AprijuiceItemColorProvider : ItemColor {
@@ -20,6 +23,8 @@ object AprijuiceItemColorProvider : ItemColor {
override fun getColor(stack: ItemStack, layer: Int): Int {
if (layer == 0) return -1
val flavourComponent = stack.get(CobblemonItemComponents.FLAVOUR) ?: return -1
// todo we are not coloring the leaf anymore
/*if (layer == LEAF_INDEX) {
val quality = flavourComponent.getQuality()
@@ -33,12 +38,7 @@ object AprijuiceItemColorProvider : ItemColor {
}*/
if (layer == JUICE_INDEX) {
val rideBoostsComponent = stack.get(CobblemonItemComponents.RIDE_BOOST) ?: return -1
if (rideBoostsComponent.boosts.isEmpty()) return -1
val highestBoost = rideBoostsComponent.boosts.maxOf { it.value }
val highestRidingStats = rideBoostsComponent.boosts.filter { it.value == highestBoost }.keys
if (highestRidingStats.isEmpty()) return -1
val colorMix = getColourMixFromRideStatBoosts(highestRidingStats)
val colorMix = getColourMixFromFlavours(flavourComponent.getDominantFlavours())
if (colorMix != null) return colorMix
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.client.render.entity
import com.cobblemon.mod.common.OrientationControllable
import com.cobblemon.mod.common.api.riding.Rideable
import com.cobblemon.mod.common.client.MountedPokemonAnimationRenderController
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
@@ -30,11 +31,20 @@ object MountedLivingEntityRenderer {
partialTicks: Float,
i: Float
) {
val vehicle = entity.vehicle
if (entity.vehicle !is Rideable) return
val matrix = stack.last().pose()
val delegate = pokemon.delegate as PokemonClientDelegate
val locator = delegate.locatorStates[delegate.getSeatLocator(entity)]
if (vehicle is OrientationControllable) {
val vehicleController = vehicle.orientationController
if (vehicleController.isActive() && vehicleController.orientation != null) {
vehicleController.tick()
}
}
//Positions entity
if (locator != null) {
MountedPokemonAnimationRenderController.setup(pokemon, partialTicks)
@@ -143,8 +143,8 @@ object CobblemonModelPredicateRegistry {
aprijuice.forEach { aprijuice ->
ItemProperties.register(aprijuice, cobblemonResource("aprijuice_quality")) { stack, world, entity, seed ->
val rideBoostsComponent = stack.get(CobblemonItemComponents.RIDE_BOOST) ?: return@register 0.0f
val quality = rideBoostsComponent.getQuality()
val flavourComponent = stack.get(CobblemonItemComponents.FLAVOUR) ?: return@register 0.0f
val quality = flavourComponent.getQuality()
return@register when (quality) {
CookingQuality.LOW -> 0.0f
@@ -0,0 +1,73 @@
/*
* 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.client.render.models.blockbench.pokemon.gen1
import com.cobblemon.mod.common.client.render.models.blockbench.animation.QuadrupedWalkAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class ArcanineModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame, QuadrupedFrame {
override val rootPart = root.registerChildWithAllChildren("arcanine")
override val head = getPart("head")
override val foreLeftLeg = getPart("left_shoulder")
override val foreRightLeg = getPart("right_shoulder")
override val hindLeftLeg = getPart("left_thigh")
override val hindRightLeg = getPart("right_thigh")
override var portraitScale = 1.37F
override var portraitTranslation = Vec3(-0.58, 1.21, 0.0)
override var profileScale = 0.58F
override var profileTranslation = Vec3(0.14, 0.92, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("arcanine", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("arcanine", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("arcanine", "idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("arcanine", "idle"),
QuadrupedWalkAnimation(this)
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("arcanine", "faint") else null
}
@@ -32,7 +32,7 @@ class SquirtleModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override var portraitTranslation = Vec3(-0.26, -0.21, 0.0)
override var profileScale = 0.78F
override var profileTranslation = Vec3(0.0, 0.57, 0.0)
override var profileTranslation = Vec3(-0.04, 0.57, 0.0)
lateinit var sleep: CobblemonPose
lateinit var standing: CobblemonPose
@@ -0,0 +1,93 @@
/*
* 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.client.render.models.blockbench.pokemon.gen1
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import com.cobblemon.mod.common.util.isInWater
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class TentacruelModel(root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("tentacruel")
override var portraitScale = 1.3F
override var portraitTranslation = Vec3(-0.3, 1.8, 0.0)
override var profileScale = 0.55F
override var profileTranslation = Vec3(0.0, 1.1, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var swim: CobblemonPose
lateinit var float: CobblemonPose
lateinit var sleep: CobblemonPose
lateinit var watersleep: CobblemonPose
override fun registerPoses() {
val blink = quirk { bedrockStateful("tentacruel", "blink")}
standing = registerPose(
poseName = "standing",
poseType = PoseType.STAND,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("tentacruel", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseType = PoseType.WALK,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("tentacruel", "ground_idle")
//bedrock("tentacruel", "ground_walk")
)
)
float = registerPose(
poseName = "float",
poseTypes = UI_POSES + PoseType.FLOAT,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("tentacruel", "water_idle")
)
)
swim = registerPose(
poseName = "swim",
poseType = PoseType.SWIM,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("tentacruel", "water_swim")
)
)
sleep = registerPose(
poseName = "sleep",
poseType = PoseType.SLEEP,
condition = { !it.isInWater },
animations = arrayOf(bedrock("tentacruel", "sleep"))
)
watersleep = registerPose(
poseName = "watersleep",
poseType = PoseType.SLEEP,
condition = { it.isInWater },
animations = arrayOf(bedrock("tentacruel", "water_sleep"))
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("tentacruel", "faint") else null
}
@@ -0,0 +1,61 @@
/*
* 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.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class ForretressModel(root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("forretress")
override var portraitScale = 1.65F
override var portraitTranslation = Vec3(-0.3, 0.3, 0.0)
override var profileScale = 0.7F
override var profileTranslation = Vec3(0.0, 0.8, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
lateinit var sleep: Pose
override fun registerPoses() {
val blink = quirk { bedrockStateful("forretress", "blink")}
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("forretress", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("forretress", "ground_walk")
)
)
sleep = registerPose(
poseType = PoseType.SLEEP,
transformTicks = 10,
animations = arrayOf(bedrock("forretress", "sleep"))
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isNotPosedIn(sleep)) bedrockStateful("forretress", "faint") else null
}
@@ -0,0 +1,109 @@
/*
* 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.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.sineFunction
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class HeracrossModel (root: ModelPart) : PokemonPosableModel(root), BipedFrame, BimanualFrame, BiWingedFrame {
override val rootPart = root.registerChildWithAllChildren("heracross")
override val leftArm = getPart("arm_right")
override val rightArm = getPart("arm_left")
override val leftLeg = getPart("leg_right")
override val rightLeg = getPart("leg_left")
override val leftWing = getPart("wing_right")
override val rightWing = getPart("wing_left")
override var portraitScale = 1.6F
override var portraitTranslation = Vec3(-0.2, 0.37, 0.0)
override var profileScale = 0.7F
override var profileTranslation = Vec3(-0.02, 0.64, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var hovering: CobblemonPose
lateinit var flying: CobblemonPose
override fun registerPoses() {
val blink = quirk { bedrockStateful("heracross", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES - PoseType.HOVER,
quirks = arrayOf(blink),
transformedParts = arrayOf(
leftWing.createTransformation().withVisibility(visibility = false),
rightWing.createTransformation().withVisibility(visibility = false)
),
animations = arrayOf(
bedrock("heracross", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES - PoseType.FLY,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("heracross", "ground_idle"),
BipedWalkAnimation(this,0.6F, 1F),
BimanualSwingAnimation(this, 0.6F, 1F)
)
)
hovering = registerPose(
poseName = "hovering",
poseType = PoseType.HOVER,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("heracross", "air_idle"),
WingFlapIdleAnimation(this,
flapFunction = sineFunction(verticalShift = 35F.toRadians(), period = 0.1F, amplitude = 0.6F),
timeVariable = { state, _, _ -> state.animationSeconds },
axis = ModelPartTransformation.Y_AXIS
)
)
)
flying = registerPose(
poseName = "flying",
poseType = PoseType.FLY,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("heracross", "air_idle"),
WingFlapIdleAnimation(this,
flapFunction = sineFunction(verticalShift = 35F.toRadians(), period = 0.1F, amplitude = 0.6F),
timeVariable = { state, _, _ -> state.animationSeconds },
axis = ModelPartTransformation.Y_AXIS
)
),
transformedParts = arrayOf(
rootPart.createTransformation().addRotationDegrees(ModelPartTransformation.X_AXIS, 45)
)
)
}
}
@@ -0,0 +1,125 @@
/*
* 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.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.isBattling
import com.cobblemon.mod.common.util.isUnderWater
import com.cobblemon.mod.common.util.isInWater
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class LanturnModel (root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("lanturn")
override var portraitScale = 1.7F
override var portraitTranslation = Vec3(-0.65, -0.7, 0.0)
override var profileScale = 0.6F
override var profileTranslation = Vec3(0.0, 0.7, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var floating: CobblemonPose
lateinit var swimming: CobblemonPose
lateinit var sleep: CobblemonPose
lateinit var watersleep: CobblemonPose
lateinit var battleidle: CobblemonPose
lateinit var waterbattleidle: CobblemonPose
// override val cryAnimation = CryProvider { bedrockStateful("lanturn", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("lanturn", "blink")}
sleep = registerPose(
poseName = "sleeping",
poseType = PoseType.SLEEP,
condition = { !it.isInWater },
animations = arrayOf(bedrock("lanturn", "sleep"))
)
watersleep = registerPose(
poseName = "water_sleeping",
poseType = PoseType.SLEEP,
condition = { it.isInWater },
animations = arrayOf(bedrock("lanturn", "water_sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.UI_POSES + PoseType.STAND,
transformTicks = 10,
condition = { !it.isBattling && !it.isInWater && !it.isUnderWater},
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("lanturn", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
transformTicks = 10,
poseType = PoseType.WALK,
condition = { !it.isInWater && !it.isUnderWater},
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("lanturn", "ground_walk")
)
)
floating = registerPose(
poseName = "floating",
transformTicks = 10,
poseType = PoseType.FLOAT,
condition = { it.isInWater },
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("lanturn", "water_idle")
)
)
swimming = registerPose(
poseName = "swimming",
transformTicks = 10,
condition = { it.isInWater },
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("lanturn", "water_swim"),
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling && !it.isInWater },
animations = arrayOf(
bedrock("lanturn", "ground_battle_idle")
)
)
waterbattleidle = registerPose(
poseName = "water_battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling && it.isInWater },
animations = arrayOf(
bedrock("lanturn", "water_battle_idle")
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, battleidle, sleep)) bedrockStateful("lanturn", "faint") else if (state.isPosedIn( waterbattleidle, watersleep, floating, swimming )) bedrockStateful("lanturn", "water_faint") else null
}
@@ -0,0 +1,87 @@
/*
* 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.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import com.cobblemon.mod.common.util.isBattling
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class SteelixModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("steelix")
override val head = getPart("head")
override var portraitScale = 0.7F
override var portraitTranslation = Vec3(-0.7, 1.8, 0.0)
override var profileScale = 0.4F
override var profileTranslation = Vec3(-0.1, 1.1, -6.0)
lateinit var standing: Pose
lateinit var walking: Pose
lateinit var sleep: Pose
lateinit var battleidle: Pose
override val cryAnimation = CryProvider { bedrockStateful("steelix", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("steelix", "blink") }
val jitter = quirk { bedrockStateful("steelix", "quirk_jawjitter") }
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("steelix", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
transformTicks = 0,
condition = { !it.isBattling },
quirks = arrayOf(blink, jitter),
animations = arrayOf(
singleBoneLook(),
bedrock("steelix", "ground_idle")
)
)
walking = registerPose(
poseName = "walking",
poseTypes = MOVING_POSES,
transformTicks = 0,
quirks = arrayOf(blink, jitter),
animations = arrayOf(
singleBoneLook(),
bedrock("steelix", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 0,
quirks = arrayOf(blink, jitter),
condition = { it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("steelix", "battle_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walking, battleidle, sleep)) bedrockStateful("steelix", "faint") else null
}
@@ -0,0 +1,67 @@
/*
* 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.client.render.models.blockbench.pokemon.gen3
import com.cobblemon.mod.common.client.render.models.blockbench.animation.QuadrupedWalkAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.QuadrupedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class CameruptModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, QuadrupedFrame {
override val rootPart = root.registerChildWithAllChildren("camerupt")
override val head = getPart("neck")
override val foreLeftLeg = getPart("leg_front_left")
override val foreRightLeg = getPart("leg_front_right")
override val hindLeftLeg = getPart("leg_back_left")
override val hindRightLeg = getPart("leg_back_right")
override var portraitScale = 1.2F
override var portraitTranslation = Vec3(-0.85, 0.1, 0.0)
override var profileScale = 0.55F
override var profileTranslation = Vec3(0.0, 0.85, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
override fun registerPoses() {
val blink = quirk { bedrockStateful("camerupt", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.UI_POSES + PoseType.STATIONARY_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("camerupt", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
QuadrupedWalkAnimation(this, periodMultiplier = 1.1F),
singleBoneLook(),
bedrock("camerupt", "ground_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("camerupt", "faint") else null
}
@@ -0,0 +1,58 @@
/*
* 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.client.render.models.blockbench.pokemon.gen3
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class RayquazaModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("rayquaza")
override val head = getPart("head")
override var portraitScale = 1.5F
override var portraitTranslation = Vec3(-1.85, 3.5, 0.0)
override var profileScale = 0.4F
override var profileTranslation = Vec3(0.0, 1.3, -6.0)
lateinit var standing: Pose
lateinit var walk: Pose
override fun registerPoses() {
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
animations = arrayOf(
singleBoneLook(),
bedrock("rayquaza", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
animations = arrayOf(
singleBoneLook(),
bedrock("rayquaza", "ground_idle")
//bedrock("rayquaza", "ground_walk")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("rayquaza", "faint") else null
}
@@ -0,0 +1,87 @@
/*
* 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.client.render.models.blockbench.pokemon.gen5
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WaveAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WaveSegment
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.sineFunction
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class BasculinModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("basculin")
override val head = getPart("head")
override var portraitScale = 2.0F
override var portraitTranslation = Vec3(-0.3, -1.2, 0.0)
override var profileScale = 0.8F
override var profileTranslation = Vec3(0.0, 0.5, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
val tail = getPart("tail_fin")
val wtail = WaveSegment(tail, 7F)
override val cryAnimation = CryProvider { bedrockStateful("basculin", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("basculin", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("basculin", "water_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("basculin", "water_idle"),
WaveAnimation(
waveFunction = sineFunction(
period = 8F,
amplitude = 0.4F
),
basedOnLimbSwing = true,
oscillationsScalar = 8F,
head = head,
rotationAxis = ModelPartTransformation.Y_AXIS,
motionAxis = ModelPartTransformation.X_AXIS,
headLength = 0.1F,
segments = arrayOf(
wtail
)
)
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("basculin", "faint") else null
}
@@ -0,0 +1,81 @@
/*
* 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.client.render.models.blockbench.pokemon.gen5
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.isBattling
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class DarmanitanModel (root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("darmanitan")
override var portraitScale = 0.96F
override var portraitTranslation = Vec3(-0.35, 0.71, 0.0)
override var profileScale = 0.57F
override var profileTranslation = Vec3(-0.11, 0.73, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var sleep: CobblemonPose
lateinit var battleidle: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("darmanitan", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("darmanitan", "blink") }
val quirk = quirk(secondsBetweenOccurrences = 15F to 100F) { bedrockStateful("darmanitan", "quirk") }
sleep = registerPose(
poseName = "sleeping",
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("darmanitan", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink, quirk),
condition = { !it.isBattling },
animations = arrayOf(
bedrock("darmanitan", "ground_idle")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink, quirk),
condition = { it.isBattling },
animations = arrayOf(
bedrock("darmanitan", "battle_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("darmanitan", "ground_walk")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("darmanitan", "faint") else null
}
@@ -0,0 +1,71 @@
/*
* 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.client.render.models.blockbench.pokemon.gen5
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.isBattling
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class DarmanitanZenModel (root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("darmanitan")
override var portraitScale = 1.05F
override var portraitTranslation = Vec3(-0.28, 0.48, 0.0)
override var profileScale = 0.63F
override var profileTranslation = Vec3(0.0, 0.69, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var sleep: CobblemonPose
lateinit var battleIdle: CobblemonPose
override fun registerPoses() {
sleep = registerPose(
poseName = "sleeping",
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("darmanitan_zen", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
condition = { !it.isBattling },
animations = arrayOf(
bedrock("darmanitan_zen", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
animations = arrayOf(
bedrock("darmanitan_zen", "ground_walk")
)
)
battleIdle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
condition = { it.isBattling },
animations = arrayOf(
bedrock("darmanitan_zen", "battle_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("darmanitan_zen", "faint") else null
}
@@ -26,11 +26,11 @@ class ChespinModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, B
override val leftLeg = getPart("leg_left")
override val rightLeg = getPart("leg_right")
override var portraitScale = 2.03F
override var portraitTranslation = Vec3(-0.12, -0.44, 0.0)
override var portraitScale = 2.7F
override var portraitTranslation = Vec3(-0.15, -1.2, 0.0)
override var profileScale = 0.77F
override var profileTranslation = Vec3(0.0, 0.6, 0.0)
override var profileScale = 0.85F
override var profileTranslation = Vec3(0.0, 0.5, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
@@ -28,11 +28,11 @@ class FroakieModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame, Bi
override val rightLeg = getPart("leg_right")
override val leftLeg = getPart("leg_left")
override var portraitScale = 1.86F
override var portraitTranslation = Vec3(-0.25, -0.51, 0.0)
override var portraitScale = 2.0F
override var portraitTranslation = Vec3(-0.2, -0.5, 0.0)
override var profileScale = 0.75F
override var profileTranslation = Vec3(0.0, 0.56, 0.0)
override var profileScale = 0.8F
override var profileTranslation = Vec3(0.0, 0.5, 0.0)
lateinit var sleep: Pose
lateinit var standing: Pose
@@ -0,0 +1,87 @@
/*
* 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.client.render.models.blockbench.pokemon.gen7
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class CutieflyModel(root: ModelPart) : PokemonPosableModel(root){
override val rootPart = root.registerChildWithAllChildren("cutiefly")
override var portraitScale = 2.4F
override var portraitTranslation = Vec3(-0.3, 1.5, 0.0)
override var profileScale = 0.7F
override var profileTranslation = Vec3(0.0, 1.2, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var sleep: CobblemonPose
lateinit var shoulderLeft: CobblemonPose
lateinit var shoulderRight: CobblemonPose
val shoulderOffset = 12.5
override fun registerPoses() {
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("cutiefly", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
animations = arrayOf(
bedrock("cutiefly", "ground_idle")
),
transformedParts = arrayOf(rootPart.createTransformation().addPosition(ModelPartTransformation.Y_AXIS, -12F))
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
animations = arrayOf(
bedrock("cutiefly", "ground_walk"),
),
transformedParts = arrayOf(rootPart.createTransformation().addPosition(ModelPartTransformation.Y_AXIS, -12F))
)
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
animations = arrayOf(
bedrock("cutiefly", "ground_idle")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(shoulderOffset, -4, 0)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
animations = arrayOf(
bedrock("cutiefly", "ground_idle")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(-shoulderOffset, -4, 0)
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("cutiefly", "faint") else null
}
@@ -0,0 +1,76 @@
/*
* 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.client.render.models.blockbench.pokemon.gen7
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class DhelmiseModel(root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("dhelmise")
override var portraitScale = 1.1F
override var portraitTranslation = Vec3(-0.5, 2.7, 0.0)
override var profileScale = 0.35F
override var profileTranslation = Vec3(0.0, 1.35, 0.0)
lateinit var sleep: Pose
lateinit var standing: Pose
lateinit var walk: Pose
lateinit var float: Pose
lateinit var swim: Pose
override fun registerPoses() {
sleep = registerPose(
poseType = PoseType.SLEEP,
transformTicks = 10,
animations = arrayOf(bedrock("dhelmise", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
animations = arrayOf(
bedrock("dhelmise", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
animations = arrayOf(
bedrock("dhelmise", "ground_walk")
)
)
float = registerPose(
poseName = "float",
poseTypes = PoseType.UI_POSES + PoseType.FLOAT,
animations = arrayOf(
bedrock("dhelmise", "water_idle")
)
)
swim = registerPose(
poseName = "swim",
poseType = PoseType.SWIM,
animations = arrayOf(
bedrock("dhelmise", "water_swim")
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isNotPosedIn(sleep)) bedrockStateful("dhelmise", "faint") else null
}
@@ -0,0 +1,86 @@
/*
* 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.client.render.models.blockbench.pokemon.gen7
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class MimikyuModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("mimikyu")
override val head = getPart("head")
override var portraitScale = 2.5F
override var portraitTranslation = Vec3(0.0, -2.3, 0.0)
override var profileScale = 0.8F
override var profileTranslation = Vec3(0.0, 0.5, 0.0)
lateinit var shoulderLeft: Pose
lateinit var shoulderRight: Pose
lateinit var standing: Pose
lateinit var walk: Pose
override val cryAnimation = CryProvider { bedrockStateful("mimikyu", "cry") }
override fun registerPoses() {
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
animations = arrayOf(
bedrock("mimikyu", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
animations = arrayOf(
bedrock("mimikyu", "ground_idle")
//bedrock("mimikyu", "ground_walk")
)
)
val shoulderOffset = 0.3
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
animations = arrayOf(
bedrock("mimikyu", "shoulder_left")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
animations = arrayOf(
bedrock("mimikyu", "shoulder_right")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("mimikyu", "faint") else null
}
@@ -0,0 +1,58 @@
/*
* 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.client.render.models.blockbench.pokemon.gen7
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class RibombeeModel(root: ModelPart) : PokemonPosableModel(root){
override val rootPart = root.registerChildWithAllChildren("ribombee")
override var portraitScale = 1.8F
override var portraitTranslation = Vec3(0.0, 0.95, 0.0)
override var profileScale = 0.5F
override var profileTranslation = Vec3(0.1, 0.9, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
lateinit var sleep: Pose
override fun registerPoses() {
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("ribombee", "sleep"))
)
standing = registerPose(
poseName = "idle",
poseTypes = STATIONARY_POSES + UI_POSES,
animations = arrayOf(
bedrock("ribombee", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
animations = arrayOf(
bedrock("ribombee", "ground_walk")
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("ribombee", "faint") else null
}
@@ -0,0 +1,62 @@
/*
* 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.client.render.models.blockbench.pokemon.gen8
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class BasculegionModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("basculegion")
override val head = getPart("head")
override var portraitScale = 1.4F
override var portraitTranslation = Vec3(-1.1, -0.5, 0.0)
override var profileScale = 0.5F
override var profileTranslation = Vec3(0.0, 0.8, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("basculegion", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("basculegion", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("basculegion", "water_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("basculegion", "water_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("basculegion", "faint") else null
}
@@ -0,0 +1,80 @@
/*
* 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.client.render.models.blockbench.pokemon.gen8
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class DragapultModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("dragapult")
override val head = getPart("head")
override var portraitScale = 1.79F
override var portraitTranslation = Vec3(-0.62, 1.47, 0.0)
override var profileScale = 0.45F
override var profileTranslation = Vec3(0.0, 0.73, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var ui_poses: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("dragapult", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("dragapult", "blink") }
ui_poses = registerPose(
poseName = "ui_poses",
poseTypes = PoseType.UI_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("dragapult", "ground_idle")
)
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STANDING_POSES,
quirks = arrayOf(blink),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.Y_AXIS, -16)
),
animations = arrayOf(
singleBoneLook(),
bedrock("dragapult", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.Y_AXIS, -16)
),
animations = arrayOf(
singleBoneLook(),
bedrock("dragapult", "ground_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("dragapult", "faint") else null
}
@@ -0,0 +1,81 @@
/*
* 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.client.render.models.blockbench.pokemon.gen8
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.isBattling
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class RabootModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("raboot")
override val head = getPart("head")
override var portraitScale = 2.5F
override var portraitTranslation = Vec3(-0.15, 0.3, 0.0)
override var profileScale = 0.63F
override var profileTranslation = Vec3(0.0, 0.86, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var battleIdle: CobblemonPose
lateinit var sleep: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("raboot", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("raboot", "blink") }
val hipQuirk = quirk { bedrockStateful("raboot", "hip_quirk") }
val sleepQuirk = quirk { bedrockStateful("raboot", "sleep_ear_quirk") }
sleep = registerPose(
poseName = "sleep",
quirks = arrayOf(sleepQuirk),
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("raboot", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
condition = { !it.isBattling },
quirks = arrayOf(blink, hipQuirk),
animations = arrayOf(
singleBoneLook(),
bedrock("raboot", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("raboot", "ground_walk")
)
)
battleIdle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
condition = { it.isBattling },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("raboot", "battle_idle")
)
)
}
}
@@ -0,0 +1,67 @@
/*
* 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.client.render.models.blockbench.pokemon.gen9
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class GrafaiaiModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("grafaiai")
override val head = getPart("head")
override var portraitScale = 1.5F
override var portraitTranslation = Vec3(-0.1, 0.05, 0.0)
override var profileScale = 0.8F
override var profileTranslation = Vec3(0.0, 0.5, 0.0)
lateinit var standing: Pose
lateinit var walking: Pose
lateinit var sleeping: Pose
override val cryAnimation = CryProvider { bedrockStateful("grafaiai", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("grafaiai", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("grafaiai", "ground_idle")
)
)
walking = registerPose(
poseName = "walking",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("grafaiai", "ground_walk")
)
)
sleeping = registerPose(
poseName = "sleeping",
poseType = PoseType.SLEEP,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("grafaiai", "sleep")
)
)
}
}
@@ -0,0 +1,91 @@
/*
* 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.client.render.models.blockbench.pokemon.gen9
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class ShroodleModel (root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("shroodle")
override var portraitScale = 2.5F
override var portraitTranslation = Vec3(0.0, -2.3, 0.0)
override var profileScale = 0.9F
override var profileTranslation = Vec3(0.0, 0.4, 0.0)
lateinit var standing: Pose
lateinit var walking: Pose
lateinit var sleeping: Pose
lateinit var shoulderLeft: Pose
lateinit var shoulderRight: Pose
val shoulderOffset = -1
override val cryAnimation = CryProvider { bedrockStateful("shroodle", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("shroodle", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("shroodle", "ground_idle")
)
)
walking = registerPose(
poseName = "walking",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("shroodle", "ground_walk")
)
)
sleeping = registerPose(
poseName = "sleeping",
poseType = PoseType.SLEEP,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("shroodle", "sleep")
)
)
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("shroodle", "ground_idle")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("shroodle", "ground_idle")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, -shoulderOffset)
)
)
}
}
@@ -250,6 +250,7 @@ object VaryingModelRepository {
inbuilt("machoke", ::MachokeModel)
inbuilt("machamp", ::MachampModel)
inbuilt("arbok", ::ArbokModel)
inbuilt("arcanine", ::ArcanineModel)
inbuilt("chansey", ::ChanseyModel)
inbuilt("cubone", ::CuboneModel)
inbuilt("ditto", ::DittoModel)
@@ -293,8 +294,10 @@ object VaryingModelRepository {
inbuilt("rapidash", ::RapidashModel)
inbuilt("sandshrew", ::SandshrewModel)
inbuilt("sandslash", ::SandslashModel)
inbuilt("steelix", ::SteelixModel)
inbuilt("tangela", ::TangelaModel)
inbuilt("tentacool", ::TentacoolModel)
inbuilt("tentacruel", ::TentacruelModel)
inbuilt("venomoth", ::VenomothModel)
inbuilt("venonat", ::VenonatModel)
inbuilt("weezing", ::WeezingModel)
@@ -310,6 +313,7 @@ object VaryingModelRepository {
inbuilt("wooper", ::WooperModel)
inbuilt("wooper_paldean", ::WooperPaldeanModel)
inbuilt("yanma", ::YanmaModel)
inbuilt("rayquaza", ::RayquazaModel)
inbuilt("bibarel", ::BibarelModel)
inbuilt("bidoof", ::BidoofModel)
inbuilt("buneary", ::BunearyModel)
@@ -317,10 +321,12 @@ object VaryingModelRepository {
inbuilt("mamoswine", ::MamoswineModel)
inbuilt("piplup", ::PiplupModel)
inbuilt("yanmega", ::YanmegaModel)
inbuilt("basculin", ::BasculinModel)
inbuilt("emolga", ::EmolgaModel)
inbuilt("bounsweet", ::BounsweetModel)
inbuilt("dartrix", ::DartrixModel)
inbuilt("decidueye", ::DecidueyeModel)
inbuilt("mimikyu", ::MimikyuModel)
inbuilt("naganadel", ::NaganadelModel)
inbuilt("poipole", ::PoipoleModel)
inbuilt("rowlet", ::RowletModel)
@@ -338,6 +344,7 @@ object VaryingModelRepository {
inbuilt("nacli", :: NacliModel)
inbuilt("naclstack", :: NaclstackModel)
inbuilt("garganacl", ::GarganaclModel)
inbuilt("dhelmise", :: DhelmiseModel)
inbuilt("alcremie", :: AlcremieModel)
inbuilt("milcery", :: MilceryModel)
inbuilt("turtwig", :: TurtwigModel)
@@ -355,6 +362,7 @@ object VaryingModelRepository {
inbuilt("quilladin", :: QuilladinModel)
inbuilt("chesnaught", :: ChesnaughtModel)
inbuilt("pineco", :: PinecoModel)
inbuilt("forretress", :: ForretressModel)
inbuilt("lotad", :: LotadModel)
inbuilt("lombre", :: LombreModel)
inbuilt("ludicolo", :: LudicoloModel)
@@ -390,6 +398,7 @@ object VaryingModelRepository {
inbuilt("grookey", ::GrookeyModel)
inbuilt("thwackey", ::ThwackeyModel)
inbuilt("rillaboom", ::RillaboomModel)
inbuilt("raboot", ::RabootModel)
inbuilt("oshawott", ::OshawottModel)
inbuilt("dewott", ::DewottModel)
inbuilt("samurott", ::SamurottModel)
@@ -410,6 +419,7 @@ object VaryingModelRepository {
inbuilt("tandemaus", ::TandemausModel)
inbuilt("maushold", ::MausholdModel)
inbuilt("mausholdfour", ::MausholdfourModel)
inbuilt("lanturn", ::LanturnModel)
inbuilt("chingling", ::ChinglingModel)
inbuilt("chimecho", ::ChimechoModel)
inbuilt("fidough", ::FidoughModel)
@@ -425,6 +435,8 @@ object VaryingModelRepository {
inbuilt("flittle", ::FlittleModel)
inbuilt("surskit", ::SurskitModel)
inbuilt("masquerain", ::MasquerainModel)
inbuilt("cutiefly", ::CutieflyModel)
inbuilt("ribombee", ::RibombeeModel)
inbuilt("carnivine", ::CarnivineModel)
inbuilt("falinks", ::FalinksModel)
inbuilt("stufful", ::StuffulModel)
@@ -457,6 +469,7 @@ object VaryingModelRepository {
inbuilt("luxio", ::LuxioModel)
inbuilt("luxray", ::LuxrayModel)
inbuilt("numel", ::NumelModel)
inbuilt("camerupt", ::CameruptModel)
inbuilt("roggenrola", ::RoggenrolaModel)
inbuilt("boldore", ::BoldoreModel)
inbuilt("gigalith", ::GigalithModel)
@@ -472,6 +485,8 @@ object VaryingModelRepository {
inbuilt("bunnelby", ::BunnelbyModel)
inbuilt("arrokuda", ::ArrokudaModel)
inbuilt("barraskewda", ::BarraskewdaModel)
inbuilt("shroodle", ::ShroodleModel)
inbuilt("grafaiai", ::GrafaiaiModel)
inbuilt("squawkabilly", ::SquawkabillyModel)
inbuilt("ponyta_galarian", ::PonytaGalarianModel)
inbuilt("rapidash_galarian", ::RapidashGalarianModel)
@@ -548,6 +563,7 @@ object VaryingModelRepository {
inbuilt("dracozolt", ::DracozoltModel)
inbuilt("shieldon", ::ShieldonModel)
inbuilt("cranidos", ::CranidosModel)
inbuilt("basculegion", ::BasculegionModel)
inbuilt("tyrunt", ::TyruntModel)
inbuilt("anorith", ::AnorithModel)
inbuilt("armaldo", ::ArmaldoModel)
@@ -574,6 +590,8 @@ object VaryingModelRepository {
inbuilt("petilil_hisui_bias", ::PetililHisuiBiasModel)
inbuilt("lilligant_hisuian", ::LilligantHisuianModel)
inbuilt("darumaka", ::DarumakaModel)
inbuilt("darmanitan", ::DarmanitanModel)
inbuilt("darmanitan_zen", ::DarmanitanZenModel)
inbuilt("turtonator", ::TurtonatorModel)
inbuilt("cufant", ::CufantModel)
inbuilt("copperajah", ::CopperajahModel)
@@ -588,6 +606,7 @@ object VaryingModelRepository {
inbuilt("beartic", ::BearticModel)
inbuilt("dreepy", ::DreepyModel)
inbuilt("drakloak", ::DrakloakModel)
inbuilt("dragapult", ::DragapultModel)
inbuilt("diglett_alolan", ::DiglettAlolanModel)
inbuilt("dugtrio_alolan", ::DugtrioAlolanModel)
inbuilt("makuhita", ::MakuhitaModel)
@@ -602,6 +621,7 @@ object VaryingModelRepository {
inbuilt("sliggoo_hisuian", ::SliggooHisuianModel)
inbuilt("goodra", ::GoodraModel)
inbuilt("goodra_hisuian", ::GoodraHisuianModel)
inbuilt("heracross", ::HeracrossModel)
inbuilt("salandit", ::SalanditModel)
inbuilt("salazzle", ::SalazzleModel)
inbuilt("jangmo-o", ::JangmoOModel)
@@ -9,6 +9,8 @@
package com.cobblemon.mod.common.client.tooltips
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.text.blue
import com.cobblemon.mod.common.api.text.gray
import com.cobblemon.mod.common.item.AprijuiceItem
import com.cobblemon.mod.common.util.lang
import net.minecraft.network.chat.Component
@@ -18,11 +20,11 @@ object AprijuiceTooltipGenerator : TooltipGenerator() {
override fun generateAdditionalTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
if (stack.item !is AprijuiceItem) return null
val rideBoostComponent = stack.get(CobblemonItemComponents.RIDE_BOOST) ?: return null
val flavourComponent = stack.get(CobblemonItemComponents.FLAVOUR) ?: return null
val resultLines = mutableListOf<Component>()
val quality = rideBoostComponent.getQuality()
val quality = flavourComponent.getQuality()
resultLines.add(lang("cooking.cooking_quality", quality.getLang()))
SeasoningTooltipGenerator.generateAdditionalTooltip(stack, lines)
@@ -9,10 +9,14 @@
package com.cobblemon.mod.common.client.tooltips
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.text.blue
import com.cobblemon.mod.common.api.text.gray
import com.cobblemon.mod.common.item.AprijuiceItem
import com.cobblemon.mod.common.util.lang
import net.minecraft.network.chat.Component
import net.minecraft.world.item.ItemStack
object RecipeSeasoningAbsorptionTooltipGenerator : TooltipGenerator() {
object RecipeSeasoningAbsorbtionTooltipGenerator : TooltipGenerator() {
override fun generateCategoryTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
// Skip if this is a crafting result preview. Vera wanted to be able to give extra context to things not fully crafted for added guidance in crafting UIs
if (stack.get(CobblemonItemComponents.CRAFTED) == true) {
@@ -11,7 +11,9 @@ package com.cobblemon.mod.common.client.tooltips
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.cooking.Seasonings
import com.cobblemon.mod.common.api.text.blue
import com.cobblemon.mod.common.api.text.gray
import com.cobblemon.mod.common.util.lang
import net.minecraft.core.component.DataComponents
import net.minecraft.network.chat.Component
import net.minecraft.world.item.ItemStack
@@ -22,7 +24,6 @@ object SeasoningTooltipGenerator : TooltipGenerator() {
val food = stack.get(CobblemonItemComponents.FOOD)
val baitEffects = stack.get(CobblemonItemComponents.BAIT_EFFECTS)?.effects
val mobEffects = stack.get(CobblemonItemComponents.MOB_EFFECTS)?.mobEffects
val boosts = stack.get(CobblemonItemComponents.RIDE_BOOST)?.boosts
val result = mutableListOf<Component>()
@@ -54,10 +55,6 @@ object SeasoningTooltipGenerator : TooltipGenerator() {
// Bait Effects
if (!baitEffects.isNullOrEmpty()) result.add(lang("seasoning_bait_effect_header").blue())
if (!boosts.isNullOrEmpty()) {
result.add(lang("seasoning_ride_boosts_info_header").blue())
}
}
return if (result.isNotEmpty()) result else null
@@ -69,9 +66,8 @@ object SeasoningTooltipGenerator : TooltipGenerator() {
val food = stack.get(CobblemonItemComponents.FOOD)
val baitEffects = stack.get(CobblemonItemComponents.BAIT_EFFECTS)?.effects
val mobEffects = stack.get(CobblemonItemComponents.MOB_EFFECTS)?.mobEffects
val rideBoosts = stack.get(CobblemonItemComponents.RIDE_BOOST)?.boosts
if (!isSeasoningIngredient && flavors == null && food == null && baitEffects == null && mobEffects == null && rideBoosts == null) return null // exit early if there is nothing to show to save time
if (!isSeasoningIngredient && flavors == null && food == null && baitEffects == null && mobEffects == null) return null // exit early if there is nothing to show to save time
val result = mutableListOf<Component>()
@@ -99,9 +95,6 @@ object SeasoningTooltipGenerator : TooltipGenerator() {
result.addAll(generateAdditionalBaitEffectTooltip(stack))
}
// Ride Boosts
result.addAll(generateAdditionalRideBoostsTooltip(stack))
return if (result.isNotEmpty()) result else null
}
}
@@ -44,7 +44,6 @@ val foodInfoSubHeader by lazy { lang("seasoning_food_info_header").blue() }
val mobEffectSeasoningHeader by lazy { lang("item_class.mob_effect_seasoning").blue() }
val mobEffectHeader by lazy { lang("seasoning_mob_effect_header").gray() }
val mobEffectInfoSubHeader by lazy { lang("seasoning_mob_effect_info_header").blue() }
val rideBoostSeasoningHeader by lazy { lang("seasoning_ride_boosts_info_header").blue() }
private fun recipeUsesProcessor(stack: ItemStack, processorType: String): Boolean {
val level = Minecraft.getInstance().level ?: return false
@@ -262,27 +261,6 @@ fun generateAdditionalBaitEffectTooltip(stack: ItemStack): MutableList<Component
return resultLines
}
fun generateAdditionalRideBoostsTooltip(stack: ItemStack): MutableList<Component> {
val boosts = stack.get(CobblemonItemComponents.RIDE_BOOST)?.boosts
?: return mutableListOf()
val resultLines = mutableListOf<Component>()
resultLines.add(rideBoostSeasoningHeader)
for ((stat, value) in boosts) {
val statName = stat.displayName.also { it.style = it.style.withColor(stat.flavour.colour) }
val valueText = if (value < 0) {
Component.literal("$value").red()
} else {
Component.literal("+$value").green()
}
resultLines.add(lang("seasoning_ride_boost_entry", statName, valueText))
}
return resultLines
}
private fun getRomanNumeral(number: Int): String {
if (number <= 0) return number.toString()
@@ -327,16 +327,17 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
val middleNode = path.getNode(i - 1)
val nextNode = path.getNode(i)
val directionToMiddle = middleNode.asBlockPos().subtract(firstNode.asBlockPos()).toVec3d().normalize()
val nodeType = firstNode.type
if (nodeType != middleNode.type || nodeType != nextNode.type || nodeType == PathType.WALKABLE) {
i++
continue
}
val directionToMiddle = middleNode.asBlockPos().subtract(firstNode.asBlockPos()).toVec3d().normalize()
val directionToEnd = nextNode.asBlockPos().subtract(middleNode.asBlockPos()).toVec3d().normalize()
// If we'd be making a big (greater than 45 degrees) turn by removing the middle node, that's a bit much, leave it alone.
if (acos(directionToMiddle.dot(directionToEnd)) > PI / 4) {
if (acos(directionToMiddle.dot(directionToEnd)) > PI / 3) {
i++
continue
}
@@ -75,7 +75,8 @@ import net.minecraft.world.phys.EntityHitResult
import net.minecraft.world.phys.Vec3
class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity>, world: Level) : FishingHook(type, world) {
class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity>, world: Level) :
FishingHook(type, world) {
var plannedSpawnAction: SpawnAction<*>? = null
@@ -775,10 +776,7 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
cause = spawnCause,
world = level() as ServerLevel,
pos = position().toBlockPos(),
influences = mutableListOf(
PlayerLevelRangeInfluence(player, TYPICAL_VARIATION),
bucketInfluence
)
influences = mutableListOf(PlayerLevelRangeInfluence(player, TYPICAL_VARIATION), bucketInfluence)
)
val result = spawner.calculateSpawnActionForPosition(
@@ -10,9 +10,11 @@ package com.cobblemon.mod.common.item
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.pot.CookingQuality
import com.cobblemon.mod.common.pokemon.Nature
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel
@@ -30,15 +32,22 @@ import net.minecraft.world.level.Level
class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)), PokemonSelectingItem {
override val bagItem = null
fun hasRideBoosts(stack: ItemStack): Boolean {
val rideBoostComponent = stack.get(CobblemonItemComponents.RIDE_BOOST)
return rideBoostComponent?.boosts?.isNotEmpty() == true
companion object {
const val DISLIKED_FLAVOUR_MULTIPLIER = 0.75F
const val LIKED_FLAVOUR_MULTIPLIER = 1.25F
const val STRONG_APRICORN_MULTIPLIER = 1.25F
const val WEAK_APRICORN_MULTIPLIER = 0.75F
const val TRIPLE_POINT_THRESHOLD = 30
const val DOUBLE_POINT_THRESHOLD = 15
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
val stack = user.getItemInHand(hand)
return if (!hasRideBoosts(stack)) {
val hasFlavour = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours?.any { it.value > 0 } == true
return if (!hasFlavour) {
// act like a drink :D
user.startUsingItem(hand)
InteractionResultHolder.consume(stack)
@@ -51,15 +60,15 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
}
override fun getName(stack: ItemStack): Component {
val rideBoostsComponent = stack.get(CobblemonItemComponents.RIDE_BOOST)
val hasBoosts = rideBoostsComponent?.boosts?.isNotEmpty() == true
val quality = rideBoostsComponent?.getQuality()
val flavourComponent = stack.get(CobblemonItemComponents.FLAVOUR)
val hasFlavour = flavourComponent?.flavours?.values?.any { it > 0 } == true
val quality = flavourComponent?.getQuality()
val baseNameKey = "item.cobblemon.aprijuice_${type.name.lowercase()}"
val prefixKey = when {
hasBoosts && quality == CookingQuality.HIGH -> "item.cobblemon.aprijuice.prefix.delicious"
hasBoosts && quality == CookingQuality.MEDIUM -> "item.cobblemon.aprijuice.prefix.tasty"
!hasBoosts -> "item.cobblemon.aprijuice.prefix.plain"
hasFlavour && quality == CookingQuality.HIGH -> "item.cobblemon.aprijuice.prefix.delicious"
hasFlavour && quality == CookingQuality.MEDIUM -> "item.cobblemon.aprijuice.prefix.tasty"
!hasFlavour -> "item.cobblemon.aprijuice.prefix.plain"
else -> null
}
@@ -70,16 +79,22 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
)
} else {
Component.translatable(baseNameKey)
} // todo if no boosts call it "Plain Red Aprijuice" or "Raw Red Aprijuice" maybe and have players able to drink it
} // todo if no flavor call it "Plain Red Aprijuice" or "Raw Red Aprijuice" maybe and have players able to drink it
}
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
val boosts = getBoosts(stack)
val boosts = getBoosts(stack, pokemon)
return boosts.isNotEmpty() && boosts.any { pokemon.canAddRideBoost(it.key) } && super.canUseOnPokemon(stack, pokemon)
}
fun getBoosts(stack: ItemStack): Map<RidingStat, Int> {
return stack.get(CobblemonItemComponents.RIDE_BOOST)?.boosts ?: emptyMap()
fun getBoosts(stack: ItemStack, pokemon: Pokemon): Map<RidingStat, Float> {
val flavours = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours ?: emptyMap()
return RidingStat.entries.associate { ridingStat ->
val flavour = ridingStat.flavour
val flavourValue = flavours[flavour]?.takeUnless { it == 0 } ?: return@associate (ridingStat to 0F)
val adjustedValue = calculateRidingBoostForFlavour(flavour, type, flavourValue, pokemon.nature)
ridingStat to adjustedValue
}.filter { it.value > 0 }
}
override fun applyToPokemon(
@@ -93,16 +108,46 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
pokemon.feedPokemon(1)
val boosts = getBoosts(stack)
pokemon.addRideBoosts(boosts.mapValues { it.value.toFloat() })
val boosts = getBoosts(stack, pokemon)
pokemon.addRideBoosts(boosts)
stack.consume(1, player)
return InteractionResultHolder.success(stack)
}
fun calculateRidingBoostForFlavour(flavour: Flavour, apricorn: Apricorn, value: Int, nature: Nature): Float {
val tasteMultiplier = if (flavour == nature.dislikedFlavour) {
DISLIKED_FLAVOUR_MULTIPLIER
} else if (flavour == nature.favouriteFlavour) {
LIKED_FLAVOUR_MULTIPLIER
} else {
1F
}
val apricornPolarity = apricorn.flavourStrength[flavour]
val apricornMultiplier = if (apricornPolarity == true) {
STRONG_APRICORN_MULTIPLIER
} else if (apricornPolarity == false) {
WEAK_APRICORN_MULTIPLIER
} else {
1F
}
val applyFlavour = value * apricornMultiplier * tasteMultiplier
return if (applyFlavour >= TRIPLE_POINT_THRESHOLD) {
3F
} else if (applyFlavour >= DOUBLE_POINT_THRESHOLD) {
2F
} else {
1F
}
}
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
if (!hasRideBoosts(stack) && user is Player && !world.isClientSide) {
val hasFlavour = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours?.any { it.value > 0 } == true
if (!hasFlavour && user is Player && !world.isClientSide) {
user.foodData.eat(4, 1.2f)
stack.consume(1, user)
}
@@ -111,11 +156,13 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
}
override fun getUseAnimation(stack: ItemStack): UseAnim {
return if (hasRideBoosts(stack)) UseAnim.NONE else UseAnim.DRINK
val hasFlavour = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours?.any { it.value > 0 } == true
return if (hasFlavour) UseAnim.NONE else UseAnim.DRINK
}
override fun getUseDuration(stack: ItemStack, entity: LivingEntity): Int {
return if (hasRideBoosts(stack)) 0 else 32 // 32 ticks like drinking a potion
val hasFlavour = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours?.any { it.value > 0 } == true
return if (hasFlavour) 0 else 32 // 32 ticks like drinking a potion
}
// todo not sure which one is needed at the moment, but I assume just the eating sound?
@@ -1,54 +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.item.components
import com.cobblemon.mod.common.CobblemonMechanics
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.pot.CookingQuality
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import io.netty.buffer.ByteBuf
import net.minecraft.network.codec.ByteBufCodecs
import net.minecraft.network.codec.StreamCodec
/**
* Put on aprijuice after cooking, gives boosts to riding stats when used on a Pokémon.
*
* @author Hiroku
* @since November 7th, 2025
*/
class RideBoostsComponent(
val boosts: Map<RidingStat, Int>
) {
companion object {
val CODEC: Codec<RideBoostsComponent> = RecordCodecBuilder.create { builder ->
builder.group(
Codec.unboundedMap(Codec.STRING, Codec.INT).fieldOf("boosts").forGetter { it.boosts.mapKeys { it.key.name } }
).apply(builder) { map -> RideBoostsComponent(map.mapKeys { RidingStat.valueOf(it.key) }) }
}
val PACKET_CODEC: StreamCodec<ByteBuf, RideBoostsComponent> = ByteBufCodecs.fromCodec(CODEC)
}
fun getQuality(): CookingQuality {
val mechanic = CobblemonMechanics.aprijuices
val totalPoints = boosts.values.sum()
return mechanic.cookingQualityPointThresholds.filter { totalPoints >= it.key }.maxOf { it.value }
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is RideBoostsComponent) return false
return boosts == other.boosts
}
override fun hashCode(): Int {
return boosts.hashCode()
}
}
@@ -1,70 +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.item.crafting
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.CobblemonMechanics
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.api.cooking.Seasonings
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.item.AprijuiceItem
import com.cobblemon.mod.common.item.components.RideBoostsComponent
import net.minecraft.world.item.ItemStack
/**
* The seasoning processor that converts flavourful inputs and produces ride stat boosts on aprijuices.
*
* Example case:
* - Berries with a total of 40 SPICY and 20 SWEET seasoning are applied to a Red Aprijuice.
* - 40 SPICY hits the threshold for 2 points in ACCELERATION.
* - 20 SWEET hits the threshold for 1 point in SPEED.
* - The Red Aprijuice's inherent effects add 2 point to ACCELERATION and takes 1 point from STAMINA.
* - The resulting RideBoostsComponent on the aprijuice will have:
* - ACCELERATION: 4 points (2 from SPICY + 2 from apricorn)
* - SPEED: 1 point (1 from SWEET)
* - STAMINA: -1 point (1 from apricorn)
*
* @author Hiroku
* @since November 7th, 2025
*/
object RideBoostsSeasoningProcessor : SeasoningProcessor {
override val type = "ride_boosts"
override fun apply(result: ItemStack, seasoning: List<ItemStack>) {
val flavours = mutableMapOf<Flavour, Int>()
for (seasoningStack in seasoning) {
val seasoningObj = Seasonings.getFromItemStack(seasoningStack) ?: continue
for ((flavour, value) in seasoningObj.flavours ?: emptyMap()) {
flavours[flavour] = (flavours[flavour] ?: 0) + value
}
}
val resultItem = result.item
if (resultItem is AprijuiceItem) {
val apricornColour = resultItem.type
val mechanic = CobblemonMechanics.aprijuices
val apricornStatEffects = mechanic.apricornStatEffects[apricornColour] ?: emptyMap()
val statBoosts = mutableMapOf<RidingStat, Int>()
flavours.forEach { (flavour, value) ->
val ridingStat = RidingStat.getByFlavour(flavour) ?: return@forEach
val pointsFromFlavour = mechanic.statPointFlavourThresholds.filter { value >= it.key }.maxOf { it.value }
val pointsFromApricorn = apricornStatEffects[ridingStat] ?: 0
val totalBoost = pointsFromFlavour + pointsFromApricorn
statBoosts[ridingStat] = totalBoost
}
result.set(CobblemonItemComponents.RIDE_BOOST, RideBoostsComponent(statBoosts))
}
}
override fun consumesItem(seasoning: ItemStack): Boolean {
val seasoningData = Seasonings.getFromItemStack(seasoning)
return seasoningData != null && !seasoningData.flavours.isNullOrEmpty()
}
}
@@ -26,8 +26,7 @@ interface SeasoningProcessor {
FlavourSeasoningProcessor.type to FlavourSeasoningProcessor,
FoodColourSeasoningProcessor.type to FoodColourSeasoningProcessor,
FoodSeasoningProcessor.type to FoodSeasoningProcessor,
MobEffectSeasoningProcessor.type to MobEffectSeasoningProcessor,
RideBoostsSeasoningProcessor.type to RideBoostsSeasoningProcessor,
MobEffectSeasoningProcessor.type to MobEffectSeasoningProcessor
)
}
@@ -11,21 +11,21 @@ package com.cobblemon.mod.common.item.group
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonItemComponents
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.api.cooking.Flavour
import com.cobblemon.mod.common.item.AprijuiceItem
import com.cobblemon.mod.common.item.components.RideBoostsComponent
import com.cobblemon.mod.common.item.components.FlavourComponent
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.network.chat.Component
import net.minecraft.world.level.ItemLike
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.resources.ResourceKey
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.CreativeModeTab
import net.minecraft.world.item.CreativeModeTab.DisplayItemsGenerator
import net.minecraft.world.item.CreativeModeTab.ItemDisplayParameters
import net.minecraft.world.item.CreativeModeTab.Output
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.level.ItemLike
@Suppress("unused", "UNUSED_PARAMETER")
object CobblemonItemGroups {
@@ -542,13 +542,13 @@ object CobblemonItemGroups {
private fun defaultAprijuice(item: AprijuiceItem): ItemStack {
return ItemStack(item).apply {
this.set(CobblemonItemComponents.RIDE_BOOST, RideBoostsComponent(
this.set(CobblemonItemComponents.FLAVOUR, FlavourComponent(
mapOf(
RidingStat.ACCELERATION to 1,
RidingStat.JUMP to 1,
RidingStat.SPEED to 1,
RidingStat.STAMINA to 1,
RidingStat.SKILL to 1
Flavour.SPICY to 10,
Flavour.DRY to 10,
Flavour.SWEET to 10,
Flavour.BITTER to 10,
Flavour.SOUR to 10,
)
))
}
@@ -6,12 +6,13 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.item.interactive
package com.cobblemon.mod.common.item.food
import com.cobblemon.mod.common.CobblemonItemComponents
import net.minecraft.network.chat.Component
import net.minecraft.sounds.SoundEvent
import net.minecraft.sounds.SoundEvents
import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.food.FoodProperties
@@ -1,28 +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.mechanics
import com.cobblemon.mod.common.api.apricorn.Apricorn
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.pot.CookingQuality
/**
* Mechanic to hold various properties that motivate aprijuice as a mechanic.
*
* @author Hiroku
* @since November 7th, 2025
*/
class AprijuicesMechanic {
/** The points that apply to different riding stats, based on the apricorn used for the aprijuice. */
val apricornStatEffects = mutableMapOf<Apricorn, Map<RidingStat, Int>>()
/** Maps flavour values to stat points for riding stats. Aprijuice finds the highest threshold it meets. */
val statPointFlavourThresholds = mutableMapOf<Int, Int>()
/** Maps stat points for riding stats to what cooking quality that represents. It's for tooltips. */
val cookingQualityPointThresholds = mutableMapOf<Int, CookingQuality>()
}
@@ -1,40 +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.net.messages.client.ui
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
import java.util.UUID
class ExpGainedDataPacket(
val pokemonUUID: UUID,
val oldLevel: Int?,
val expGained: Int,
val countOfMovesLearned: Int
): NetworkPacket<ExpGainedDataPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeUUID(pokemonUUID)
buffer.writeNullable(oldLevel) { pb, v -> pb.writeInt(v) }
buffer.writeInt(expGained)
buffer.writeInt(countOfMovesLearned)
}
companion object {
val ID = cobblemonResource("exp_gained_data")
fun decode(buffer: RegistryFriendlyByteBuf) = ExpGainedDataPacket(
buffer.readUUID(),
buffer.readNullable { buffer.readInt() },
buffer.readInt(),
buffer.readInt()
)
}
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.pokemon
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToPlayers
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.abilities.Abilities
@@ -81,7 +80,6 @@ import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
import com.cobblemon.mod.common.net.messages.client.PokemonUpdatePacket
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
import com.cobblemon.mod.common.net.serverhandling.storage.SendOutPokemonHandler.SEND_OUT_DURATION
import com.cobblemon.mod.common.net.serverhandling.storage.SendOutPokemonHandler.THROW_DURATION
import com.cobblemon.mod.common.pokeball.PokeBall
@@ -1931,7 +1929,9 @@ open class Pokemon : ShowdownIdentifiable {
if (result.experienceAdded <= 0) {
return result
}
player.sendSystemMessage(lang("experience.gained", getDisplayName(), result.experienceAdded), true)
if (result.oldLevel != result.newLevel) {
player.sendSystemMessage(lang("experience.level_up", getDisplayName(), result.newLevel))
val repeats = result.newLevel - result.oldLevel
// Someone can technically trigger a "delevel"
if (repeats >= 1) {
@@ -1939,13 +1939,10 @@ open class Pokemon : ShowdownIdentifiable {
this.incrementFriendship(LEVEL_UP_FRIENDSHIP_CALCULATOR.calculate(this))
}
}
result.newMoves.forEach {
player.sendSystemMessage(lang("experience.learned_move", getDisplayName(), it.displayName))
}
}
player.sendPacket(ExpGainedDataPacket(
this.uuid,
if (result.oldLevel != result.newLevel) result.oldLevel else null,
result.experienceAdded,
result.newMoves.size
))
return result
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.pokemon.ai
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.entity.OmniPathingEntity
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
import com.cobblemon.mod.common.util.canFit
import com.google.common.collect.Maps
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
@@ -266,23 +265,6 @@ class OmniPathNodeMaker : NodeEvaluator() {
return !currentContext.level().noCollision(mob, boundingBox)
}
// Borrowed from WalkNodeEvaluator, specifically here for things that don't use the
// PokemonMoveControl such as NPCs, to prevent them from being caught on upward diagonals
private fun isDiagonalValidForNonPokemon(root: Node, xNode: Node?, zNode: Node?): Boolean {
if (this.mob.moveControl == PokemonMoveControl) return true
if (zNode != null && xNode != null && zNode.y <= root.y && xNode.y <= root.y) {
if (xNode.type != PathType.WALKABLE_DOOR && zNode.type != PathType.WALKABLE_DOOR) {
val bl = zNode.type == PathType.FENCE && xNode.type == PathType.FENCE && this.mob.bbWidth
.toDouble() < 0.5
return (zNode.y < root.y || zNode.costMalus >= 0.0f || bl) && (xNode.y < root.y || xNode.costMalus >= 0.0f || bl)
} else {
return false
}
} else {
return false
}
}
protected fun getFloorLevel(pos: BlockPos): Double {
val blockGetter: BlockGetter = currentContext.level()
if ((canFloat()) && blockGetter.getFluidState(pos).`is`(FluidTags.WATER)) {
@@ -352,8 +334,6 @@ class OmniPathNodeMaker : NodeEvaluator() {
map[direction2]
) || (node.type == PathType.BLOCKED && !pathNode2.closed)
) {
if (!isDiagonalValidForNonPokemon(node, map[direction], map[direction2]))
continue
successors[i++] = pathNode2
}
}
@@ -379,8 +359,7 @@ class OmniPathNodeMaker : NodeEvaluator() {
node.z + direction.stepZ + direction2.stepZ
) ?: continue
if (isAccessibleDiagonal(pathNode2, upperMap[direction], upperMap[direction2])
) {
if (isAccessibleDiagonal(pathNode2, upperMap[direction], upperMap[direction2])) {
successors[i++] = pathNode2
}
}
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionDisplay
import com.cobblemon.mod.common.api.pokemon.evolution.PreProcessor
import com.cobblemon.mod.common.api.pokemon.evolution.progress.EvolutionProgress
import com.cobblemon.mod.common.api.text.green
import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.asTranslated
@@ -27,6 +26,11 @@ class ClientEvolutionController(
private val pokemon: Pokemon,
evolutions: Set<EvolutionDisplay>,
) : EvolutionController<EvolutionDisplay, ClientEvolutionController.Intermediate> {
init {
if (evolutions.isNotEmpty()) sendPlayerNotification()
}
private val evolutions = evolutions.toMutableSet()
override val size: Int
@@ -83,7 +87,10 @@ class ClientEvolutionController(
fun sendPlayerNotification() {
if (pokemon.heldItem?.item != CobblemonItems.EVERSTONE) {
PartyOverlayDataControl.pokemonGainedEvo(pokemon.uuid, 1)
Minecraft.getInstance().player?.let { player ->
player.sendSystemMessage("cobblemon.ui.evolve.hint".asTranslated(pokemon.getDisplayName()).green())
player.playSound(CobblemonSounds.EVOLUTION_NOTIFICATION, 1F, 1F)
}
}
}
@@ -0,0 +1,57 @@
/*
* 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.util.adapters
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.reflect.TypeToken
import java.lang.reflect.Type
import net.minecraft.network.chat.Component
object RidingStatDefinitionAdapter : JsonDeserializer<RidingStatDefinition> {
override fun deserialize(
json: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): RidingStatDefinition {
if (json.isJsonPrimitive) {
val range = IntRangeAdapter.deserialize(json, TypeToken.get(IntRange::class.java).type, context)
return RidingStatDefinition().apply {
this.ranges.putAll(RidingStyle.entries.associateWith { range })
}
}
json as JsonObject
val rangesJson = json.get("ranges")
val displayName = json.get("displayName")?.let { TextAdapter.deserialize(it, TypeToken.get(Component::class.java).type, context) }
val description = json.get("description")?.let { TextAdapter.deserialize(it, TypeToken.get(Component::class.java).type, context) }
if (rangesJson.isJsonPrimitive) {
val range = IntRangeAdapter.deserialize(rangesJson, TypeToken.get(IntRange::class.java).type, context)
return RidingStatDefinition().apply {
displayName?.let { this.displayName = it }
description?.let { this.description = it }
this.ranges.putAll(RidingStyle.entries.associateWith { range })
}
} else {
val ranges = rangesJson.asJsonObject.entrySet().associate { (key, value) ->
RidingStyle.valueOf(key) to IntRangeAdapter.deserialize(value, TypeToken.get(IntRange::class.java).type, context)
}
return RidingStatDefinition().apply {
displayName?.let { this.displayName = it }
description?.let { this.description = it }
this.ranges.putAll(ranges)
}
}
}
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.world.feature
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.tags.CobblemonBiomeTags
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
@@ -22,8 +21,6 @@ import net.minecraft.world.level.block.Block.UPDATE_ALL
import net.minecraft.world.level.block.Block.UPDATE_CLIENTS
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.LeavesBlock
import net.minecraft.world.level.block.entity.BeehiveBlockEntity
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.properties.BlockStateProperties
import net.minecraft.world.level.chunk.status.ChunkStatus
@@ -31,7 +28,6 @@ import net.minecraft.world.level.levelgen.feature.Feature
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext
import net.minecraft.world.level.levelgen.feature.TreeFeature
import net.minecraft.world.level.levelgen.feature.configurations.BlockStateConfiguration
import java.util.function.Consumer
class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfiguration.CODEC) {
@@ -76,6 +72,7 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
// Place the tree
val potentialBeeNestPositions = mutableListOf<BlockPos>()
val flowerPositions = isFlowerNearby(worldGenLevel, origin)
// Create trunk
val logState = CobblemonBlocks.SACCHARINE_LOG.defaultBlockState()
@@ -83,7 +80,7 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
val logPos = origin.relative(UP, y)
worldGenLevel.setBlock(logPos, logState, UPDATE_CLIENTS)
}
var currentHeight = trunkHeight
// Place patterns
@@ -159,21 +156,15 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
}
// Place bee nest logic
if (isGenerating) {
// world gen
if (worldGenLevel.random.nextInt(5) == 0) {
placeBeeNest(worldGenLevel, potentialBeeNestPositions)
}
} else if (isFlowerNearby(worldGenLevel, origin) && worldGenLevel.random.nextInt(20) == 0) {
// post world gen
placeBeeNest(worldGenLevel, potentialBeeNestPositions)
if (isGenerating || flowerPositions.isNotEmpty()) {
placeBeeNest(worldGenLevel, potentialBeeNestPositions, flowerPositions)
}
return true
}
/**
* A function to filter possible bee nest positions [locationsToCheck] to remove locations with a non-empty block to the south.
* A function to filter possible bee nest positions [locationsToCheck] to remove locations with a none empty block to the south.
* @return A sub-set of bee nest positions with an empty block to the south (z + 1).
*/
private fun filterBeeNestPositions(worldGenLevel: WorldGenLevel, locationsToCheck: List<BlockPos>): List<BlockPos> {
@@ -192,52 +183,42 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
return viableBeeNestPositions
}
private fun isFlowerNearby(worldGenLevel: WorldGenLevel, origin: BlockPos): Boolean {
private fun isFlowerNearby(worldGenLevel: WorldGenLevel, origin: BlockPos): List<BlockPos> {
val flowerPositions = mutableListOf<BlockPos>()
for (dx in -2..2) {
for (dy in -2..2) {
for (dz in -2..2) {
val pos = origin.offset(dx, dy, dz)
if (worldGenLevel.getBlockState(pos).`is`(BlockTags.FLOWERS)) {
return true
flowerPositions.add(pos)
}
}
}
}
return false
return flowerPositions
}
private fun placeBeeNest(worldGenLevel: WorldGenLevel, potentialBeeNestPositions: MutableList<BlockPos>) {
private fun placeBeeNest(worldGenLevel: WorldGenLevel, potentialBeeNestPositions: MutableList<BlockPos>, flowerPositions: List<BlockPos>) {
val viableBeeNestPositions: List<BlockPos> = filterBeeNestPositions(worldGenLevel, potentialBeeNestPositions)
val nestPos = viableBeeNestPositions.randomOrNull()
if (nestPos != null && worldGenLevel.isEmptyBlock(nestPos)) {
val nestPos = viableBeeNestPositions.firstOrNull { pos ->
flowerPositions.any { flowerPos -> flowerPos.closerThan(pos, 1.5) }
} ?: viableBeeNestPositions.randomOrNull()
val validNestPos = flowerPositions.firstOrNull { flowerPos ->
nestPos?.closerThan(flowerPos, 1.5) == true
}?.relative(Direction.SOUTH) ?: nestPos
if (validNestPos != null && worldGenLevel.isEmptyBlock(validNestPos)) {
val southFacingBeeNest = Blocks.BEE_NEST.defaultBlockState().setValue(BlockStateProperties.HORIZONTAL_FACING, Direction.SOUTH)
setBlockIfClear(worldGenLevel, validNestPos, southFacingBeeNest)
} else if (nestPos != null && worldGenLevel.isEmptyBlock(nestPos)) {
// Natural Generation
val southFacingBeeNest = Blocks.BEE_NEST.defaultBlockState().setValue(BlockStateProperties.HORIZONTAL_FACING, Direction.SOUTH)
setBlockIfClear(worldGenLevel, nestPos, southFacingBeeNest)
populateBeeNest(worldGenLevel, nestPos)
}
}
private fun populateBeeNest(worldGenLevel: WorldGenLevel, pos: BlockPos) {
worldGenLevel.getBlockEntity(pos, BlockEntityType.BEEHIVE)
.ifPresent(
Consumer { beehiveBlockEntity: BeehiveBlockEntity? ->
val randomSource: RandomSource = worldGenLevel.random
val isCombee = randomSource.nextInt(2)
val i: Int = 2 + randomSource.nextInt(2)
for (j in 0..<i) {
if (isCombee > 0) {
beehiveBlockEntity!!.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)))
} else {
val properties = "${POKEMON_ARGS} lvl=${LEVEL_RANGE.random()}"
val pokemon = PokemonProperties.parse(properties)
val entity = pokemon.createEntity(worldGenLevel.level)
beehiveBlockEntity!!.addOccupant(entity)
}
}
})
}
private fun placeBigLeafPattern(worldGenLevel: WorldGenLevel, origin: BlockPos, logBlock: BlockState, leafBlock: BlockState) {
val positions = listOf(
origin.offset(-2, 0, 0),
@@ -347,9 +328,4 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
}
worldGenLevel.setBlock(blockPos, blockState, UPDATE_ALL)
}
companion object {
val POKEMON_ARGS = "combee"
val LEVEL_RANGE = 5..15
}
}
@@ -1,99 +0,0 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.eggant_berry",
"texture_width": 8,
"texture_height": 8,
"visible_bounds_width": 2,
"visible_bounds_height": 1.5,
"visible_bounds_offset": [0, 0.25, 0]
},
"bones": [
{
"name": "Eggant",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-1, -4.5, -1], "size": [2, 2, 2], "uv": [0, 0]},
{"origin": [-0.5, -2.5, -0.5], "size": [1, 2, 1], "uv": [0, 4]},
{"origin": [0, -1, -0.5], "size": [0, 1, 1], "pivot": [0, -0.25, 0], "rotation": [0, 45, 0], "uv": [2, 6]},
{"origin": [-0.5, -1, 0], "size": [1, 1, 0], "pivot": [0, -0.25, 0], "rotation": [0, 45, 0], "uv": [0, 7]}
]
},
{
"name": "leaf_front",
"parent": "Eggant",
"pivot": [0, -0.5, -0.5],
"rotation": [-15, 0, 0],
"cubes": [
{"origin": [-0.5, -2.5, -0.5], "size": [1, 2, 0], "uv": [0, 0]}
]
},
{
"name": "leaf_front2",
"parent": "leaf_front",
"pivot": [0, -2.5, -0.5],
"rotation": [-60, 0, 0],
"cubes": [
{"origin": [-0.5, -3.5, -0.5], "size": [1, 1, 0], "uv": [4, 6]}
]
},
{
"name": "leaf_right",
"parent": "Eggant",
"pivot": [-0.5, -0.5, 0],
"rotation": [0, 0, 15],
"cubes": [
{"origin": [-0.5, -2.5, -0.5], "size": [0, 2, 1], "uv": [6, -1]}
]
},
{
"name": "leaf_right2",
"parent": "leaf_right",
"pivot": [-0.5, -2.5, 0],
"rotation": [0, 0, 60],
"cubes": [
{"origin": [-0.5, -3.5, -0.5], "size": [0, 1, 1], "uv": [6, 5]}
]
},
{
"name": "leaf_left",
"parent": "Eggant",
"pivot": [0.5, -0.5, 0],
"rotation": [0, 0, -15],
"cubes": [
{"origin": [0.5, -2.5, -0.5], "size": [0, 2, 1], "uv": [6, 3]}
]
},
{
"name": "leaf_left2",
"parent": "leaf_left",
"pivot": [0.5, -2.5, 0],
"rotation": [0, 0, -60],
"cubes": [
{"origin": [0.5, -3.5, -0.5], "size": [0, 1, 1], "uv": [6, 6]}
]
},
{
"name": "leaf_back",
"parent": "Eggant",
"pivot": [0, -0.5, 0.5],
"rotation": [15, 0, 0],
"cubes": [
{"origin": [-0.5, -2.5, 0.5], "size": [1, 2, 0], "uv": [4, 4]}
]
},
{
"name": "leaf_back2",
"parent": "leaf_back",
"pivot": [0, -2.5, 0.5],
"rotation": [60, 0, 0],
"cubes": [
{"origin": [-0.5, -3.5, 0.5], "size": [1, 1, 0], "uv": [4, 7]}
]
}
]
}
]
}
@@ -25,7 +25,7 @@
"active_time": 1
},
"minecraft:emitter_shape_point": {
"offset": ["((v.target_deltax*(v.emitter_age/v.emitter_lifetime))*0.8)+(math.sin(v.emitter_age*700)*0.1)", "((v.target_deltay*(v.emitter_age/v.emitter_lifetime))*0.8)+(math.cos(90-v.emitter_age*540)*0.1)", "(-v.target_deltaz*(v.emitter_age/v.emitter_lifetime))*0.9"],
"offset": ["((-v.target_deltax*(v.emitter_age/v.emitter_lifetime))*0.8)+(math.sin(v.emitter_age*700)*0.1)", "((v.target_deltay*(v.emitter_age/v.emitter_lifetime))*0.8)+(math.cos(90-v.emitter_age*540)*0.1)", "(-v.target_deltaz*(v.emitter_age/v.emitter_lifetime))*0.9"],
"direction": ["math.random(-0.45,0.45)", "math.random(-0.45,0.45)-(v.target_deltay/v.target_deltaz)", "math.random(-2.05,-0.55)"]
},
"minecraft:particle_lifetime_expression": {
@@ -1,89 +0,0 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:blastoise6",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/water/giantsplash"
}
},
"curves": {
"variable.fade": {
"type": "bezier_chain",
"input": "v.particle_age",
"nodes": {
"0.0": {
"value": 0,
"slope": 0
},
"1.5": {
"value": 0.4,
"slope": 0
},
"1.0": {
"value": 0,
"slope": 0
}
}
}
},
"components": {
"minecraft:emitter_local_space": {
"position": false,
"rotation": false,
"velocity": false
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 100,
"max_particles": 100
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1000000
},
"minecraft:emitter_shape_point": {
"direction": ["0+math.random(-0.15,0.15)", -1, "0+math.random(-0.15,0.15)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "0.5-(v.particle_random_4/4)"
},
"minecraft:particle_initial_spin": {
"rotation": "math.random_integer(0,10)*90"
},
"minecraft:particle_initial_speed": 10,
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["v.particle_random_1-0.5", -9.8, "v.particle_random_3-0.5"]
},
"minecraft:particle_appearance_billboard": {
"size": ["0.4-variable.fade", "0.4-variable.fade"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 12,
"texture_height": 96,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [12, 12],
"step_UV": [0, 12],
"frames_per_second": 6,
"max_frame": 8,
"stretch_to_lifetime": true
}
}
},
"minecraft:particle_motion_collision": {
"coefficient_of_restitution": 0.3,
"collision_radius": 0.05
},
"minecraft:particle_appearance_lighting": {},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FF3FA8FF",
"1.0": "#ffffffff"
}
}
}
}
}
}
@@ -888,7 +888,7 @@
}
}
},
"animation.tentacruel.ground_sleep": {
"animation.tentacruel.sleep": {
"loop": true,
"bones": {
"body": {
@@ -205,12 +205,10 @@
"head": {
"rotation": {
"0.0": [85, 0, 0],
"0.0833": [66, 0, 0],
"0.1667": [62, 0, 0],
"0.2083": [60, 0, 0],
"0.4167": [55, 0, 0],
"0.5417": [57, 0, 0],
"0.6667": [80.75, 0, 0],
"0.7917": [79.5, 0, 0],
"0.9167": [84.175, 0, 0],
"1.0": [85, 0, 0]
@@ -223,31 +221,11 @@
"0.2917": [13.11, -5.57, 54.92],
"0.4583": [-3.06, -22.4, 43.92],
"0.5": [-9.1, -26.61, 43.92],
"0.5833": {
"pre": [-7.51, -17.12, 40.18],
"post": [-7.51, -17.12, 40.18],
"lerp_mode": "catmullrom"
},
"0.625": {
"post": [3.43, -12.375, 38.315],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [14.27, -3.065, 36.275],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [34.65, 4.64, 35.195],
"lerp_mode": "catmullrom"
},
"0.9167": {
"post": [69.62, 6.785, 50.56],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [70.90134, 0.89017, 78.92416],
"lerp_mode": "catmullrom"
}
"0.625": [16.53, -12.375, 38.315],
"0.6667": [22.57, -3.065, 36.275],
"0.75": [34.65, 4.64, 35.195],
"0.9167": [58.82, 6.785, 50.56],
"1.0": [70.90134, 0.89017, 78.92416]
},
"position": [0, -1.68678, 1.0746]
},
@@ -275,8 +253,8 @@
"0.2083": [0, 0, -16.25],
"0.5": [0, 0, -25],
"0.5417": [0, 0, -25.83],
"0.7083": [0, 0, 20],
"0.875": [0, 0, -47.5],
"0.625": [0, 0, 20],
"0.7917": [0, 0, -47.5],
"1.0": [0, 0, -70]
}
},
@@ -287,31 +265,11 @@
"0.2917": [13.11, 5.57, -54.92],
"0.4583": [-3.06, 22.4, -43.92],
"0.5": [-9.1, 26.61, -43.92],
"0.5833": {
"pre": [-7.51, 17.12, -40.18],
"post": [-7.51, 17.12, -40.18],
"lerp_mode": "catmullrom"
},
"0.625": {
"post": [3.43, 12.375, -38.315],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [14.27, 3.065, -36.275],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [34.65, -4.64, -35.195],
"lerp_mode": "catmullrom"
},
"0.9167": {
"post": [69.62, -6.785, -50.56],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [70.90134, -0.89017, -78.92416],
"lerp_mode": "catmullrom"
}
"0.625": [16.53, 12.375, -38.315],
"0.6667": [22.57, 3.065, -36.275],
"0.75": [34.65, -4.64, -35.195],
"0.9167": [58.82, -6.785, -50.56],
"1.0": [70.90134, -0.89017, -78.92416]
},
"position": [0, -1.68678, 1.0746]
},
@@ -339,8 +297,8 @@
"0.2083": [0, 0, 16.25],
"0.5": [0, 0, 25],
"0.5417": [0, 0, 25.83],
"0.7083": [0, 0, -20],
"0.875": [0, 0, 47.5],
"0.625": [0, 0, -20],
"0.7917": [0, 0, 47.5],
"1.0": [0, 0, 70]
}
},
@@ -459,59 +417,113 @@
"animation_length": 0.75,
"bones": {
"body": {
"rotation": ["Math.cos((query.anim_time)*90*16/3-45)*9", 0, 0],
"position": [0, "0+Math.cos((query.anim_time)*90*16/3+210)*-4", "0+Math.cos((query.anim_time)*90*16/3-90)*-2"]
"rotation": ["-5+Math.cos((query.anim_time) * 90 * 16/3 - 45) * 2", 0, 0],
"position": [0, "0+Math.cos((query.anim_time) * 90 * 16/3 + 45) * 2", "0+Math.cos((query.anim_time) * 90 * 16/3) * 3"]
},
"tail": {
"rotation": ["-2.5+Math.cos((query.anim_time)*90*16/3-90)*9", 0, 0]
"rotation": ["-2.5+Math.cos((query.anim_time) * 90 * 16/3 - 90) * 6", 0, 0]
},
"tail2": {
"rotation": ["-5+Math.cos((query.anim_time)*90*16/3-140)*12", 0, 0]
"rotation": ["-5+Math.cos((query.anim_time) * 90 * 16/3 - 135) * 6", 0, 0]
},
"tail3": {
"rotation": ["5+Math.cos((query.anim_time)*90*16/3-180)*15", 0, 0]
"rotation": ["5+Math.cos((query.anim_time) * 90 * 16/3 - 180) * 6", 0, 0]
},
"tail4": {
"rotation": ["5+Math.cos((query.anim_time)*90*16/3-210)*20", 0, 0]
"rotation": ["5+Math.cos((query.anim_time) * 90 * 16/3 - 200) * 16", 0, 0]
},
"tail6": {
"rotation": ["5+Math.cos((query.anim_time)*90*16/3-300)*35", 0, 0]
"rotation": ["5+Math.cos((query.anim_time) * 90 * 16/3 - 350) * 26", 0, 0]
},
"chest": {
"rotation": ["Math.cos((query.anim_time)*90*16/3+90)*6", 0, 0],
"rotation": ["5+Math.cos((query.anim_time) * 90 * 16/3 + 45) * 1", 0, 0],
"position": [0, 0, 0.25]
},
"neck": {
"rotation": ["-35+Math.cos((query.anim_time)*90*16/3+150)*5", 0, 0],
"position": [0, 0, 3]
"rotation": ["-50+Math.cos((query.anim_time) * 90 * 16/3 + 90) * -2", 0, 0]
},
"head": {
"rotation": ["35+Math.cos((query.anim_time)*90*16/3+210)*9", 0, 0],
"rotation": ["47.5+Math.cos((query.anim_time) * 90 * 16/3 - 45) * -6", 0, 0],
"position": [0, 0, 1]
},
"flipper_left": {
"rotation": [55.29871, "-54.409+Math.cos((query.anim_time)*90*16/3+90)*20", 28.25077]
},
"flipper_right": {
"rotation": [55.29871, "54.409-Math.cos((query.anim_time)*90*16/3+90)*20", -28.25076]
},
"torso": {
"rotation": ["2.5+Math.cos((query.anim_time)*90*16/3+45)*8", 0, 0]
},
"tail5": {
"rotation": ["7.5+Math.cos((query.anim_time)*90*16/3-260)*26", 0, 0]
"rotation": {
"0.0": [37.25, 50.65, 0],
"0.0417": [37.25, 46.72, 1.1],
"0.375": [37.25, -45.255, 12.5],
"0.4167": [37.25, -47.5, 12.5],
"0.4583": [39.9, -45.255, 12.5],
"0.5417": [52.825, -13.75, 8.97],
"0.5833": [55.5, -0.315, 7.2],
"0.625": [52.325, 16.325, 5.03],
"0.7083": [38.4, 46.72, 0.7],
"0.75": [37.25, 50.65, 0]
},
"position": [0, -1.68678, 1.0746]
},
"flipper_left2": {
"rotation": [0, 0, "0-Math.cos((query.anim_time)*90*16/3+30)*6"]
"rotation": {
"0.0": [0, 0, 0],
"0.125": [0, 0, -10],
"0.2917": [0, 0, -0.76],
"0.4167": [0, 0, 24.75],
"0.4583": [0, 0, 37.5],
"0.625": [0, 0, 64.5],
"0.75": [0, 0, 0]
}
},
"flipper_left3": {
"rotation": [0, 0, "0-Math.cos((query.anim_time)*90*16/3-30)*20"]
"rotation": {
"0.0": [0, 0, 10],
"0.125": [0, 0, -7.5],
"0.375": [0, 0, -9.37],
"0.4583": [0, 0, 20],
"0.625": [0, 0, 35],
"0.75": [0, 0, 10]
}
},
"flipper_right": {
"rotation": {
"0.0": [37.25, -50.65, 0],
"0.0417": [37.25, -46.72, -1.1],
"0.375": [37.25, 45.255, -12.5],
"0.4167": [37.25, 47.5, -12.5],
"0.4583": [39.9, 45.255, -12.5],
"0.5417": [52.825, 13.75, -8.97],
"0.5833": [55.5, 0.315, -7.2],
"0.625": [52.325, -16.325, -5.03],
"0.7083": [38.4, -46.72, -0.7],
"0.75": [37.25, -50.65, 0]
},
"position": [0, -1.68678, 1.0746]
},
"flipper_right2": {
"rotation": [0, 0, "-0+Math.cos((query.anim_time)*90*16/3+30)*6"]
"rotation": {
"0.0": [0, 0, 0],
"0.125": [0, 0, 10],
"0.2917": [0, 0, 0.76],
"0.4167": [0, 0, -24.75],
"0.4583": [0, 0, -37.5],
"0.625": [0, 0, -64.5],
"0.75": [0, 0, 0]
}
},
"flipper_right3": {
"rotation": [0, 0, "-0+Math.cos((query.anim_time)*90*16/3-30)*20"]
"rotation": {
"0.0": [0, 0, -30],
"0.0833": [0, 0, -3.17],
"0.125": [0, 0, 7.5],
"0.375": [0, 0, 9.37],
"0.4583": [0, 0, -20],
"0.625": [0, 0, -35],
"0.75": [0, 0, -30]
}
},
"torso": {
"rotation": ["2.5+Math.cos((query.anim_time) * 90 * 16/3 + 0) * 2", 0, 0]
},
"tail5": {
"rotation": ["7.5+Math.cos((query.anim_time) * 90 * 16/3 - 260) * 26", 0, 0]
}
}
},
@@ -519,16 +531,16 @@
"loop": true,
"bones": {
"body": {
"rotation": [0, 0, "q.r.yaw_change(0)*-12"]
"rotation": [0, 0, "q.r.yaw_change(0)*-10"]
},
"tail": {
"rotation": ["q.r.pitch_change(0)*5", "q.r.yaw_change(0)*-7.5", 0]
"rotation": ["q.r.pitch_change(0)*5", "q.r.yaw_change(0)*-5", 0]
},
"tail2": {
"rotation": ["q.r.pitch_change(4)*8", "q.r.yaw_change(0)*-7.5", 0]
"rotation": ["q.r.pitch_change(4)*8", "q.r.yaw_change(0)*-5", 0]
},
"tail3": {
"rotation": ["q.r.pitch_change(6)*12", "q.r.yaw_change(0)*-7.5", 0]
"rotation": ["q.r.pitch_change(6)*12", "q.r.yaw_change(0)*-5", 0]
},
"torso": {
"rotation": ["q.r.pitch_change(0)*-5", "q.r.yaw_change(0)*5", 0]
@@ -551,38 +563,19 @@
"neck": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [-10, 0, 0],
"post": [-10, 0, 0],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [-10, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": [-10, 0, 0],
"1.0": [-10, 0, 0],
"1.25": [0, 0, 0]
}
},
"jaw": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [45, 0, 0],
"post": [45, 0, 0],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [45, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": [45, 0, 0],
"1.0": [45, 0, 0],
"1.25": [0, 0, 0]
}
}
},
"sound_effects": {
"0.0833": {
"effect": "pokemon.dewgong.cry"
}
}
},
"animation.dewgong.blink": {
@@ -614,124 +614,6 @@
}
}
},
"animation.lapras.ride_ground_walk": {
"loop": true,
"bones": {
"chest": {
"rotation": [0, "-q.r.yaw_change(0)*-10", 0]
},
"chest2": {
"rotation": [0, "-q.r.yaw_change(0)*-5", "0+q.r.yaw_change(0)*-10"]
},
"neck2": {
"rotation": [0, "-q.r.yaw_change(0)*-10", "q.r.yaw_change(0)*2"]
},
"neck3": {
"rotation": [0, "-q.r.yaw_change(0)*-10", "q.r.yaw_change(0)*5"]
},
"head": {
"rotation": [0, 0, 0]
},
"head_angle": {
"rotation": [0, "-0-q.r.yaw_change(0)*-20", "0+q.r.yaw_change(0)*-5"]
}
}
},
"animation.lapras.ride_ground_jump": {
"loop": true,
"bones": {
"body": {
"rotation": ["-q.r.velocity_y(0)*20-math.sin(q.anim_time*90*10+30)*-0.5", 0, 0],
"position": [0, "math.clamp((q.r.velocity_y(0)*8),3,8)", 0]
},
"chest": {
"rotation": ["-0-math.sin(q.anim_time*90*10+30)*0.5", 0, 0]
},
"chest2": {
"rotation": ["-math.abs(q.r.velocity_y(0)*3)-math.sin(q.anim_time*90*10)*0.5", 0, 0]
},
"neck2": {
"rotation": ["-12.5-math.abs(q.r.velocity_y(0)*1.5)-math.sin(q.anim_time*90*10-30)*0.75", 0, 0]
},
"neck3": {
"rotation": ["-15-math.abs(q.r.velocity_y(0))-math.sin(q.anim_time*90*10-60)*0.75", 0, 0],
"position": [0, -1, 0]
},
"head": {
"rotation": ["10-math.clamp((q.r.velocity_y(0)*10),-10,0)-math.sin(q.anim_time*90*20-90)/2", 0, 0],
"position": [0, "math.clamp((q.r.velocity_y(0)*1),-1,0)", 0]
},
"head_angle": {
"rotation": ["-0-math.sin(q.anim_time*90*10-90)*0.3", 0, 0]
},
"tail": {
"rotation": ["-math.clamp((q.r.velocity_y(0)*30),-10,30)-(math.sin(q.anim_time*90*20)/2)", 0, 0]
},
"tail2": {
"rotation": ["-math.clamp((q.r.velocity_y(0)*20),-20,10)-(math.sin(q.anim_time*90*20-30)*1.5)", 0, 0]
},
"leg_front_left": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*10)+(math.cos(q.anim_time*90*20)/3)", "15+q.r.velocity_y(0)*30+(math.sin(q.anim_time*90*20)/4)"],
"position": [0, "-math.clamp((q.r.velocity_y(0)*-1),0,1)", 0]
},
"leg_front_left2": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-30)/2)", "q.r.velocity_y(0)*10+(math.sin(q.anim_time*90*20-30)/3)"],
"position": ["-math.abs(q.r.velocity_y(0)*-1)", 0, 0]
},
"leg_front_left3": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*10)+math.cos(q.anim_time*90*20-60)", "q.r.velocity_y(0)*15+math.sin(q.anim_time*90*20-60)"]
},
"leg_front_left4": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-90)*1.5)", "q.r.velocity_y(0)*15+(math.sin(q.anim_time*90*20-90)*1.5)"]
},
"leg_back_left": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*20)+(math.cos(q.anim_time*90*20-30)/4)", "15+q.r.velocity_y(0)*30+(math.sin(q.anim_time*90*20-30)/4)"]
},
"leg_back_left2": {
"rotation": [
1.78588,
"-1.6959-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-60)/2)",
"0.4116+q.r.velocity_y(0)*15+(math.sin(q.anim_time*90*20-60)/2)"
]
},
"leg_back_left3": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+math.cos(q.anim_time*90*20-90)", "q.r.velocity_y(0)*15+math.sin(q.anim_time*90*20-90)"]
},
"leg_back_left4": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-120)*2)", "q.r.velocity_y(0)*15+(math.sin(q.anim_time*90*20-120)*2)"]
},
"leg_front_right": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*10)-(math.cos(q.anim_time*90*20)/3)", "-15-q.r.velocity_y(0)*30-(math.sin(q.anim_time*90*20)/4)"],
"position": [0, "-math.clamp((q.r.velocity_y(0)*-1),0,1)", 0]
},
"leg_front_right2": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-30)/2)", "-q.r.velocity_y(0)*10-(math.sin(q.anim_time*90*20-30)/3)"],
"position": ["math.abs(q.r.velocity_y(0)*-1)", 0, 0]
},
"leg_front_right3": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*10)-math.cos(q.anim_time*90*20-60)", "-q.r.velocity_y(0)*15-math.sin(q.anim_time*90*20-60)"]
},
"leg_front_right4": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-90)*1.5)", "-q.r.velocity_y(0)*15-(math.sin(q.anim_time*90*20-90)*1.5)"]
},
"leg_back_right": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*20)-(math.cos(q.anim_time*90*20-30)/4)", "-15-q.r.velocity_y(0)*30-(math.sin(q.anim_time*90*20-30)/4)"]
},
"leg_back_right2": {
"rotation": [
1.78588,
"1.6959+math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-60)/2)",
"-0.4116-q.r.velocity_y(0)*15-(math.sin(q.anim_time*90*20-60)/2)"
]
},
"leg_back_right3": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-math.cos(q.anim_time*90*20-90)", "-q.r.velocity_y(0)*15-math.sin(q.anim_time*90*20-90)"]
},
"leg_back_right4": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-120)*2)", "-q.r.velocity_y(0)*15-(math.sin(q.anim_time*90*20-120)*2)"]
}
}
},
"animation.lapras.surfacewater_idle": {
"loop": true,
"bones": {
@@ -920,136 +802,6 @@
}
}
},
"animation.lapras.ride_surfacewater_swim": {
"loop": true,
"bones": {
"body": {
"rotation": [0, 0, "q.r.yaw_change(0)*-10"],
"position": [0, "0-math.abs(q.r.yaw_change(0))*0.5", 0]
},
"chest": {
"rotation": [0, "-q.r.yaw_change(0)*-10", 0]
},
"chest2": {
"rotation": [0, "-q.r.yaw_change(0)*-5", "q.r.yaw_change(0)*-15"]
},
"neck2": {
"rotation": [0, "-q.r.yaw_change(0)*-10", "q.r.yaw_change(0)*5"]
},
"neck3": {
"rotation": [0, "-q.r.yaw_change(0)*-10", "q.r.yaw_change(0)*2"]
},
"head_angle": {
"rotation": [0, "-q.r.yaw_change(0)*-20", "q.r.yaw_change(0)*7.5"]
},
"leg_front_left": {
"rotation": [0, 0, "q.r.yaw_change(0)*15"]
},
"leg_back_left": {
"rotation": [0, 0, "q.r.yaw_change(0)*15"]
},
"leg_front_right": {
"rotation": [0, 0, "q.r.yaw_change(0)*15"]
},
"leg_back_right": {
"rotation": [0, 0, "q.r.yaw_change(0)*15"]
}
}
},
"animation.lapras.ride_surfacewater_jump": {
"loop": true,
"bones": {
"body": {
"rotation": ["-q.r.velocity_y(0)*20-math.sin(q.anim_time*90*10+30)*-0.5", 0, 0]
},
"chest": {
"rotation": ["-0-math.sin(q.anim_time*90*10+30)*0.5", 0, 0]
},
"chest2": {
"rotation": ["-math.abs(q.r.velocity_y(0)*3)-math.sin(q.anim_time*90*10)*0.5", 0, 0]
},
"neck2": {
"rotation": ["-12.5-math.abs(q.r.velocity_y(0)*1.5)-math.sin(q.anim_time*90*10-30)*0.75", 0, 0]
},
"neck3": {
"rotation": ["-15-math.abs(q.r.velocity_y(0))-math.sin(q.anim_time*90*10-60)*0.75", 0, 0],
"position": [0, -1, 0]
},
"head": {
"rotation": ["10-math.clamp((q.r.velocity_y(0)*10),-10,0)-math.sin(q.anim_time*90*20-90)/2", 0, 0],
"position": [0, "math.clamp((q.r.velocity_y(0)*1),-1,0)", 0]
},
"head_angle": {
"rotation": ["-0-math.sin(q.anim_time*90*10-90)*0.3", 0, 0]
},
"tail": {
"rotation": ["-math.clamp((q.r.velocity_y(0)*30),-10,30)-(math.sin(q.anim_time*90*20)/2)", 0, 0]
},
"tail2": {
"rotation": ["-math.clamp((q.r.velocity_y(0)*20),-20,10)-(math.sin(q.anim_time*90*20-30)*1.5)", 0, 0]
},
"leg_front_left": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*10)+(math.cos(q.anim_time*90*20)/3)", "15+q.r.velocity_y(0)*30+(math.sin(q.anim_time*90*20)/4)"],
"position": [0, "-math.clamp((q.r.velocity_y(0)*-1),0,1)", 0]
},
"leg_front_left2": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-30)/2)", "q.r.velocity_y(0)*10+(math.sin(q.anim_time*90*20-30)/3)"],
"position": ["-math.abs(q.r.velocity_y(0)*-1)", 0, 0]
},
"leg_front_left3": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*10)+math.cos(q.anim_time*90*20-60)", "q.r.velocity_y(0)*15+math.sin(q.anim_time*90*20-60)"]
},
"leg_front_left4": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-90)*1.5)", "q.r.velocity_y(0)*15+(math.sin(q.anim_time*90*20-90)*1.5)"]
},
"leg_back_left": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*20)+(math.cos(q.anim_time*90*20-30)/4)", "15+q.r.velocity_y(0)*30+(math.sin(q.anim_time*90*20-30)/4)"]
},
"leg_back_left2": {
"rotation": [
1.78588,
"-1.6959-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-60)/2)",
"0.4116+q.r.velocity_y(0)*15+(math.sin(q.anim_time*90*20-60)/2)"
]
},
"leg_back_left3": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+math.cos(q.anim_time*90*20-90)", "q.r.velocity_y(0)*15+math.sin(q.anim_time*90*20-90)"]
},
"leg_back_left4": {
"rotation": [0, "-math.abs(q.r.velocity_y(0)*15)+(math.cos(q.anim_time*90*20-120)*2)", "q.r.velocity_y(0)*15+(math.sin(q.anim_time*90*20-120)*2)"]
},
"leg_front_right": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*10)-(math.cos(q.anim_time*90*20)/3)", "-15-q.r.velocity_y(0)*30-(math.sin(q.anim_time*90*20)/4)"],
"position": [0, "-math.clamp((q.r.velocity_y(0)*-1),0,1)", 0]
},
"leg_front_right2": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-30)/2)", "-q.r.velocity_y(0)*10-(math.sin(q.anim_time*90*20-30)/3)"],
"position": ["math.abs(q.r.velocity_y(0)*-1)", 0, 0]
},
"leg_front_right3": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*10)-math.cos(q.anim_time*90*20-60)", "-q.r.velocity_y(0)*15-math.sin(q.anim_time*90*20-60)"]
},
"leg_front_right4": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-90)*1.5)", "-q.r.velocity_y(0)*15-(math.sin(q.anim_time*90*20-90)*1.5)"]
},
"leg_back_right": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*20)-(math.cos(q.anim_time*90*20-30)/4)", "-15-q.r.velocity_y(0)*30-(math.sin(q.anim_time*90*20-30)/4)"]
},
"leg_back_right2": {
"rotation": [
1.78588,
"1.6959+math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-60)/2)",
"-0.4116-q.r.velocity_y(0)*15-(math.sin(q.anim_time*90*20-60)/2)"
]
},
"leg_back_right3": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-math.cos(q.anim_time*90*20-90)", "-q.r.velocity_y(0)*15-math.sin(q.anim_time*90*20-90)"]
},
"leg_back_right4": {
"rotation": [0, "math.abs(q.r.velocity_y(0)*15)-(math.cos(q.anim_time*90*20-120)*2)", "-q.r.velocity_y(0)*15-(math.sin(q.anim_time*90*20-120)*2)"]
}
}
},
"animation.lapras.water_idle": {
"loop": true,
"bones": {
@@ -8,8 +8,8 @@
"body": {
"position": [
0,
"5.5+math.sin(q.anim_time*90*2)*-0.3+math.sin(q.anim_time*90*2+60)*-0.3",
"-8+math.sin(q.anim_time*90*2+60)*-0.3+math.sin(q.anim_time*90*2)*-0.3"
"1+math.sin(q.anim_time*90*2)*-0.3+math.sin(q.anim_time*90*2+60)*-0.3",
"-8+math.sin(q.anim_time*90*2+60)*-0.3+math.sin(q.anim_time*90*2)*-0.2"
]
},
"neck": {
@@ -26,21 +26,21 @@
"rotation": [0, "65+math.sin(q.anim_time*90*2-120)*-2", "-(math.sin(q.anim_time*90*2-120)*2)"]
},
"segment1": {
"rotation": ["12+math.sin(q.anim_time*90*2+60)*2", -5.37, 8.45]
"rotation": ["32+math.sin(q.anim_time*90*2+60)*2", -5.37, 8.45]
},
"segment2": {
"rotation": ["31+math.sin(q.anim_time*90*2)*3", 2, -10],
"rotation": ["36+math.sin(q.anim_time*90*2)*3", 2, -10],
"position": [-0.3, 1.25, 0]
},
"segment3": {
"rotation": [
"44.3062+math.sin(q.anim_time*90*2)*-3+math.sin(q.anim_time*90*2+60)*-2",
"21.8062+math.sin(q.anim_time*90*2)*-3+math.sin(q.anim_time*90*2+60)*-2",
"3.7251+math.sin(q.anim_time*90*2+30)*-1",
"3.8029+math.sin(q.anim_time*90*2-30)*1"
"-18.6971+math.sin(q.anim_time*90*2-30)*1"
]
},
"segment4": {
"rotation": [0.52696, "math.sin(q.anim_time*90*2-90)*-2.0687", "42.509+math.sin(q.anim_time*90*2-60)*2"],
"rotation": [0.52696, "math.sin(q.anim_time*90*2-90)*-2.0687", "22.509+math.sin(q.anim_time*90*2-60)*2"],
"position": [0, 0, -0.1]
},
"segment5": {
@@ -63,7 +63,7 @@
"bones": {
"body": {
"rotation": [0, "math.sin(q.anim_time*90*2)*10", 0],
"position": ["math.sin(q.anim_time*90*2-90)*-2", 0.5, "-8+math.sin(q.anim_time*90*4-30)*-0.3"]
"position": ["math.sin(q.anim_time*90*2-90)*-2", 0, "-8+math.sin(q.anim_time*90*4-30)*-0.3"]
},
"neck": {
"rotation": ["10+math.sin(q.anim_time*90*4-0)*4", 0, "math.sin(q.anim_time*90*2-90)*8"],
@@ -112,7 +112,7 @@
"bones": {
"body": {
"rotation": [20, "math.sin(q.anim_time*90*4)*10", 0],
"position": ["math.sin(q.anim_time*90*4-90)*-4", -2, -9]
"position": ["math.sin(q.anim_time*90*4-90)*-4", -2.5, -9]
},
"neck": {
"rotation": ["37.5+math.sin(q.anim_time*90*8-30)*3", 0, "math.sin(q.anim_time*90*4-90)*8"],
@@ -625,32 +625,6 @@
"lerp_mode": "catmullrom"
}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.4167": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.0": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.4167": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"1.0": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
}
},
"sound_effects": {
@@ -660,149 +634,21 @@
}
},
"animation.dratini.blink": {
"animation_length": 0.1667,
"animation_length": 0.16667,
"bones": {
"eyelid_left": {
"position": {
"0.0": [0.1, 0, -0.1],
"0.1667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
"0.125": [0.1, 0, -0.1],
"0.1667": [0, 0, 0]
}
},
"eyelid_right": {
"position": {
"0.0": [-0.1, 0, -0.1],
"0.1667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
"0.125": [-0.1, 0, -0.1],
"0.1667": [0, 0, 0]
}
},
"eye_left": {
"position": {
"0.0": [-0.1, 0, 0.1],
"0.1667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]}
}
},
"eye_right": {
"position": {
"0.0": [0.1, 0, 0.1],
"0.1667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_ditto": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_blink_ditto": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
}
},
"animation.dratini.angry": {
"loop": true,
"bones": {
"pupil_left": {
"position": [0, -0.6, 0]
},
"eye_angry_left": {
"position": [0.1, 0, -0.1]
},
"eye_angry_right": {
"position": [-0.1, 0, -0.1]
},
"pupil_right": {
"position": [0, -0.6, 0]
}
}
},
"animation.dratini.sad": {
"loop": true,
"bones": {
"eye_sad_left": {
"position": [0.1, 0, -0.1]
},
"eye_sad_right": {
"position": [-0.1, 0, -0.1]
}
}
},
"animation.dratini.happy": {
"loop": true,
"bones": {
"mouth": {
"position": [0, -0.1, 0]
},
"eyelid_happy_left": {
"position": [0.1, 0, -0.1]
},
"eyelid_happy_right": {
"position": [-0.1, 0, -0.1]
}
}
},
"animation.dratini.hurt": {
"loop": true,
"bones": {
"eyelid_recoil_left": {
"position": [0.1, 0, -0.1]
},
"eyelid_recoil_right": {
"position": [-0.1, 0, -0.1]
}
}
},
"animation.dratini.ditto_face": {
"loop": true,
"bones": {
"face": {
"position": [0, 0, 0.1],
"scale": 0
},
"face_ditto": {
"position": [0, 0, -0.1]
}
}
},
"animation.dratini.render": {
"loop": true,
"bones": {
"body": {
"rotation": [0, -17.5, 0]
},
"neck": {
"rotation": [15, 0, 0]
},
"head": {
"rotation": [-15.77241, 45.41054, -21.63402]
},
"head2": {
"rotation": [-27.5, 0, 0]
},
"segment1": {
"rotation": [45, 0, 0]
},
"segment2": {
"rotation": [37.5, 0, 0]
},
"segment3": {
"rotation": [7.5, 0, 20]
},
"segment4": {
"rotation": [-2.5, 0, 27.5]
},
"segment5": {
"rotation": [-5, 0, 32.5]
},
"segment6": {
"rotation": [0, 0, 40]
},
"segment7": {
"rotation": [-7.5, 0, 37.5]
},
"segment8": {
"rotation": [-5, 0, 32.5]
}
}
}
@@ -6,10 +6,10 @@
"animation_length": 4,
"bones": {
"body": {
"position": [1, "math.sin(q.anim_time*90*1+60)*-0.5", "math.sin(q.anim_time*90*1+60)*-0.4"]
"position": [0, "math.sin(q.anim_time*90*1+60)*-0.5", "math.sin(q.anim_time*90*1+60)*-0.4"]
},
"neck4": {
"rotation": ["7.5+math.sin(q.anim_time*90*1-150)*3", -7.5, 0]
"neck3": {
"rotation": ["-10+math.sin(q.anim_time*90*1-150)*3", -7.5, 0]
},
"gem": {
"rotation": [-15, 0, 0]
@@ -18,38 +18,38 @@
"rotation": ["17+math.sin(q.anim_time*90*1-120)*-2+math.sin(q.anim_time*90*1)*-6", 0.05179, 0.04188]
},
"neck2": {
"rotation": ["-17.9656+math.sin(q.anim_time*90*1-60)*5", 1.67701, 16.75809]
"rotation": ["-15+math.sin(q.anim_time*90*1-60)*5", -4.9407, 0.54193]
},
"neck": {
"rotation": ["8.1465+math.sin(q.anim_time*90*1)*4", 15.66212, -17.75207],
"rotation": ["12.5+math.sin(q.anim_time*90*1)*4", 12.5, 0],
"position": [0.2, 0, 0.8]
},
"segment1": {
"rotation": ["41.1364+math.sin(q.anim_time*90*1+60)*5", 34.38879, -21.62284]
"rotation": ["47.547+math.sin(q.anim_time*90*1+60)*5", 12, 0.34277]
},
"segment2": {
"rotation": ["43.0311+math.sin(q.anim_time*90*1+60)*-5", 0.98082, -5.0687]
"rotation": ["37.8179+math.sin(q.anim_time*90*1+60)*-5", -5.78965, 2.36827]
},
"segment3": {
"rotation": [25.85914, -3.20053, "31.4955+math.sin(q.anim_time*90*1+30)*1"],
"rotation": [3.74777, -2.73501, "24+math.sin(q.anim_time*90*1+30)*1"],
"position": [0, 0, 0.2]
},
"segment5": {
"segment4": {
"rotation": [-1.36519, 0.54554, "32+math.sin(q.anim_time*90*1)*2"],
"position": [0, 0, 0]
},
"segment6": {
"rotation": [-8.15081, -3.98475, "37+math.sin(q.anim_time*90*1-60)*3"],
"segment5": {
"rotation": [-0.65081, -3.98475, "37+math.sin(q.anim_time*90*1-60)*3"],
"position": [0, 0, 0]
},
"segment6": {
"rotation": ["17+math.sin(q.anim_time*90*1)*-4", -0.87703, "20+math.sin(q.anim_time*90*1-120)*10"]
},
"segment7": {
"rotation": ["25+math.sin(q.anim_time*90*1-40)*-7", -0.85406, "10+math.sin(q.anim_time*90*1-150)*15"]
},
"segment8": {
"rotation": ["28.8172+math.sin(q.anim_time*90*1)*-4", -10.97137, "33.1904+math.sin(q.anim_time*90*1-120)*10"]
},
"segment9": {
"rotation": ["27.0216+math.sin(q.anim_time*90*1-40)*-7", 7.93873, "29.4413+math.sin(q.anim_time*90*1-150)*15"]
},
"segment10": {
"rotation": ["30.079+math.sin(q.anim_time*90*1-80)*-12", -6.29684, "-31.5806+math.sin(q.anim_time*90*1-180)*25"]
"rotation": ["16+math.sin(q.anim_time*90*1-80)*-12", 1.70246, "15+math.sin(q.anim_time*90*1-180)*25"]
},
"mouth": {
"position": [0, 0, 0]
@@ -65,27 +65,6 @@
},
"gem_tail2": {
"position": [0, -1, 0]
},
"head_rotation": {
"rotation": [-0.40083, -4.06131, -0.53742]
},
"neck3": {
"rotation": [-5, 0, 0]
},
"segment4": {
"rotation": [5.25766, -11.2531, 22.47096]
},
"segment7": {
"rotation": [25, 0, 17.5]
},
"segment11": {
"rotation": [22.5, 0, -2.5]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -95,9 +74,9 @@
"bones": {
"body": {
"rotation": [0, "math.sin(q.anim_time*90*2)*15", 0],
"position": ["math.sin(q.anim_time*90*2-90)*-4", 1, 0]
"position": ["math.sin(q.anim_time*90*2-90)*-4", 0, 0]
},
"neck4": {
"neck3": {
"rotation": ["-7.5+math.sin(q.anim_time*90*4-90)*-3", 0, "math.sin(q.anim_time*90*2-90)*3"]
},
"gem": {
@@ -122,19 +101,19 @@
"segment3": {
"rotation": [3.24777, 0, "math.sin(q.anim_time*90*2-130)*-10"]
},
"segment5": {
"segment4": {
"rotation": [0.63481, 0, "math.sin(q.anim_time*90*2-160)*-14"]
},
"segment6": {
"segment5": {
"rotation": ["math.sin(q.anim_time*90*4-12)*-1-1", 0, "math.sin(q.anim_time*90*2-170)*-18"]
},
"segment8": {
"segment6": {
"rotation": ["17+math.sin(q.anim_time*90*4-30)*-3", 0, "math.sin(q.anim_time*90*2-230)*-22"]
},
"segment9": {
"segment7": {
"rotation": ["10+math.sin(q.anim_time*90*4-90)*-5", 0, "math.sin(q.anim_time*90*2-270)*-26"]
},
"segment10": {
"segment8": {
"rotation": ["math.sin(q.anim_time*90*4-90)*-8", 0, "math.sin(q.anim_time*90*2-310)*-30"]
},
"mouth": {
@@ -151,12 +130,6 @@
},
"gem_tail2": {
"position": [0, -1, 0]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -166,9 +139,9 @@
"bones": {
"body": {
"rotation": [0, "math.sin(q.anim_time*90*4)*15", 0],
"position": ["math.sin(q.anim_time*90*4-90)*-4", -1, 0]
"position": ["math.sin(q.anim_time*90*4-90)*-4", -2, 0]
},
"neck4": {
"neck3": {
"rotation": ["-15+math.sin(q.anim_time*90*8-90)*-3", 0, "0+math.sin(q.anim_time*90*4-90)*3"]
},
"gem": {
@@ -193,19 +166,19 @@
"segment3": {
"rotation": [0.74777, 0, "math.sin(q.anim_time*90*4-130)*-10"]
},
"segment5": {
"segment4": {
"rotation": [0.63481, 0, "math.sin(q.anim_time*90*4-160)*-14"]
},
"segment6": {
"segment5": {
"rotation": ["math.sin(q.anim_time*90*8-12)*-1-1", 0, "math.sin(q.anim_time*90*4-170)*-18"]
},
"segment8": {
"segment6": {
"rotation": ["17+math.sin(q.anim_time*90*8-30)*-3", 0, "math.sin(q.anim_time*90*4-230)*-22"]
},
"segment9": {
"segment7": {
"rotation": ["10+math.sin(q.anim_time*90*8-90)*-5", 0, "math.sin(q.anim_time*90*4-270)*-26"]
},
"segment10": {
"segment8": {
"rotation": ["math.sin(q.anim_time*90*8-90)*-8", 0, "math.sin(q.anim_time*90*4-310)*-30"]
},
"mouth": {
@@ -223,15 +196,9 @@
"gem_tail2": {
"position": [0, -1, 0]
},
"head_rotation": {
"head2": {
"rotation": [-10, 0, 0],
"position": [0, 0, 0.6]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -240,9 +207,9 @@
"animation_length": 4,
"bones": {
"body": {
"position": [0, "4+math.sin(q.anim_time*90*1+60)*-0.5", "math.sin(q.anim_time*90*1+60)*-0.4"]
"position": [0, "2.75+math.sin(q.anim_time*90*1+60)*-0.5", "math.sin(q.anim_time*90*1+60)*-0.4"]
},
"neck4": {
"neck3": {
"rotation": ["-10+math.sin(q.anim_time*90*1-150)*3", -7.5, 0]
},
"gem": {
@@ -265,32 +232,32 @@
"rotation": ["17.8179+math.sin(q.anim_time*90*1+60)*-5", -5.78965, 2.36827]
},
"segment3": {
"rotation": [21.8, -2.73501, "24+math.sin(q.anim_time*90*1+30)*1"],
"rotation": [18.74777, -2.73501, "24+math.sin(q.anim_time*90*1+30)*1"],
"position": [0, 0, 0.2]
},
"segment5": {
"segment4": {
"rotation": [-1.36519, 0.54554, "32+math.sin(q.anim_time*90*1)*2"],
"position": [0, 0, 0]
},
"segment6": {
"segment5": {
"rotation": [-0.65081, -3.98475, "37+math.sin(q.anim_time*90*1-60)*3+math.sin(q.anim_time*90*12-30)*-0.5"],
"position": [0, 0, 0]
},
"segment8": {
"segment6": {
"rotation": [
"17+math.sin(q.anim_time*90*1)*-4+math.sin(q.anim_time*90*4)*-1",
-0.87703,
"20+math.sin(q.anim_time*90*1-120)*10+math.sin(q.anim_time*90*12-90)*-2"
]
},
"segment9": {
"segment7": {
"rotation": [
"25+math.sin(q.anim_time*90*1-40)*-7+math.sin(q.anim_time*90*4-60)*-6",
-0.85406,
"37+math.sin(q.anim_time*90*1-60)*3+math.sin(q.anim_time*90*12-150)*-8"
]
},
"segment10": {
"segment8": {
"rotation": [
"16+math.sin(q.anim_time*90*1-80)*-12+math.sin(q.anim_time*90*4-120)*-12",
1.70246,
@@ -311,12 +278,6 @@
},
"gem_tail2": {
"position": [0, -1, 0]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -335,14 +296,14 @@
"neck2": {
"rotation": ["-20+math.sin(q.anim_time*90*0.5+120)*12", 0, 0]
},
"neck4": {
"neck3": {
"rotation": ["-20+math.sin(q.anim_time*90*0.5+90)*5", 0, 0]
},
"head": {
"rotation": ["22.5+math.sin(q.anim_time*90*0.5+120)*-8", "math.sin(q.anim_time*90*1)*-2", 0],
"position": [0, -0.5, 0.5]
},
"head_rotation": {
"head2": {
"rotation": [-20, 0, 0],
"position": [0, 0, 0.5]
},
@@ -363,26 +324,20 @@
"rotation": ["13+math.sin(q.anim_time*90*0.5+30)*-5", 0, "math.sin(q.anim_time*90*1-120)*-3"],
"position": ["math.sin(q.anim_time*90*1-120)*0.1", 0, 0]
},
"segment5": {
"segment4": {
"rotation": ["7.5+math.sin(q.anim_time*90*0.5-30)*-7", 0, "math.sin(q.anim_time*90*1-160)*-5"]
},
"segment6": {
"segment5": {
"rotation": ["6+math.sin(q.anim_time*90*0.5-60)*-10", 0, "math.sin(q.anim_time*90*1-180)*-6"]
},
"segment8": {
"segment6": {
"rotation": ["10+math.sin(q.anim_time*90*0.5-90)*-14", 0, "math.sin(q.anim_time*90*1-200)*-7"]
},
"segment9": {
"segment7": {
"rotation": ["math.sin(q.anim_time*90*0.5-120)*-17.5", 0, "math.sin(q.anim_time*90*1-230)*-8"]
},
"segment10": {
"segment8": {
"rotation": ["math.sin(q.anim_time*90*0.5-150)*-20-20", 0, "math.sin(q.anim_time*90*1-260)*-10"]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -401,14 +356,14 @@
"neck2": {
"rotation": ["math.sin(q.anim_time*90*1+40)*2", 0, "math.sin(q.anim_time*90*2+90)*-8"]
},
"neck4": {
"neck3": {
"rotation": ["math.sin(q.anim_time*90*1+10)*2", 0, "math.sin(q.anim_time*90*2+150)*-8"]
},
"head": {
"rotation": [-90, 0, 0],
"position": [0, 1, -1.5]
},
"head_rotation": {
"head2": {
"rotation": ["math.sin(q.anim_time*90*1+60)*2", "math.sin(q.anim_time*90*2+190)*9", 0]
},
"wing_left": {
@@ -426,26 +381,20 @@
"segment3": {
"rotation": ["math.sin(q.anim_time*90*1-60)*4", 0, "math.sin(q.anim_time*90*2-120)*-8"]
},
"segment5": {
"segment4": {
"rotation": ["math.sin(q.anim_time*90*1-90)*6", 0, "math.sin(q.anim_time*90*2-150)*-10"]
},
"segment6": {
"segment5": {
"rotation": ["math.sin(q.anim_time*90*1-120)*8", 0, "math.sin(q.anim_time*90*2-180)*-14"]
},
"segment8": {
"segment6": {
"rotation": ["math.sin(q.anim_time*90*1-150)*12", 0, "math.sin(q.anim_time*90*2-210)*-17"]
},
"segment9": {
"segment7": {
"rotation": ["math.sin(q.anim_time*90*1-180)*18", 0, "math.sin(q.anim_time*90*2-240)*-21"]
},
"segment10": {
"segment8": {
"rotation": ["math.sin(q.anim_time*90*1-210)*25", 0, "math.sin(q.anim_time*90*2-270)*-28"]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -464,14 +413,14 @@
"neck2": {
"rotation": ["-22.5+math.sin(q.anim_time*90*1+120)*2", 0, 0]
},
"neck4": {
"neck3": {
"rotation": ["-17.5+math.sin(q.anim_time*90*1+90)*4", 0, 0]
},
"head": {
"rotation": ["27.5+math.sin(q.anim_time*90*1+120)*-6", "math.sin(q.anim_time*90*1)*-2", 0],
"position": [0, -0.5, 0.5]
},
"head_rotation": {
"head2": {
"rotation": [-22.5, 0, 0],
"position": [0, 0, 0.5]
},
@@ -492,26 +441,20 @@
"rotation": ["13+math.sin(q.anim_time*90*0.5+30)*-3", 0, "math.sin(q.anim_time*90*1-120)*-3"],
"position": ["math.sin(q.anim_time*90*1-120)*0.1", 0, 0]
},
"segment5": {
"segment4": {
"rotation": ["7.5+math.sin(q.anim_time*90*0.5-30)*-4", 0, "math.sin(q.anim_time*90*1-160)*-5"]
},
"segment6": {
"segment5": {
"rotation": ["-9+math.sin(q.anim_time*90*0.5-60)*-5", 0, "math.sin(q.anim_time*90*1-180)*-6"]
},
"segment8": {
"segment6": {
"rotation": ["-10+math.sin(q.anim_time*90*0.5-90)*-6", 0, "math.sin(q.anim_time*90*1-200)*-7"]
},
"segment9": {
"segment7": {
"rotation": ["-12.5+math.sin(q.anim_time*90*0.5-120)*-10", 0, "math.sin(q.anim_time*90*1-230)*-8"]
},
"segment10": {
"segment8": {
"rotation": ["-15+math.sin(q.anim_time*90*0.5-150)*-15", 0, "math.sin(q.anim_time*90*1-260)*-10"]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -530,7 +473,7 @@
"neck2": {
"rotation": ["-20+math.sin(q.anim_time*90*1+30)*3", 0, "math.sin(q.anim_time*90*2+90)*-2"]
},
"neck4": {
"neck3": {
"rotation": ["-17.5+math.sin(q.anim_time*90*1)*3", 0, "math.sin(q.anim_time*90*2+150)*-2"]
},
"head": {
@@ -551,26 +494,20 @@
"segment3": {
"rotation": ["7.5+math.sin(q.anim_time*90*1-60)*4", 0, "math.sin(q.anim_time*90*2-120)*-8"]
},
"segment5": {
"segment4": {
"rotation": ["7+math.sin(q.anim_time*90*1-90)*3", 0, "math.sin(q.anim_time*90*2-150)*-10"]
},
"segment6": {
"segment5": {
"rotation": ["math.sin(q.anim_time*90*1-120)*4", 0, "math.sin(q.anim_time*90*2-180)*-14"]
},
"segment8": {
"segment6": {
"rotation": ["math.sin(q.anim_time*90*1-150)*6", 0, "math.sin(q.anim_time*90*2-210)*-17"]
},
"segment9": {
"segment7": {
"rotation": ["math.sin(q.anim_time*90*1-150)*6", 0, "math.sin(q.anim_time*90*2-240)*-21"]
},
"segment10": {
"segment8": {
"rotation": ["-12+math.sin(q.anim_time*90*1-210)*16", 0, "math.sin(q.anim_time*90*2-270)*-28"]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
}
}
},
@@ -579,7 +516,7 @@
"animation_length": 8,
"bones": {
"body": {
"position": [-2, -4, -0.25]
"position": [0, -5.02199, -0.25981]
},
"neck": {
"rotation": ["91.5726+math.sin(q.anim_time*90*0.5)*1", -54.1247, 0.49087],
@@ -589,19 +526,19 @@
"rotation": ["-0.3596+math.sin(q.anim_time*90*0.5)*1", -2.43635, 39.13885],
"position": [0, 0, -0.5]
},
"neck4": {
"neck3": {
"rotation": ["2.5+math.sin(q.anim_time*90*0.5)*-2", 0, 32.5]
},
"head": {
"rotation": [-2.59808, 0, 0]
},
"eyelid_left": {
"position": [0.1, 0, -0.1]
"position": [0.1, 0, 0]
},
"eyelid_right": {
"position": [-0.1, 0, -0.1]
"position": [-0.1, 0, 0]
},
"head_rotation": {
"head2": {
"rotation": ["-85.7351+math.sin(q.anim_time*90*0.5-60)*2", 3.45429, 44.2998],
"position": [0.75, -2.5, 0.5]
},
@@ -622,39 +559,21 @@
"rotation": [-4.20405, 5.6842, -36.7242],
"position": [-0.5, 0.75, 0]
},
"segment5": {
"segment4": {
"rotation": ["-1.9856+math.sin(q.anim_time*90*0.5-30)*1", -4.26772, -40.83982],
"position": [0, 0.75, -0.1]
},
"segment6": {
"segment5": {
"rotation": ["-2.3291+math.sin(q.anim_time*90*0.5-60)*-1", -1.52401, -37.1775]
},
"segment8": {
"segment6": {
"rotation": ["0.9256+math.sin(q.anim_time*90*0.5-90)*-2", 0.29269, -49.14743]
},
"segment9": {
"segment7": {
"rotation": ["-9.9963+math.sin(q.anim_time*90*0.5-120)*-4", -8.1283, -41.61724]
},
"segment10": {
"segment8": {
"rotation": ["math.sin(q.anim_time*90*0.5-150)*-10.9703", 3.1679, -57.39212]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
},
"eye_left": {
"position": [-0.1, 0, 0.1]
},
"eye_right": {
"position": [0.1, 0, 0.1]
},
"eyes_ditto": {
"position": [0, 0, 0.1]
},
"eyes_blink_ditto": {
"position": [0, 0, -0.1]
}
}
},
@@ -673,7 +592,7 @@
"neck2": {
"rotation": ["10+math.sin(q.anim_time*90*0.5+120)*12", 0, 0]
},
"neck4": {
"neck3": {
"rotation": ["15+math.sin(q.anim_time*90*0.5+90)*5", 0, 0]
},
"head": {
@@ -681,12 +600,12 @@
"position": [0, -0.5, 0.5]
},
"eyelid_left": {
"position": [0.1, 0, -0.1]
"position": [0.1, 0, 0]
},
"eyelid_right": {
"position": [-0.1, 0, -0.1]
"position": [-0.1, 0, 0]
},
"head_rotation": {
"head2": {
"rotation": [-5, 0, 0],
"position": [0, 0, -0.5]
},
@@ -707,38 +626,20 @@
"rotation": ["-19.5+math.sin(q.anim_time*90*0.5+30)*-5", 0, "math.sin(q.anim_time*90*1-120)*-3"],
"position": ["math.sin(q.anim_time*90*1-120)*0.1", 0, 0]
},
"segment5": {
"segment4": {
"rotation": ["-22.5+math.sin(q.anim_time*90*0.5-30)*-7", 0, "math.sin(q.anim_time*90*1-160)*-5"]
},
"segment6": {
"segment5": {
"rotation": ["-26.5+math.sin(q.anim_time*90*0.5-60)*-10", 0, "math.sin(q.anim_time*90*1-180)*-6"]
},
"segment8": {
"segment6": {
"rotation": ["-30+math.sin(q.anim_time*90*0.5-90)*-14", 0, "math.sin(q.anim_time*90*1-200)*-7"]
},
"segment9": {
"segment7": {
"rotation": ["-31.5+math.sin(q.anim_time*90*0.5-120)*-17.5", 0, "math.sin(q.anim_time*90*1-230)*-8"]
},
"segment10": {
"segment8": {
"rotation": ["math.sin(q.anim_time*90*0.5-150)*-20+2.5", 0, "math.sin(q.anim_time*90*1-260)*-10"]
},
"wing_open_left": {
"scale": 0
},
"wing_open_right": {
"scale": 0
},
"eye_left": {
"position": [-0.1, 0, 0.1]
},
"eye_right": {
"position": [0.1, 0, 0.1]
},
"eyes_ditto": {
"position": [0, 0, 0.1]
},
"eyes_blink_ditto": {
"position": [0, 0, -0.1]
}
}
},
@@ -793,7 +694,7 @@
}
}
},
"neck4": {
"neck3": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
@@ -901,20 +802,6 @@
"lerp_mode": "catmullrom"
}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.4583": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.0": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.4583": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.0": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
},
"sound_effects": {
@@ -924,151 +811,26 @@
}
},
"animation.dragonair.blink": {
"animation_length": 0.1667,
"animation_length": 0.16667,
"bones": {
"eyelid_left": {
"position": {
"0.0": [0.1, 0, -0.1],
"0.1667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
"0.0": [0.1, 0, 0],
"0.125": [0.1, 0, 0],
"0.1667": [0, 0, 0]
}
},
"eyelid_right": {
"position": {
"0.0": [-0.1, 0, -0.1],
"0.1667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
}
},
"eye_left": {
"position": {
"0.0": [-0.1, 0, 0.1],
"0.1667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]}
}
},
"eye_right": {
"position": {
"0.0": [0.1, 0, 0.1],
"0.1667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_ditto": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_blink_ditto": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
"0.0": [-0.1, 0, 0],
"0.125": [-0.1, 0, 0],
"0.1667": [0, 0, 0]
}
}
}
},
"animation.dragonair.open_wings": {
"loop": true,
"bones": {
"wing_left": {
"scale": 0
},
"wing_right": {
"scale": 0
},
"wing_open_left": {
"rotation": [0, 55, 0]
},
"wing_open_left2": {
"rotation": [-5, 0, 0]
},
"wing_open_right": {
"rotation": [0, -55, 0]
},
"wing_open_right2": {
"rotation": [-5, 0, 0]
}
}
},
"animation.dragonair.ditto_face": {
"loop": true,
"bones": {
"face": {
"position": [0, 0, 0.1],
"scale": 0
},
"face_ditto": {
"position": [0, 0, -0.1]
}
}
},
"animation.dragonair.render": {
"loop": true,
"bones": {
"body": {
"rotation": [10.80524, -22.13991, -4.11405]
},
"neck": {
"rotation": [23.98295, -6.80058, 23.80662]
},
"neck2": {
"rotation": [-24.66786, -6.27015, -13.6836]
},
"neck3": {
"rotation": [-17.43656, -0.9762, -7.43656]
},
"neck4": {
"rotation": [7.5, 0, 0]
},
"head": {
"rotation": [15, 0, 0]
},
"head_rotation": {
"rotation": [-1.10693, -12.45167, 5.12076]
},
"wing_left": {
"rotation": [0, 17.5, 0]
},
"wing_open_left": {
"scale": 0
},
"wing_right": {
"rotation": [0, -17.5, 0]
},
"wing_open_right": {
"scale": 0
},
"segment1": {
"rotation": [43.90051, -28.53623, 32.94098]
},
"segment2": {
"rotation": [22.47096, 11.2531, -25.25766]
},
"segment3": {
"rotation": [25.95571, 1.37878, -20.05795]
},
"segment4": {
"rotation": [2.5, 0, -40]
},
"segment5": {
"rotation": [-9.99067, -0.43399, -39.96207]
},
"segment6": {
"rotation": [10.95862, 5.35355, -32.10382]
},
"segment7": {
"rotation": [11.3131, 3.45947, -13.97891]
},
"segment8": {
"rotation": [6.35826, 5.38943, -14.05092]
},
"segment9": {
"rotation": [24.14743, 7.43547, -13.06431]
},
"segment10": {
"rotation": [45, 0, 0]
},
"segment11": {
"rotation": [17.5, 0, 0]
}
}
"animation.dragonair.new": {
"loop": true
}
}
}
@@ -70,6 +70,201 @@
}
}
},
"animation.lanturn.ground_walk": {
"loop": true,
"animation_length": 1.33333,
"bones": {
"torso": {
"rotation": ["18.5323-1*math.cos(q.anim_time*90*6+30)*-1", "8*math.cos(q.anim_time*90*3+30)*1", "2*math.cos(q.anim_time*90*3+30)*1"],
"position": [0, "-0.1+0.3*math.sin(q.anim_time*90*6+30)*1", 0]
},
"arm_left": {
"rotation": {
"0.0": [27.13972, 17.81489, 54.80802],
"0.5": [-9.78627, -11.33853, 53.65617],
"0.6667": {
"pre": [-11.47, -13.08, 42.11],
"post": [-11.47, -13.08, 42.11],
"lerp_mode": "catmullrom"
},
"0.8333": {
"post": [-8.23014, -10.8395, 27.91971],
"lerp_mode": "catmullrom"
},
"0.9583": {
"post": [-3.82491, -6.18459, 13.68449],
"lerp_mode": "catmullrom"
},
"1.125": {
"post": [0.38257, 5.03012, 2.61807],
"lerp_mode": "catmullrom"
},
"1.3333": [27.13972, 17.81489, 54.80802]
},
"position": {
"0.0": [0.6, -0.2, -0.3],
"0.25": [-0.56, -0.2, -0.7],
"0.5": [-0.63, -0.2, -0.9],
"0.6667": [-0.51, -0.2, -0.65],
"0.8333": [-0.4, -0.2, -0.4],
"1.3333": [0.6, -0.2, -0.3]
}
},
"arm_left2": {
"rotation": {
"0.0": [0, 0, -51],
"0.25": {
"pre": [0, 0, -53.5],
"post": [0, 0, -53.5],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [0, 0, -48.55],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [0, 0, -31.44],
"lerp_mode": "catmullrom"
},
"0.9167": {
"post": [0, 0, 6.71],
"lerp_mode": "catmullrom"
},
"1.0417": {
"post": [0, 0, 25.7],
"lerp_mode": "catmullrom"
},
"1.125": {
"post": [0, 0, 4.89],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [0, 0, -48.1],
"lerp_mode": "catmullrom"
},
"1.3333": [0, 0, -51]
}
},
"arm_right": {
"rotation": {
"0.0": {
"post": [-11.47, 13.08, -42.11],
"lerp_mode": "catmullrom"
},
"0.1667": {
"post": [-8.23014, 10.8395, -27.91971],
"lerp_mode": "catmullrom"
},
"0.2917": {
"post": [-3.82491, 6.18459, -13.68449],
"lerp_mode": "catmullrom"
},
"0.4583": {
"post": [0.38257, -5.03012, -2.61807],
"lerp_mode": "catmullrom"
},
"0.6667": [27.13972, -17.81489, -54.80802],
"1.1667": [-9.78627, 11.33853, -53.65617],
"1.3333": [-11.47, 13.08, -42.11]
},
"position": {
"0.0": [0.51, -0.2, -0.65],
"0.1667": [0.4, -0.2, -0.4],
"0.6667": [-0.6, -0.2, -0.3],
"0.9167": [0.56, -0.2, -0.7],
"1.1667": [0.63, -0.2, -0.9],
"1.3333": [0.51, -0.2, -0.65]
}
},
"arm_right2": {
"rotation": {
"0.0": {
"post": [0, 0, 31.44],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [0, 0, -6.71],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [0, 0, -25.7],
"lerp_mode": "catmullrom"
},
"0.4583": {
"post": [0, 0, -4.89],
"lerp_mode": "catmullrom"
},
"0.5833": {
"post": [0, 0, 48.1],
"lerp_mode": "catmullrom"
},
"0.6667": [0, 0, 51],
"0.9167": {
"pre": [0, 0, 53.5],
"post": [0, 0, 53.5],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [0, 0, 48.55],
"lerp_mode": "catmullrom"
},
"1.3333": {
"post": [0, 0, 31.44],
"lerp_mode": "catmullrom"
}
}
},
"head": {
"rotation": ["-13.4677-1*math.cos(q.anim_time*90*6+30)*-1", "8*math.cos(q.anim_time*90*3+40)*-1", 0]
},
"stem": {
"rotation": ["-0.5*math.sin(q.anim_time*90*6-30)*1", "1-5*math.sin(q.anim_time*90*3-150)*1", "1*math.sin(q.anim_time*90*6-10)*1"]
},
"stem2": {
"rotation": ["50-0.5*math.sin(q.anim_time*90*6-40)*1", 0, 0]
},
"stem3": {
"rotation": ["35-0.5*math.sin(q.anim_time*90*6-80)*1", 0, 0]
},
"stem4": {
"rotation": ["30-1*math.sin(q.anim_time*90*6-100)*1", 0, 0]
},
"stem5": {
"rotation": ["30-0.5*math.sin(q.anim_time*90*6-90)*1", 0, 0]
},
"stem6": {
"rotation": ["30-3*math.sin(q.anim_time*90*6-150)*1", 0, 0]
},
"stem7": {
"rotation": ["-65.75+5*math.sin(q.anim_time*90*6-50)*1", 0, 0],
"position": [0, -0.9, 0]
},
"stem8": {
"rotation": ["-30.75+1*math.sin(q.anim_time*90*6-70)*1", 0, 0]
},
"stem9": {
"rotation": ["-25+1*math.sin(q.anim_time*90*6-100)*1", 0, 0]
},
"stem10": {
"rotation": ["-22.5+5*math.sin(q.anim_time*90*6-120)*1", 0, 0]
},
"tail": {
"rotation": [-20, "5*math.cos(q.anim_time*90*3+50)*-1", 0]
},
"tail2": {
"rotation": [7.5, "5*math.cos(q.anim_time*90*3+70)*-1", 0]
},
"tail3": {
"rotation": [7.5, "5*math.cos(q.anim_time*90*3+90)*-1", 0]
},
"tail4": {
"rotation": [10, "7*math.cos(q.anim_time*90*3+120)*-1", 0]
},
"body": {
"rotation": [0, "8*math.cos(q.anim_time*90*3)*1", 0]
}
}
},
"animation.lanturn.ground_battle_idle": {
"loop": true,
"animation_length": 2.66667,
@@ -1306,6 +1501,82 @@
"position": [0, 0, "-q.anim_time*90*0.2"]
}
}
},
"animation.lanturn.sleep": {
"loop": true,
"bones": {
"torso": {
"rotation": ["20+0.5*math.sin(q.anim_time*90*1+170)*1", 0, 0],
"position": [0, "-0.3+0.2*math.sin(q.anim_time*90*1-20)*1", 0]
},
"arm_left": {
"rotation": [0, "-0.5-0.5*math.sin(q.anim_time*90*1-20)*1", 58.5],
"position": [0, "0.2-0.2*math.sin(q.anim_time*90*1-20)*1", 0]
},
"arm_left2": {
"rotation": [0, 0, -58]
},
"arm_right": {
"rotation": [0, "0.5-0.5*math.sin(q.anim_time*90*1-20)*-1", -58.5],
"position": [0, "0.2-0.2*math.sin(q.anim_time*90*1-20)*1", 0]
},
"arm_right2": {
"rotation": [0, 0, 58]
},
"head": {
"rotation": ["1-1*math.sin(q.anim_time*90*1+130)*1.5", 0, 0],
"position": [0, 0, -0.6]
},
"eyelid_left": {
"position": [0.1, 0, 0]
},
"eyelid_right": {
"position": [-0.1, 0, 0]
},
"stem": {
"rotation": ["-3*math.sin(q.anim_time*90*1-30)*1", "1-1*math.sin(q.anim_time*90*1-90)*-1", "1*math.sin(q.anim_time*90*1-10)*1"]
},
"stem2": {
"rotation": ["50-0.25*math.sin(q.anim_time*90*1-40)*1", 0, 0]
},
"stem3": {
"rotation": ["35-1*math.sin(q.anim_time*90*1-80)*1", 0, 0]
},
"stem4": {
"rotation": ["30-1*math.sin(q.anim_time*90*1-90)*1", 0, 0]
},
"stem5": {
"rotation": ["30-1*math.sin(q.anim_time*90*1-90)*1", 0, 0]
},
"stem6": {
"rotation": ["30-1*math.sin(q.anim_time*90*1-90)*1", 0, 0]
},
"stem7": {
"rotation": ["-72.5+3*math.sin(q.anim_time*90*1-30)*1", 0, 0],
"position": [0, -0.9, 0]
},
"stem8": {
"rotation": ["-27.5+2*math.sin(q.anim_time*90*1-10)*1", 0, 0]
},
"stem9": {
"rotation": ["-25+1*math.sin(q.anim_time*90*1-15)*1", 0, 0]
},
"stem10": {
"rotation": ["-22.5+2*math.sin(q.anim_time*90*1-30)*1", 0, 0]
},
"tail": {
"rotation": [-20, "0+1*math.sin(q.anim_time*90*1-30)*1", 0]
},
"tail2": {
"rotation": [2.5, "0+1*math.sin(q.anim_time*90*1-50)*1", 0]
},
"tail3": {
"rotation": [15, "1*math.sin(q.anim_time*90*1-60)*1", 0]
},
"tail4": {
"rotation": [5, "0+2*math.sin(q.anim_time*90*1-120)*1", 0]
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More