Compare commits

..
Author SHA1 Message Date
JPAKx4 b1817322fa camera stuffs 2025-11-21 22:33:14 -06:00
235 changed files with 6810 additions and 22822 deletions
+996 -10
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-61
View File
@@ -1,61 +0,0 @@
# Changelog
## [1.7.1 (November 29th, 2025)](#1-7-1)
### Additions
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
- Added brewing recipe for Throat Spray.
- Added vanilla sprinting's field of view change to Pokémon land mounts.
- Added a customizable keybind for the riding freelook button.
- Added double tap to sprint on land mounts.
### Changes
- Made Jet pitch turning 1.5x faster across all Pokémon.
- Party Pokémon now attack only mobs that are attacking their owner, instead of randomly targeting unrelated mobs and getting themselves hurt.
- Reduced the cost of the Vivichoke Seed trade with the Wandering Trader.
### Fixes
- Fixed incorrect camera pivot on Bird, Jet, and Dolphin mounts, leading to some disorienting riding.
- Fixed players suffocating while on vanilla mounts.
- Fixed a graphics crash that could occur on some machines when campfire pots were nearby.
- Fixed ride controls overlay being displayed to passengers. The passengers probably don't need to know about those.
- Fixed mount jumping so that it doesn't switch back to ground animations.
- Fixed ridden Pokémon land collision and some issues around stepping up blocks. Land mounts are smoother overall now.
- Fixed Furfrou's pink and magenta trims being swapped. Only a man could make that mistake.
- Fixed friendship being reset to the default value when evolving a Pokémon.
- Fixed Combees not depositing honey upon leaving a hive if they entered it with nectar.
- Fixed pastured Combees not moving during the night or in rain.
- Fixed a case in which a Combee might try to path to a flower that no longer exists.
- Fixed Combees attempting to enter a full hive.
- Fixed a crash involving Combees and hives. 500 bee bugs. Bugged bees? We can be bees. Mark, this is good news.
- Fixed a crash related to NPC navigation.
- Fixed a crash when opening a PC box with certain wallpapers while using *VulkanMod*.
- Fixed a crash when you place a block in the way of hearty grains 2nd block.
- Fixed passengers hearing the shiny noise of a ridden shiny Pokémon.
- Ponigiri can no longer be eaten at full hunger.
- Fixed Poké Snack spawning sounds not coming from the block.
- Medicinal Brew's Campfire Pot recipe now correctly displays that it can be made using an empty glass bottle or a filled bottle.
- Fixed glass bottle not being returned when slathering honey on a saccharine leaf block.
- Fixed saccharine hanging signs sometimes dropping their oak wood counterpart when being broken.
- Fixed a bunch of incompatibilities with NeoForge mods.
- Fixed a bug where wind charges hitting pasture blocks would recall all Pokémon in it.
- Fixed the Home on the Range advancement triggering when opening the Pokémon interaction wheel.
- Fixed recipes that use concrete not working on NeoForge.
- Fixed Boltund's model.
- Fixed Cyclizar's textures.
### Developer
### Molang & Datapacks
- Removed automatic generation of PC wallpaper screen glow if no asset is provided; it is now optional.
- This is because there's no practical way to do this without blowing up things like *VulkanMod*.
### Particles
### Localization
- Updated translations for:
- French
- Japanese
- Korean
- Brazilian Portuguese
- Simplified Chinese
- Traditional Chinese
-2
View File
@@ -54,8 +54,6 @@ dependencies {
// Flywheel has no common dep so just pick one and don't use any platform specific code in common
// modCompileOnly(libs.flywheelFabric)
modCompileOnly(files("temp/vivecraft-1.21.1-1.3.4.jar")) // TODO: Switch this to a proper dependency when Vivecraft gets a maven repo
// Showdown
modCompileOnly(libs.graal)
@@ -17,7 +17,6 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BeehiveBlock;
@@ -53,9 +52,7 @@ public abstract class BeeOccupantMixin {
var facing = state.getValue(HorizontalDirectionalBlock.FACING);
newPos = pos.relative(facing).getCenter();
newYaw = facing.toYRot();
if (brain.checkMemory(CobblemonMemories.HIVE_LOCATION, MemoryStatus.REGISTERED)) {
brain.setMemory(CobblemonMemories.HIVE_LOCATION, pos); // This needs to be set in the case that the hive was picked up and moved.
}
brain.setMemory(CobblemonMemories.HIVE_LOCATION, pos); // This needs to be set in the case that the hive was picked up and moved.
} else {
// Block has likely been destroyed
var center = pos.getCenter();
@@ -65,31 +62,25 @@ public abstract class BeeOccupantMixin {
center.z + level.random.nextFloat() * 0.6 - 0.3
);
newYaw = level.random.nextFloat() * 360F;
if (brain.checkMemory(CobblemonMemories.HIVE_LOCATION, MemoryStatus.REGISTERED)) {
brain.eraseMemory(CobblemonMemories.HIVE_LOCATION);
}
brain.eraseMemory(CobblemonMemories.HIVE_LOCATION);
}
entity.yRotO = newYaw;
entity.setPos(newPos);
// Do honey logic
if (brain.checkMemory(CobblemonMemories.HAS_NECTAR, MemoryStatus.REGISTERED)) {
var hasNectar = brain.getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
if (hasNectar) {
// Remove nectar and reset got to hive cooldown
brain.eraseMemory(CobblemonMemories.HAS_NECTAR);
if (brain.checkMemory(CobblemonMemories.HIVE_LOCATION, MemoryStatus.REGISTERED)) {
brain.setMemoryWithExpiry(CobblemonMemories.HIVE_COOLDOWN, true, PathToBeeHiveTaskConfig.STAY_OUT_OF_HIVE_COOLDOWN);
}
// Increment honey level of the hive
if (state.is(BlockTags.BEEHIVES, (blockStateBase) -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL))) {
int i = state.getValue(BeehiveBlock.HONEY_LEVEL);
if (i < 5) {
int j = level.random.nextInt(100) == 0 ? 2 : 1;
if (i + j > 5) {
--j;
}
level.setBlockAndUpdate(pos, state.setValue(BeehiveBlock.HONEY_LEVEL, i + j));
var hasNectar = brain.getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
if (hasNectar) {
// Remove nectar and reset got to hive cooldown
brain.eraseMemory(CobblemonMemories.HAS_NECTAR);
brain.setMemoryWithExpiry(CobblemonMemories.HIVE_COOLDOWN, true, PathToBeeHiveTaskConfig.STAY_OUT_OF_HIVE_COOLDOWN);
// Increment honey level of the hive
if (state.is(BlockTags.BEEHIVES, (blockStateBase) -> blockStateBase.hasProperty(BeehiveBlock.HONEY_LEVEL))) {
int i = state.getValue(BeehiveBlock.HONEY_LEVEL);
if (i < 5) {
int j = level.random.nextInt(100) == 0 ? 2 : 1;
if (i + j > 5) {
--j;
}
level.setBlockAndUpdate(pos, state.setValue(BeehiveBlock.HONEY_LEVEL, i + j));
}
}
}
@@ -101,13 +92,12 @@ 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", "CanPickUpLoot", "DeathTime", "FallDistance", "FallFlying", "Fire", "HandDropChances", "HandItems", "HurtByTimestamp", "HurtTime", "LeftHanded", "Motion", "NoGravity", "OnGround", "PortalCooldown", "Pos", "Rotation", "Passengers", "leash", "UUID");
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().checkMemory(CobblemonMemories.HAS_NECTAR, MemoryStatus.REGISTERED)
&& pokemonEntity.getBrain().getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
Boolean hasNectar = pokemonEntity.getBrain().getMemory(CobblemonMemories.HAS_NECTAR).orElse(false);
cir.setReturnValue(new BeehiveBlockEntity.Occupant(CustomData.of(compoundTag), 0, hasNectar ? 2400 : 600));
cir.cancel();
}
@@ -0,0 +1,38 @@
/*
* 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;
import com.cobblemon.mod.common.block.PreEmptsExplosion;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = Explosion.class)
public class ExplosionMixin {
@Redirect(
method = "finalizeExplosion",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;",
ordinal = 0
)
)
public BlockState cobblemon$whenExploded(Level world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if(blockState.getBlock() instanceof PreEmptsExplosion preExplosionBlock) {
preExplosionBlock.whenExploded(world, blockState, pos);
}
return blockState;
}
}
@@ -0,0 +1,32 @@
/*
* 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;
import net.minecraft.stats.RecipeBookSettings;
import net.minecraft.world.inventory.RecipeBookType;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@Mixin(RecipeBookSettings.class)
public class RecipeBookSettingsMixin {
@Shadow @Final public Map<RecipeBookType, RecipeBookSettings.TypeSettings> states;
@Inject(method = "<init>", at = @At("TAIL"))
private void cobblemon$init(CallbackInfo ci) {
states.put(RecipeBookType.valueOf("COOKING_POT"), new RecipeBookSettings.TypeSettings(true, true));
}
}
@@ -6,9 +6,8 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.fabric.mixin;
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonRecipeBookTypes;
import net.minecraft.world.inventory.RecipeBookType;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
@@ -41,9 +40,7 @@ public class RecipeBookTypeMixin {
)
private static void cobblemon$addRecipeBookType(CallbackInfo ci) {
ArrayList<RecipeBookType> types = new ArrayList<>(List.of($VALUES));
// if you change or add any of these, neoforge uses a separate mechanism
// check enumextensions.json and `CobblemonEnumExtensions`
types.add(cobblemon$createBookType(CobblemonRecipeBookTypes.COOKING_POT_NAME, $VALUES.length));
types.add(cobblemon$createBookType("COOKING_POT", $VALUES.length));
$VALUES = types.toArray(RecipeBookType[]::new);
}
}
@@ -33,7 +33,7 @@ public class AbstractClientPlayerMixin {
cir.setReturnValue(usageContext.getFovMultiplier());
} else {
// Only modify fov through riding if the pokedex is not open
AbstractClientPlayer player = (AbstractClientPlayer) (Object) this;
LocalPlayer player = (LocalPlayer) (Object) this;
// Only modify fov for the driver and not the passengers
if (player != null && player.isPassenger() && player.getVehicle() instanceof PokemonEntity && player.getVehicle().getControllingPassenger() == player) {
PokemonEntity ride = (PokemonEntity) player.getVehicle();
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.api.orientation.OrientationController;
import com.cobblemon.mod.common.client.CobblemonClient;
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
import com.cobblemon.mod.common.client.keybind.keybinds.RidingFreelookBinding;
import com.cobblemon.mod.common.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
@@ -157,7 +156,7 @@ public abstract class MouseHandlerMixin {
}
var vehicleController = controllableVehicle.getOrientationController();
var freeLooking = RidingFreelookBinding.INSTANCE.isDown();
var lookaroundButtonPressed = Minecraft.getInstance().mouseHandler.isMiddlePressed();
Pair<Boolean, Boolean> mouseShouldModifyDriver = ((PokemonEntity) vehicle).ifRidingAvailableSupply(new Pair(false, false), (behaviour, settings, state) -> {
return behaviour.mouseModifiesDriverRotation(
settings,
@@ -171,7 +170,7 @@ public abstract class MouseHandlerMixin {
// affect the vehicle orientation when looking around.
// If the client is a passenger it will modify these rotations and return
//-------------------------------------------------------------------------
if (freeLooking || player.getControlledVehicle() == null) {
if (lookaroundButtonPressed || player.getControlledVehicle() == null) {
// Modify driver rotations
cobblemon$setDriverRotations(player, cursorDeltaX, cursorDeltaY);
@@ -193,10 +192,10 @@ public abstract class MouseHandlerMixin {
// Smoothly return driver rotations to zero when needed
//-------------------------------------------------------------------------
var playerRotater = (RidePassenger)player;
if( !freeLooking && !mouseShouldModifyDriver.getFirst()){
if( !lookaroundButtonPressed && !mouseShouldModifyDriver.getFirst()){
playerRotater.cobblemon$setRideYRot(lerp(min(5.0f * (float)movementTime, 1.0f), Mth.wrapDegrees(playerRotater.cobblemon$getRideYRot()), 0.0f));
}
if( !freeLooking && !mouseShouldModifyDriver.getSecond()) {
if( !lookaroundButtonPressed && !mouseShouldModifyDriver.getSecond()) {
playerRotater.cobblemon$setRideXRot(lerp(min(5.0f * (float)movementTime, 1.0f), Mth.wrapDegrees(playerRotater.cobblemon$getRideXRot()), 0.0f));
}
@@ -6,11 +6,10 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.fabric.mixin;
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.CobblemonItems;
import com.cobblemon.mod.common.CobblemonRecipeBookTypes;
import com.cobblemon.mod.common.CobblemonRecipeCategories;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.RecipeBookCategories;
@@ -50,19 +49,17 @@ public class RecipeBookCategoriesMixin {
)
private static void cobblemon$addRecipeBookType(CallbackInfo ci) {
ArrayList<RecipeBookCategories> types = new ArrayList<>(List.of($VALUES));
// if you change or add any of these, neoforge uses a separate mechanism
// check enumextensions.json and `CobblemonEnumExtensions`
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_SEARCH", $VALUES.length, new ItemStack(Items.COMPASS)));
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.LEEK_AND_POTATO_STEW)));
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.POTION)));
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.APRIJUICE_RED)));
types.add(cobblemon$createCategory("COBBLEMON_COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.PROTEIN)));
types.add(cobblemon$createCategory("COOKING_POT_SEARCH", $VALUES.length, new ItemStack(Items.COMPASS)));
types.add(cobblemon$createCategory("COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.LEEK_AND_POTATO_STEW)));
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.POTION)));
types.add(cobblemon$createCategory("COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.APRIJUICE_RED)));
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.PROTEIN)));
$VALUES = types.toArray(RecipeBookCategories[]::new);
}
@Inject(method = "getCategories", at = @At("HEAD"), cancellable = true)
private static void modifyCategories(RecipeBookType recipeBookType, CallbackInfoReturnable<List<RecipeBookCategories>> cir) {
if (recipeBookType == CobblemonRecipeBookTypes.INSTANCE.getCOOKING_POT()) {
if (recipeBookType == RecipeBookType.valueOf("COOKING_POT")) {
List var10000 = ImmutableList.of(
CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory(),
CobblemonRecipeCategories.COOKING_POT_FOODS.toVanillaCategory(),
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.mixin.entity;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.pokemon.Pokemon;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import net.minecraft.client.player.LocalPlayer;
@@ -24,7 +23,6 @@ import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -50,8 +48,16 @@ public abstract class EntityMixin {
)
)
public boolean cobblemon$forceOnGroundForStepUp(Entity entity, Operation<Boolean> original) {
if (entity instanceof PokemonEntity vehicle && entity.hasControllingPassenger()) {
return true;
if (entity instanceof PokemonEntity && entity.hasControllingPassenger()) {
BlockPos below = entity.blockPosition().below();
Level level = entity.level();
var blockStateBelow = level.getBlockState(below);
boolean isAirOrLiquid = blockStateBelow.isAir() || !blockStateBelow.getFluidState().isEmpty();
boolean canSupportEntity = blockStateBelow.isFaceSturdy(level, below, Direction.UP);
boolean standingOnSolid = canSupportEntity && !isAirOrLiquid;
if (standingOnSolid) {
return true;
}
}
return original.call(entity);
}
@@ -62,7 +68,18 @@ public abstract class EntityMixin {
cancellable = true
)
private void cobblemon$modifyEyePosition_partial(float partialTicks, CallbackInfoReturnable<Vec3> cir) {
cobblemon$getCustomEyePos(cir);
var entity = (Entity)(Object)this;
if (entity.level().isClientSide) return;
if (!(entity instanceof Player player)) return;
if (!(player instanceof RidePassenger ridePassenger)) return;
if (!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
var vehicleController = vehicle.getOrientationController();
if (vehicleController == null) return;
// TODO: Determine if it needs partialtick involved.
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
cir.setReturnValue(customEyePos);
}
@Inject(
@@ -71,20 +88,15 @@ public abstract class EntityMixin {
cancellable = true
)
private void cobblemon$modifyEyePosition_noPartial(CallbackInfoReturnable<Vec3> cir) {
cobblemon$getCustomEyePos(cir);
}
@Unique
private void cobblemon$getCustomEyePos(CallbackInfoReturnable<Vec3> cir) {
var entity = (Entity)(Object)this;
if (entity.level().isClientSide) return;
if (!(entity instanceof Player player)) return;
if (!(player instanceof RidePassenger ridePassenger)) return;
if (!(player.getVehicle() instanceof OrientationControllable vehicle)) return;
if (!(vehicle instanceof PokemonEntity)) return;
var vehicleController = vehicle.getOrientationController();
if (vehicleController == null) return;
// TODO: Determine if it needs partialtick involved.
Vec3 customEyePos = ridePassenger.cobblemon$getRideEyePos();
cir.setReturnValue(customEyePos);
}
@@ -42,8 +42,8 @@ import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
import com.cobblemon.mod.common.api.starter.StarterHandler
import com.cobblemon.mod.common.api.stats.CobblemonStats
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
@@ -76,8 +76,12 @@ import com.cobblemon.mod.common.config.LastChangedVersion
import com.cobblemon.mod.common.config.constraint.IntConstraint
import com.cobblemon.mod.common.config.starter.StarterConfig
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.events.*
import com.cobblemon.mod.common.integration.vivecraft.CobblemonVR
import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.EntityCallbackHandler
import com.cobblemon.mod.common.events.CallbackHandler
import com.cobblemon.mod.common.events.PokedexHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.events.StatHandler
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents
@@ -131,12 +135,10 @@ object Cobblemon {
const val MODID = CobblemonBuildDetails.MOD_ID
const val VERSION = CobblemonBuildDetails.VERSION
const val CONFIG_PATH = "config/$MODID/main.json"
@JvmField
val LOGGER: Logger = LogManager.getLogger()
lateinit var implementation: CobblemonImplementation
@Deprecated("This field is now a config value", ReplaceWith("Cobblemon.config.captureCalculator"))
var captureCalculator: CaptureCalculator
get() = this.config.captureCalculator
@@ -166,49 +168,21 @@ object Cobblemon {
val serverPlayerStructs = mutableMapOf<UUID, ObjectValue<Player>>()
val statistics: CobblemonStats = CobblemonStats
var cobblemonVR: CobblemonVR? = null
@JvmStatic
val builtinPacks = listOf<CobblemonPack>(
CobblemonPack(
id = "adorncompatibility",
name = "Adorn Compatibility",
packType = PackType.CLIENT_RESOURCES,
activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED,
neededMods = setOf("adorn")
),
CobblemonPack(
id = "gyaradosjump",
name = "Gyarados Jump Patterns",
packType = PackType.CLIENT_RESOURCES,
activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED
),
CobblemonPack(
id = "regionbiasforms",
name = "Region Bias Forms",
packType = PackType.CLIENT_RESOURCES,
activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED
),
CobblemonPack(
id = "uniqueshinyforms",
name = "Shinies for Magikarp Jump",
packType = PackType.CLIENT_RESOURCES,
activationBehaviour = ResourcePackActivationBehaviour.NORMAL
),
CobblemonPack(id = "adorncompatibility", name = "Adorn Compatibility", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.ALWAYS_ENABLED, neededMods = setOf("adorn")),
CobblemonPack(id = "gyaradosjump", name = "Gyarados Jump Patterns", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
CobblemonPack(id = "regionbiasforms", name = "Region Bias Forms", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED),
CobblemonPack(id = "uniqueshinyforms", name = "Shinies for Magikarp Jump", packType = PackType.CLIENT_RESOURCES, activationBehaviour = ResourcePackActivationBehaviour.NORMAL),
CobblemonPack(
id = "repurposedstructurescobblemon",
name = "Repurposed Structures Cobblemon",
packType = PackType.SERVER_DATA,
activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED,
neededMods = setOf("repurposed_structures")
),
CobblemonPack(id = "repurposedstructurescobblemon", name = "Repurposed Structures Cobblemon", packType = PackType.SERVER_DATA, activationBehaviour = ResourcePackActivationBehaviour.DEFAULT_ENABLED, neededMods = setOf("repurposed_structures")),
)
fun preInitialize(implementation: CobblemonImplementation) {
this.implementation = implementation
this.LOGGER.info("Launching Cobblemon ${CobblemonBuildDetails.VERSION}${if (CobblemonBuildDetails.SNAPSHOT) "-SNAPSHOT" else ""} ")
this.LOGGER.info("Launching Cobblemon ${CobblemonBuildDetails.VERSION}${if(CobblemonBuildDetails.SNAPSHOT) "-SNAPSHOT" else ""} ")
if (CobblemonBuildDetails.SNAPSHOT) {
this.LOGGER.info(" - Git Commit: ${smallCommitHash()} (https://gitlab.com/cable-mc/cobblemon/-/commit/${CobblemonBuildDetails.GIT_COMMIT})")
this.LOGGER.info(" - Branch: ${CobblemonBuildDetails.BRANCH}")
@@ -272,10 +246,7 @@ object Cobblemon {
}
PlatformEvents.RIGHT_CLICK_ENTITY.subscribe { event ->
if (event.player.getItemInHand(event.hand).item is NameTagItem && event.entity.type.`is`(
CobblemonEntityTypeTags.CANNOT_HAVE_NAME_TAG
)
) {
if (event.player.getItemInHand(event.hand).item is NameTagItem && event.entity.type.`is`(CobblemonEntityTypeTags.CANNOT_HAVE_NAME_TAG)) {
event.cancel()
}
}
@@ -286,10 +257,7 @@ object Cobblemon {
pokemon.lockedEvolutions
.filterIsInstance<BlockClickEvolution>()
.forEach { evolution ->
evolution.attemptEvolution(
pokemon,
BlockClickEvolution.BlockInteractionContext(block, player.level())
)
evolution.attemptEvolution(pokemon, BlockClickEvolution.BlockInteractionContext(block, player.level()))
}
}
}
@@ -349,11 +317,6 @@ object Cobblemon {
SlowpokeTailRegrowthSpeciesFeatureProvider
)
if (implementation.isModInstalled("vivecraft")) { // VR integration
cobblemonVR = CobblemonVR()
cobblemonVR?.init()
}
CustomPokemonProperty.register(UncatchableProperty)
CustomPokemonProperty.register(BattleCloneProperty)
CustomPokemonProperty.register(PokemonFlagProperty)
@@ -373,7 +336,7 @@ object Cobblemon {
}
PlatformEvents.SERVER_TICK_POST.subscribe {
ServerTaskTracker.update(1 / 20F)
ServerTaskTracker.update(1/20F)
ServerRealTimeTaskTracker.update()
}
PlatformEvents.SERVER_TICK_PRE.subscribe {
@@ -417,22 +380,10 @@ object Cobblemon {
.applyConnectionString(ConnectionString(config.mongoDBConnectionString))
.build()
mongoClient = MongoClients.create(mongoClientSettings)
val generalMongoFactory = CachedPlayerDataStoreFactory(
PlayerDataMongoBackend(
mongoClient,
config.mongoDBDatabaseName,
"PlayerDataCollection"
)
)
val generalMongoFactory = CachedPlayerDataStoreFactory(PlayerDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PlayerDataCollection"))
generalMongoFactory.setup(server)
val pokedexMongoFactory = CachedPlayerDataStoreFactory(
DexDataMongoBackend(
mongoClient,
config.mongoDBDatabaseName,
"PokeDexCollection"
)
)
val pokedexMongoFactory = CachedPlayerDataStoreFactory(DexDataMongoBackend(mongoClient, config.mongoDBDatabaseName, "PokeDexCollection"))
pokedexMongoFactory.setup(server)
playerDataManager.setFactory(generalMongoFactory, PlayerInstancedDataStoreTypes.GENERAL)
@@ -554,7 +505,6 @@ object Cobblemon {
field.set(config, field.get(defaultConfig))
}
}
is IntConstraint -> {
var value = field.get(config)
if (value is Int) {
@@ -607,76 +557,20 @@ object Cobblemon {
}
private fun registerArgumentTypes() {
this.implementation.registerCommandArgument(
cobblemonResource("pokemon"),
SpeciesArgumentType::class,
SingletonArgumentInfo.contextFree(SpeciesArgumentType::species)
)
this.implementation.registerCommandArgument(
cobblemonResource("pokemon_properties"),
PokemonPropertiesArgumentType::class,
SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties)
)
this.implementation.registerCommandArgument(
cobblemonResource("spawn_bucket"),
SpawnBucketArgumentType::class,
SingletonArgumentInfo.contextFree(SpawnBucketArgumentType::spawnBucket)
)
this.implementation.registerCommandArgument(
cobblemonResource("move"),
MoveArgumentType::class,
SingletonArgumentInfo.contextFree(MoveArgumentType::move)
)
this.implementation.registerCommandArgument(
cobblemonResource("party_slot"),
PartySlotArgumentType::class,
SingletonArgumentInfo.contextFree(PartySlotArgumentType::partySlot)
)
this.implementation.registerCommandArgument(
cobblemonResource("pokemon_store"),
PokemonStoreArgumentType::class,
SingletonArgumentInfo.contextFree(PokemonStoreArgumentType::pokemonStore)
)
this.implementation.registerCommandArgument(
cobblemonResource("dialogue"),
DialogueArgumentType::class,
SingletonArgumentInfo.contextFree(DialogueArgumentType::dialogue)
)
this.implementation.registerCommandArgument(
cobblemonResource("form"),
FormArgumentType::class,
SingletonArgumentInfo.contextFree(FormArgumentType::form)
)
this.implementation.registerCommandArgument(
cobblemonResource("dex"),
DexArgumentType::class,
SingletonArgumentInfo.contextFree(DexArgumentType::dex)
)
this.implementation.registerCommandArgument(
cobblemonResource("npc_class"),
NPCClassArgumentType::class,
SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass)
)
this.implementation.registerCommandArgument(
cobblemonResource("wallpaper"),
UnlockablePCBoxWallpaperArgumentType::class,
SingletonArgumentInfo.contextFree(UnlockablePCBoxWallpaperArgumentType::wallpaper)
)
this.implementation.registerCommandArgument(
cobblemonResource("mark"),
MarkArgumentType::class,
SingletonArgumentInfo.contextFree(MarkArgumentType::mark)
)
this.implementation.registerCommandArgument(
cobblemonResource("transform_type"),
TransformTypeArgumentType::class,
SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType)
)
this.implementation.registerCommandArgument(
cobblemonResource("model_part"),
ModelPartArgumentType::class,
SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart)
)
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), SpeciesArgumentType::class, SingletonArgumentInfo.contextFree(SpeciesArgumentType::species))
this.implementation.registerCommandArgument(cobblemonResource("pokemon_properties"), PokemonPropertiesArgumentType::class, SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties))
this.implementation.registerCommandArgument(cobblemonResource("spawn_bucket"), SpawnBucketArgumentType::class, SingletonArgumentInfo.contextFree(SpawnBucketArgumentType::spawnBucket))
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, SingletonArgumentInfo.contextFree(MoveArgumentType::move))
this.implementation.registerCommandArgument(cobblemonResource("party_slot"), PartySlotArgumentType::class, SingletonArgumentInfo.contextFree(PartySlotArgumentType::partySlot))
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, SingletonArgumentInfo.contextFree(PokemonStoreArgumentType::pokemonStore))
this.implementation.registerCommandArgument(cobblemonResource("dialogue"), DialogueArgumentType::class, SingletonArgumentInfo.contextFree(DialogueArgumentType::dialogue))
this.implementation.registerCommandArgument(cobblemonResource("form"), FormArgumentType::class, SingletonArgumentInfo.contextFree(FormArgumentType::form))
this.implementation.registerCommandArgument(cobblemonResource("dex"), DexArgumentType::class, SingletonArgumentInfo.contextFree (DexArgumentType::dex))
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
this.implementation.registerCommandArgument(cobblemonResource("wallpaper"), UnlockablePCBoxWallpaperArgumentType::class, SingletonArgumentInfo.contextFree(UnlockablePCBoxWallpaperArgumentType::wallpaper))
this.implementation.registerCommandArgument(cobblemonResource("mark"), MarkArgumentType::class, SingletonArgumentInfo.contextFree(MarkArgumentType::mark))
this.implementation.registerCommandArgument(cobblemonResource("transform_type"), TransformTypeArgumentType::class, SingletonArgumentInfo.contextFree(TransformTypeArgumentType::transformType))
this.implementation.registerCommandArgument(cobblemonResource("model_part"), ModelPartArgumentType::class, SingletonArgumentInfo.contextFree(ModelPartArgumentType::modelPart))
}
}
@@ -215,7 +215,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val SACCHARINE_WALL_SIGN = this.create("saccharine_wall_sign", CobblemonWallSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_WALL_HANGING_SIGN = this.create("saccharine_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
File diff suppressed because it is too large Load Diff
@@ -9,15 +9,14 @@
package com.cobblemon.mod.common
import net.minecraft.client.RecipeBookCategories
import net.minecraft.world.inventory.RecipeBookType
enum class CobblemonRecipeCategories {
COOKING_POT_SEARCH("COBBLEMON_COOKING_POT_SEARCH"),
COOKING_POT_FOODS("COBBLEMON_COOKING_POT_FOODS"),
COOKING_POT_MEDICINES("COBBLEMON_COOKING_POT_MEDICINES"),
COOKING_POT_COMPLEX_DISHES("COBBLEMON_COOKING_POT_COMPLEX_DISHES"),
COOKING_POT_MISC("COBBLEMON_COOKING_POT_MISC");
COOKING_POT_SEARCH("COOKING_POT_SEARCH"),
COOKING_POT_FOODS("COOKING_POT_FOODS"),
COOKING_POT_MEDICINES("COOKING_POT_MEDICINES"),
COOKING_POT_COMPLEX_DISHES("COOKING_POT_COMPLEX_DISHES"),
COOKING_POT_MISC("COOKING_POT_MISC");
companion object {
val customAggregateCategories: Map<RecipeBookCategories, List<RecipeBookCategories>> = mapOf(
@@ -36,9 +35,6 @@ enum class CobblemonRecipeCategories {
fun toVanillaCategory(): RecipeBookCategories {
return RecipeBookCategories.valueOf(this.id)
}
}
object CobblemonRecipeBookTypes {
const val COOKING_POT_NAME = "COBBLEMON_COOKING_POT"
val COOKING_POT: RecipeBookType = RecipeBookType.valueOf(COOKING_POT_NAME)
}
@@ -89,14 +89,7 @@ object CobblemonTradeOffers {
* @return The resulting list.
*/
fun resolveWanderingTradeOffers(): List<WandererTradeOffer> = listOf(
WandererTradeOffer(false, listOf(
VillagerTrades.ItemsForEmeralds(CobblemonItems.VIVICHOKE_SEEDS, 6, 1, 1, 6),
VillagerTrades.ItemsForEmeralds(CobblemonItems.SACCHARINE_SAPLING, 5, 1, 4, 1),
VillagerTrades.ItemsForEmeralds(CobblemonItems.HEARTY_GRAINS, 1, 1, 12, 1),
VillagerTrades.ItemsForEmeralds(CobblemonItems.CHIPPED_POT, 5, 1, 1, 2),
VillagerTrades.ItemsForEmeralds(CobblemonItems.MASTERPIECE_TEACUP, 5, 1, 1, 2)
))
WandererTradeOffer(false, listOf(VillagerTrades.ItemsForEmeralds(CobblemonItems.VIVICHOKE_SEEDS, 24, 1, 1, 6)))
)
/**
@@ -1,44 +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.api.ai.config.task
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.DefendOwnerTask
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.memory.MemoryModuleType
class DefendOwnerTaskConfig : SingleTaskConfig {
override fun getVariables(
entity: LivingEntity,
behaviourConfigurationContext: BehaviourConfigurationContext
): List<MoLangConfigVariable> {
return emptyList()
}
override fun createTask(
entity: LivingEntity,
behaviourConfigurationContext: BehaviourConfigurationContext
): BehaviorControl<in LivingEntity>? {
behaviourConfigurationContext.addMemories(
MemoryModuleType.ATTACK_TARGET,
CobblemonMemories.NEAREST_VISIBLE_ATTACKER,
)
return WrapperLivingEntityTask(
DefendOwnerTask.create(),
PokemonEntity::class.java
)
}
}
@@ -109,7 +109,7 @@ class PollinateFlowerTaskConfig : SingleTaskConfig {
}
override fun stop(level: ServerLevel, entity: LivingEntity, gameTime: Long) {
hoverPos = null
if (successfulPollinationTicks > REQUIRED_SUCCESSFUL_POLLINATION_TICKS) {
entity.brain.setMemory(CobblemonMemories.HAS_NECTAR, true)
}
@@ -105,7 +105,6 @@ interface TaskConfig {
cobblemonResource("go_to_land") to GoToLandTaskConfig::class.java,
cobblemonResource("manage_flight_in_battle") to ManageFlightInBattleTaskConfig::class.java,
cobblemonResource("attack_hostile_mobs") to AttackHostileMobsTaskConfig::class.java,
cobblemonResource("defend_owner") to DefendOwnerTaskConfig::class.java,
cobblemonResource("move_to_sweet_berry_bush") to MoveToSweetBerryBushTaskConfig::class.java,
cobblemonResource("stop_moving_to_sweet_berry_bush") to StopTryingToReachSweetBerryBushTaskConfig::class.java,
cobblemonResource("harvest_sweet_berry_bush") to HarvestSweetBerryBushTaskConfig::class.java,
@@ -9,8 +9,13 @@
package com.cobblemon.mod.common.api.cooking
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.util.math.geometry.toDegrees
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.util.FastColor
import net.minecraft.world.item.ItemStack
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.sin
private val colourMap = mapOf(
Flavour.SPICY to 0xFEB37D,
@@ -29,30 +34,27 @@ private val bubbleColourMap = mapOf(
)
fun getColourMixFromSeasonings(seasonings: List<ItemStack>, forBubbles: Boolean = false): Int? {
val flavourValues = mutableMapOf<Flavour, Int>()
for (seasoning in seasonings) {
val flavours = Seasonings.getFlavoursFromItemStack(seasoning) ?: continue
for ((flavour, value) in flavours.entries) {
flavourValues[flavour] = (flavourValues[flavour] ?: 0) + value
}
}
val flavors = seasonings
.mapNotNull { Seasonings.getFlavoursFromItemStack(it) }
.flatMap { it.entries }
.groupingBy { it.key }
.fold(0) { acc, entry -> acc + entry.value }
if (flavourValues.isEmpty()) {
return null
}
if (flavors.isEmpty()) return null
val maxFlavorValue = flavourValues.values.maxOrNull()
val dominantFlavours = flavourValues.filter { it.value == maxFlavorValue }.map { it.key }
val maxFlavorValue = flavors.values.maxOrNull()
val dominantFlavors = flavors.filter { it.value == maxFlavorValue }.map { it.key }
return getColourMixFromFlavours(dominantFlavours, forBubbles)
return getColourMixFromFlavours(dominantFlavors, forBubbles)
}
fun getColourMixFromFlavours(dominantFlavours: List<Flavour>, forBubbles: Boolean = false): Int? {
val colors =
dominantFlavours
.mapNotNull { if (forBubbles) bubbleColourMap[it] else colourMap[it] }
dominantFlavours.mapNotNull { if (forBubbles) bubbleColourMap[it] else colourMap[it] }
.map { FastColor.ARGB32.opaque(it) }
if (colors.isEmpty()) return null
return getColourMixFromColors(colors)
}
@@ -60,33 +62,104 @@ fun getColourMixFromRideStatBoosts(dominantBoosts: Iterable<RidingStat>, forBubb
return getColourMixFromFlavours(dominantBoosts.map { it.flavour }, forBubbles)
}
// Mixing RGB colors directly often gives poor results
// Converting them to HSL and averaging hues circularly produces more natural blends
fun getColourMixFromColors(colors: List<Int>): Int? {
if (colors.isEmpty()) return null
if (colors.size == 1) return colors[0]
val firstWeight = 0.7f
val otherWeightTotal = 1f - firstWeight
val otherWeight = otherWeightTotal / (colors.size - 1)
val hslColors = colors.map {
val red = FastColor.ARGB32.red(it)
val green = FastColor.ARGB32.green(it)
val blue = FastColor.ARGB32.blue(it)
var alphaSum = 0f
var redSum = 0f
var greenSum = 0f
var blueSum = 0f
for (i in colors.indices) {
val weight = if (i == 0) firstWeight else otherWeight
val color = colors[i]
alphaSum += FastColor.ARGB32.alpha(color) * weight
redSum += FastColor.ARGB32.red(color) * weight
greenSum += FastColor.ARGB32.green(color) * weight
blueSum += FastColor.ARGB32.blue(color) * weight
rgbToHsl(red, green, blue)
}
return FastColor.ARGB32.color(
alphaSum.toInt(),
redSum.toInt(),
greenSum.toInt(),
blueSum.toInt()
val hues = hslColors.map { it.h.toDouble() }
val huesAverage = hueAverage(hues).toFloat()
val saturations = hslColors.map { it.s }
val saturationsAverage = average(saturations)
val lightness = hslColors.map { it.l }
val lightnessAverage = average(lightness)
val rgbColor = hslToRgb(huesAverage, saturationsAverage, lightnessAverage)
return FastColor.ARGB32.color(rgbColor.r, rgbColor.g, rgbColor.b)
}
// Based on https://iter.ca/post/hue-avg
fun hueAverage(hues: List<Double>): Float {
val points = hues.map { hue ->
val rad = hue.toRadians()
Pair(cos(rad), sin(rad))
}
val avgX = points.sumOf { it.first.toDouble() } / points.size
val avgY = points.sumOf { it.second.toDouble() } / points.size
var degrees = atan2(avgY, avgX).toDegrees()
if (degrees < 0) {
degrees += 360f
} else if (degrees > 360) {
degrees -= 360f
}
return degrees
}
fun average(values: List<Float>): Float {
if (values.isEmpty()) return 0f
return values.sum() / values.size
}
data class HSL(val h: Float, val s: Float, val l: Float)
fun rgbToHsl(r: Int, g: Int, b: Int): HSL {
val rf = r / 255f
val gf = g / 255f
val bf = b / 255f
val max = maxOf(rf, gf, bf)
val min = minOf(rf, gf, bf)
val delta = max - min
var h = 0f
val l = (max + min) / 2f
val s = if (delta == 0f) 0f else delta / (1f - kotlin.math.abs(2f * l - 1f))
if (delta != 0f) {
h = when (max) {
rf -> ((gf - bf) / delta) % 6f
gf -> ((bf - rf) / delta) + 2f
else -> ((rf - gf) / delta) + 4f
}
h *= 60f
if (h < 0) h += 360f
}
return HSL(h, s, l)
}
data class RGB(val r: Int, val g: Int, val b: Int)
fun hslToRgb(h: Float, s: Float, l: Float): RGB {
val c = (1f - kotlin.math.abs(2f * l - 1f)) * s
val x = c * (1f - kotlin.math.abs((h / 60f) % 2f - 1f))
val m = l - c / 2f
val (rf, gf, bf) = when {
h < 60f -> Triple(c, x, 0f)
h < 120f -> Triple(x, c, 0f)
h < 180f -> Triple(0f, c, x)
h < 240f -> Triple(0f, x, c)
h < 300f -> Triple(x, 0f, c)
else -> Triple(c, 0f, x)
}
return RGB(
((rf + m) * 255).toInt().coerceIn(0, 255),
((gf + m) * 255).toInt().coerceIn(0, 255),
((bf + m) * 255).toInt().coerceIn(0, 255)
)
}
@@ -37,6 +37,8 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.util.FormattedCharSequence
import org.joml.Matrix4f
import org.joml.Vector3f
import org.lwjgl.opengl.GL30
import java.nio.ByteBuffer
@JvmOverloads
fun blitk(
@@ -355,10 +357,10 @@ fun renderSprite(matrixStack: PoseStack, sprite: ResourceLocation) {
val matrix: PoseStack.Pose = matrixStack.last()
matrix.pose().translate(-1f, 0f, 0f)
RenderSystem.setShaderTexture(0, sprite)
RenderSystem.setShaderTexture(0, sprite);
RenderSystem.setShader(GameRenderer::getPositionTexShader)
val buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)
var buffer = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX)
buffer.addVertex(matrix, 2f, 0f, 0.0f).setUv(1f, 0f)
buffer.addVertex(matrix, 0f, 0f, 0.0f).setUv(0f, 0f)
@@ -367,3 +369,25 @@ fun renderSprite(matrixStack: PoseStack, sprite: ResourceLocation) {
BufferUploader.drawWithShader(buffer.buildOrThrow())
}
fun getPixelRGB(x: Int, y: Int): Triple<Int, Int, Int> {
val window = Minecraft.getInstance().window
val scale = window.guiScale
val buffer = ByteBuffer.allocateDirect(4)
RenderSystem.readPixels(
(x * scale).toInt(),
(window.height - y * scale - scale).toInt(),
1,
1,
GL30.GL_RGBA,
GL30.GL_UNSIGNED_BYTE,
buffer
)
return Triple(
buffer[0].toInt() and 0xFF,
buffer[1].toInt() and 0xFF,
buffer[2].toInt() and 0xFF
)
}
@@ -409,7 +409,13 @@ open class PokemonProperties {
shiny?.let { pokemon.shiny = it }
gender?.let { pokemon.gender = it }
level?.let { pokemon.level = it }
friendship?.also { pokemon.setFriendship(it) }
friendship.also {
if (it != null) {
pokemon.setFriendship(it)
} else {
pokemon.setFriendship(pokemon.form.baseFriendship)
}
}
fullness?.let { pokemon.currentFullness = it }
pokeball?.let { PokeBalls.getPokeBall(it.asIdentifierDefaultingNamespace())?.let { pokeball -> pokemon.caughtBall = pokeball } }
nature?.let { Natures.getNature(it.asIdentifierDefaultingNamespace())?.let { nature -> pokemon.nature = nature } }
@@ -322,7 +322,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
val pitchRot = handling * state.currMouseYForce.get()
// Roll
val rollRot = handling * state.currMouseXForce.get()
val rollRot = handling * 1.5 * state.currMouseXForce.get()
val mouseRotation = Vec3(0.0, pitchRot, rollRot)
@@ -114,10 +114,10 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
input: Vec3
) {
if (vehicle.level().isClientSide) {
handleSprinting(state, driver)
handleSprinting(state)
inAirCheck(state, vehicle)
tickStamina(settings, state, vehicle)
state.walking.set(state.rideVelocity.get().horizontalDistance() > 0.01 || driver.zza != 0.0f)
state.walking.set(state.rideVelocity.get().horizontalDistance() > 0.01)
}
}
@@ -139,24 +139,9 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
}
fun handleSprinting(
state: HorseState,
driver: Player
state: HorseState
) {
val sprintTimerTickLength = 7 // Emulate vanillas tick timer length
var hasDoubleTapped = false
// If you are not sprinting and you just pressed down and theres no
if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && !state.sprinting.get() && state.sprintTickTimer.get() == 0) {
state.sprintTickTimer.set(sprintTimerTickLength)
} else if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && state.sprintTickTimer.get() != 0) { // If has double tapped
hasDoubleTapped = true
}else if(!state.sprinting.get() && state.sprintTickTimer.get() > 0) {
state.sprintTickTimer.set(state.sprintTickTimer.get() - 1)
} else {
state.sprintTickTimer.set(0)
}
val tryingToSprint = (Minecraft.getInstance().options.keySprint.isDown() && Minecraft.getInstance().options.keyUp.isDown()) || hasDoubleTapped
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
@@ -171,9 +156,6 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
// If you are trying to sprint and the toggle allows it then start sprinting and disable toggle
state.sprinting.set(true)
}
// Take not of whether forward was held last tick
state.forwardHeldLastTick.set(Minecraft.getInstance().options.keyUp.isDown())
}
fun tickStamina(
@@ -245,7 +227,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
// Normalize the current rotation diff
val rotDiff = Mth.wrapDegrees(driver.yRot - vehicle.yRot).coerceIn(-maxYawDiff,maxYawDiff)
val rotDiffNorm = rotDiff / maxYawDiff//(rotDiff / maxYawDiff).coerceIn(-0.2f, 0.2f)
val rotDiffNorm = rotDiff / maxYawDiff
// Take the square root so that the ride levels out quicker when at lower differences between entity
// y and driver y
@@ -258,7 +240,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
val walkSpeed = getWalkSpeed(vehicle)
val w = max(walkSpeed, vehicle.deltaMovement.horizontalDistance())
val invRelSpeed = (RidingBehaviour.scaleToRange(w, walkSpeed, topSpeed ) - 1.0f) * -1.0f
val turnRate = ((handling.toFloat() / 20.0f) * max(walkHandlingBoost * sqrt(abs(invRelSpeed)), 1.0)).toFloat()
val turnRate = ((handling.toFloat() / 20.0f) * max(walkHandlingBoost * invRelSpeed, 1.0)).toFloat()
// Ensure you only ever rotate as much difference as there is between the angles.
val turnSpeed = turnRate * rotDiffMod
@@ -291,24 +273,30 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalHorse.speedExpr!!)
val walkSpeed = getWalkSpeed(vehicle)
val topSpeed = if(canSprint && state.sprinting.get()) rideTopSpeed else walkSpeed
val accelTime = if(state.sprinting.get()) (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalHorse.accelerationExpr!!) * 20.0) else 0.5 * 20.0
val accel = topSpeed / accelTime
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalHorse.accelerationExpr!!) * 20.0)
var activeInput = false
/******************************************************
* Gather the previous velocity and check for horizontal
* collisions
*****************************************************/
val dmSpeed = vehicle.deltaMovement.length()
val rvSpeed = state.rideVelocity.get().length()
var newVelocity = state.rideVelocity.get() //.normalize().scale(vehicle.deltaMovement.horizontalDistance())
/******************************************************
* Gather the previous velocity and check for horizontal
* collisions
*****************************************************/
// if (dmSpeed > rvSpeed) {
// // align the velocity vector to be in local vehicle space
// newVelocity = vehicle.deltaMovement
// val yawAligned = Matrix3f().rotateY(-vehicle.yRot.toRadians())
// newVelocity = (newVelocity.toVector3f().mul(yawAligned)).toVec3d()
// }
if (vehicle.horizontalCollision) {
var horizontalVec = Vec3(newVelocity.x, 0.0, newVelocity.z)
horizontalVec = horizontalVec.normalize().scale(min(horizontalVec.length(), 0.3))
newVelocity = Vec3(horizontalVec.x, newVelocity.y, horizontalVec.z)
newVelocity = newVelocity.normalize().scale(vehicle.deltaMovement.length())
}
/******************************************************
@@ -384,7 +372,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
state.jumpTicks.set(state.jumpTicks.get() + 1)
}
// Zero out lateral velocity possibly picked up from a controller transition
//Zero out lateral velocity possibly picked up from a controller transition
newVelocity = Vec3(0.0, newVelocity.y, newVelocity.z)
@@ -473,7 +461,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
vehicle: PokemonEntity,
driver: Player
): Float {
return if (state.sprinting.get()) 1.15f else 1.0f
return 1.0f
}
override fun useAngVelSmoothing(
@@ -532,14 +520,6 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
return true
}
override fun maxUpStep(
settings: HorseSettings,
state: HorseState,
vehicle: PokemonEntity
): Float? {
return if (state.inAir.get()) 0.0f else 1.2f
}
override fun getRideSounds(
settings: HorseSettings,
state: HorseState,
@@ -638,8 +618,6 @@ class HorseState : RidingBehaviourState() {
var sprintToggleable = ridingState(false, Side.CLIENT)
var inAir = ridingState(false, Side.CLIENT)
var jumpTicks = ridingState(0, Side.CLIENT)
var sprintTickTimer = ridingState(0, Side.CLIENT)
var forwardHeldLastTick = ridingState(false, Side.CLIENT)
override fun encode(buffer: FriendlyByteBuf) {
super.encode(buffer)
@@ -648,8 +626,6 @@ class HorseState : RidingBehaviourState() {
buffer.writeBoolean(sprintToggleable.get())
buffer.writeBoolean(inAir.get())
buffer.writeInt(jumpTicks.get())
buffer.writeInt(sprintTickTimer.get())
buffer.writeBoolean(forwardHeldLastTick.get())
}
override fun decode(buffer: FriendlyByteBuf) {
@@ -659,8 +635,6 @@ class HorseState : RidingBehaviourState() {
sprintToggleable.set(buffer.readBoolean(), forced = true)
inAir.set(buffer.readBoolean(), forced = true)
jumpTicks.set(buffer.readInt(), forced = true)
sprintTickTimer.set(buffer.readInt(), forced = true)
forwardHeldLastTick.set(buffer.readBoolean(), forced = true)
}
override fun reset() {
@@ -670,8 +644,6 @@ class HorseState : RidingBehaviourState() {
sprintToggleable.set(false, forced = true)
inAir.set(false, forced = true)
jumpTicks.set(0, forced = true)
sprintTickTimer.set(0, forced = true)
forwardHeldLastTick.set(false, forced = true)
}
override fun copy() = HorseState().also {
@@ -682,8 +654,6 @@ class HorseState : RidingBehaviourState() {
it.sprintToggleable.set(this.sprintToggleable.get(), forced = true)
it.inAir.set(this.inAir.get(), forced = true)
it.jumpTicks.set(this.jumpTicks.get(), forced = true)
it.sprintTickTimer.set(this.sprintTickTimer.get(), forced = true)
it.forwardHeldLastTick.set(this.forwardHeldLastTick.get(), forced = true)
}
override fun shouldSync(previous: RidingBehaviourState): Boolean {
@@ -40,12 +40,9 @@ class PokemonSpawnAction(
override fun createEntity(): PokemonEntity {
val props = props.copy()
props.level = levelRange.random()
val sourcePlayer = spawnablePosition.cause.entity as? ServerPlayer
val entity = props.createEntity(spawnablePosition.world, sourcePlayer)
entity.spawnCause = spawnablePosition.cause
entity.pokemon.setFriendship(entity.pokemon.form.baseFriendship)
SeasonFeatureHandler.updateSeason(entity.pokemon, Cobblemon.seasonResolver(spawnablePosition.world, spawnablePosition.position))
val heldItem = heldItem
if (heldItem != ItemStack.EMPTY && heldItem != null) {
@@ -44,7 +44,11 @@ abstract class SpawnAction<R>(
spawnablePosition.applyInfluences { it.affectAction(this) }
val result = run()
future.complete(result)
if (result != null) {
future.complete(result)
} else {
future.completeExceptionally(Exception("Nothing was spawned."))
}
return result
}
@@ -61,9 +61,7 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val baitEVStat = effects.firstOrNull { it.type == Effects.EV }?.subcategory?.path?.let { Stats.getStat(it) }
if (detailSpecies != null && baitEVStat != null) {
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
val evYieldValue = formData.evYield[baitEVStat]?.toFloat() ?: 0f
val evYieldValue = detailSpecies.evYield[baitEVStat]?.toFloat() ?: 0f
return when {
evYieldValue > 0 -> {
markUsed()
@@ -85,9 +83,7 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val baitTypingEffect = baitEffect?.subcategory?.path?.let { ElementalTypes.get(it) }
if (detailSpecies != null && baitTypingEffect != null) {
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
val isMatchingType = formData.types.contains(baitTypingEffect)
val isMatchingType = detailSpecies.types.contains(baitTypingEffect)
return when {
isMatchingType -> {
markUsed()
@@ -104,9 +100,6 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val detailSpecies = detail.pokemon.species?.let { PokemonSpecies.getByName(it) }
if (detailSpecies != null) {
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
// Collect all the egg group effects
val eggGroupEffects = effects.filter { it.type == Effects.EGG_GROUP }
@@ -118,7 +111,7 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
LOGGER.warn("Unknown egg group identifier: $effectEggGroupKey")
return@firstOrNull false
}
formData.eggGroups.contains(eggGroup)
detailSpecies.eggGroups.contains(eggGroup)
}
if (matchingEffect != null) {
@@ -88,6 +88,7 @@ abstract class OneToOneFileStoreAdapter<S>(
result
}
else {
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
var result = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
save(storeClass, uuid, serialize(result, registryAccess))
oldFile.delete()
@@ -19,6 +19,7 @@ import net.minecraft.server.level.ServerLevel
import net.minecraft.tags.FluidTags
import net.minecraft.util.Mth
import net.minecraft.util.RandomSource
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.*
import net.minecraft.world.level.block.Block
@@ -174,7 +175,7 @@ class HeartyGrainsBlock(settings: Properties) : CropBlock(settings), SimpleWater
UPDATE_CLIENTS
)
}
else if (stateAbove.hasProperty(HALF) && stateAbove.getValue(HALF) == DoubleBlockHalf.UPPER) {
else if (stateAbove.getValue(HALF) == DoubleBlockHalf.UPPER) {
world.setBlock(
abovePos,
stateAbove.setValue(AGE, newAge),
@@ -34,7 +34,6 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.Explosion
import net.minecraft.world.level.Level
import net.minecraft.world.level.LevelAccessor
import net.minecraft.world.level.LevelReader
@@ -56,10 +55,9 @@ import net.minecraft.world.phys.shapes.VoxelShape
import java.util.*
import net.minecraft.world.level.block.state.properties.BlockStateProperties.WATERLOGGED
import net.minecraft.world.level.gameevent.GameEvent
import java.util.function.BiConsumer
@Suppress("OVERRIDE_DEPRECATION", "DEPRECATION")
class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWaterloggedBlock {
class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWaterloggedBlock, PreEmptsExplosion {
companion object {
val CODEC = simpleCodec(::PastureBlock)
@@ -215,19 +213,9 @@ class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWater
return super.playerWillDestroy(world, pos, state, player)
}
override fun onExplosionHit(
state: BlockState,
level: Level,
pos: BlockPos,
explosion: Explosion,
dropConsumer: BiConsumer<ItemStack?, BlockPos?>
) {
val interaction = explosion.blockInteraction
if (interaction == Explosion.BlockInteraction.DESTROY || interaction == Explosion.BlockInteraction.DESTROY_WITH_DECAY) {
val blockEntity = level.getBlockEntity(pos) as? PokemonPastureBlockEntity ?: return
blockEntity.onBroken()
}
super.onExplosionHit(state, level, pos, explosion, dropConsumer)
override fun whenExploded(world: Level, state: BlockState, pos: BlockPos) {
val blockEntity = world.getBlockEntity(pos) as? PokemonPastureBlockEntity ?: return
blockEntity.onBroken()
}
override fun <T : BlockEntity?> getTicker(world: Level, state: BlockState, type: BlockEntityType<T>): BlockEntityTicker<T>? {
@@ -0,0 +1,17 @@
/*
* 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.block
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.core.BlockPos
import net.minecraft.world.level.Level
interface PreEmptsExplosion {
fun whenExploded(world: Level, state: BlockState, pos: BlockPos)
}
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.block
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
import com.cobblemon.mod.common.util.isServerSide
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.dispenser.DispenseItemBehavior
@@ -264,39 +263,23 @@ class SaccharineLeafBlock(settings: Properties) : LeavesBlock(settings) {
val isGlassBottle = itemStack.`is`(Items.GLASS_BOTTLE)
val isHoneyBottle = itemStack.`is`(Items.HONEY_BOTTLE)
if (isGlassBottle && isAtMaxAge(state)) {
if (level.isClientSide) return ItemInteractionResult.SUCCESS
if (isGlassBottle && !isAtMinAge(state)) {
// Decrement stack if not in creative mode
itemStack.consume(1, player)
// Give player a honey bottle
if (stack.isEmpty) {
// Replace the consumed empty bottle with a honey bottle
player.setItemInHand(hand, ItemStack(Items.HONEY_BOTTLE));
} else {
player.addItem(Items.HONEY_BOTTLE.defaultInstance)
}
// Give player honey bottle for now
player.addItem(Items.HONEY_BOTTLE.defaultInstance)
level.playSound(null, pos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS)
level.setBlock(pos, state.setValue(AGE, 0), UPDATE_CLIENTS)
level.setBlock(pos, state.setValue(AGE, 0), 2)
level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos)
return ItemInteractionResult.SUCCESS
} else if (isHoneyBottle && !isAtMaxAge(state)) {
if (level.isClientSide) return ItemInteractionResult.SUCCESS
// Decrement stack if not in creative mode
if (!player.isCreative) {
itemStack.consume(1, player)
if (stack.isEmpty) {
// Replace the consumed honey bottle with an empty bottle
player.setItemInHand(hand, ItemStack(Items.GLASS_BOTTLE));
} else {
player.addItem(Items.GLASS_BOTTLE.defaultInstance)
}
}
itemStack.consume(1, player)
level.playSound(null, pos, SoundEvents.HONEY_BLOCK_PLACE, SoundSource.BLOCKS)
level.setBlock(pos, state.setValue(AGE, 2), UPDATE_CLIENTS)
level.setBlock(pos, state.setValue(AGE, 2), 2)
level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos)
return ItemInteractionResult.SUCCESS
}
@@ -9,7 +9,6 @@
package com.cobblemon.mod.common.block.campfirepot
import com.cobblemon.mod.common.CobblemonMenuType
import com.cobblemon.mod.common.CobblemonRecipeBookTypes.COOKING_POT
import com.cobblemon.mod.common.CobblemonRecipeTypes
import com.cobblemon.mod.common.api.cooking.Seasonings
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity
@@ -212,7 +211,7 @@ class CookingPotMenu : RecipeBookMenu<CraftingInput, CookingPotRecipeBase>, Cont
}
override fun getRecipeBookType(): RecipeBookType {
return COOKING_POT
return RecipeBookType.valueOf("COOKING_POT")
}
override fun shouldMoveToInventory(slotIndex: Int): Boolean {
@@ -111,18 +111,13 @@ class CampfireBlockEntity(pos: BlockPos, state: BlockState) : BaseContainerBlock
BlockEntitySoundTracker.stop(pos, campfireBlockEntity.ambientSound.location)
}
val seasonings = campfireBlockEntity.getSeasonings()
if (seasonings.size != campfireBlockEntity.lastSeasoningStacks.size || seasonings.any { it !in campfireBlockEntity.lastSeasoningStacks }) {
campfireBlockEntity.lastSeasoningStacks = seasonings
campfireBlockEntity.brothColor =
getColourMixFromSeasonings(campfireBlockEntity.getSeasonings())
?: BASE_BROTH_COLOR
campfireBlockEntity.brothColor =
getColourMixFromSeasonings(seasonings)
?: BASE_BROTH_COLOR
campfireBlockEntity.bubbleColor =
getColourMixFromSeasonings(seasonings, true)
?: BASE_BROTH_BUBBLE_COLOR
}
campfireBlockEntity.bubbleColor =
getColourMixFromSeasonings(campfireBlockEntity.getSeasonings(), true)
?: BASE_BROTH_BUBBLE_COLOR
if (campfireBlockEntity.particleCooldown > 0) {
campfireBlockEntity.particleCooldown--
@@ -246,9 +241,6 @@ class CampfireBlockEntity(pos: BlockPos, state: BlockState) : BaseContainerBlock
var bubbleColor: Int = BASE_BROTH_BUBBLE_COLOR
var time: Int = 0
/** Used to know if we should be changing the colour of the broth or if we can go with the previous colour. */
var lastSeasoningStacks = listOf<ItemStack>()
var dataAccess: ContainerData = object : ContainerData {
override fun get(index: Int): Int {
return when (index) {
@@ -49,6 +49,7 @@ import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.state.BlockState
import java.util.*
open class PokeSnackBlockEntity(pos: BlockPos, state: BlockState) :
TintBlockEntity(CobblemonBlockEntities.POKE_SNACK, pos, state),
@@ -119,7 +120,7 @@ open class PokeSnackBlockEntity(pos: BlockPos, state: BlockState) :
level.dimension(),
)
block.eat(level, blockPos, blockState, null)
block.eat(level, blockPos, blockState, action.spawnablePosition.cause.entity as? Player)
}
}
@@ -8,9 +8,7 @@
package com.cobblemon.mod.common.client
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.Cobblemon.cobblemonVR
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonClientImplementation
@@ -29,7 +27,6 @@ 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
import com.cobblemon.mod.common.client.integration.vivecraft.CobblemonVRClient
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
import com.cobblemon.mod.common.client.render.DeferredRenderer
@@ -75,7 +72,6 @@ import com.cobblemon.mod.common.client.tooltips.TooltipManager
import com.cobblemon.mod.common.client.trade.ClientTrade
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.integration.vivecraft.CobblemonVR
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
import com.cobblemon.mod.common.util.isLookingAt
@@ -156,10 +152,6 @@ object CobblemonClient {
this.registerTooltipManagers()
this.registerMenuScreens()
if (Cobblemon.implementation.isModInstalled("vivecraft")) { // VR integration
CobblemonVRClient.init()
}
LOGGER.info("Registering custom BuiltinItemRenderers")
CobblemonBuiltinItemRendererRegistry.register(CobblemonItems.POKEMON_MODEL, PokemonItemRenderer())
@@ -194,10 +186,8 @@ object CobblemonClient {
) { it is PokemonEntity }
nearbyPokemon?.forEach { entity ->
if (entity is PokemonEntity && !entity.isSilent && !entity.passengers.contains(player)) {
if (player.isLookingAt(entity) && !player.isSpectator && entity.pokemon.shiny) entity.delegate.spawnShinyParticle(
player
)
if (entity is PokemonEntity && !entity.isSilent) {
if (player.isLookingAt(entity) && !player.isSpectator && entity.pokemon.shiny) entity.delegate.spawnShinyParticle(player)
entity.delegate.spawnAspectParticle()
}
}
@@ -379,10 +369,7 @@ object CobblemonClient {
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.CAMPFIRE, ::CampfireBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(
CobblemonBlockEntities.POKE_SNACK,
::PokeSnackBlockEntityRenderer
)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.POKE_SNACK, ::PokeSnackBlockEntityRenderer)
}
private fun registerEntityRenderers() {
@@ -411,11 +398,7 @@ object CobblemonClient {
private fun registerItemColors() {
implementation.registerItemColors(AprijuiceItemColorProvider, *CobblemonItems.aprijuices.toTypedArray())
implementation.registerItemColors(
PokeSnackItemColorProvider,
CobblemonItems.POKE_SNACK,
CobblemonItems.POKE_CAKE
)
implementation.registerItemColors(PokeSnackItemColorProvider, CobblemonItems.POKE_SNACK, CobblemonItems.POKE_CAKE)
implementation.registerItemColors(PokeBaitItemColorProvider, CobblemonItems.POKE_BAIT)
implementation.registerItemColors(PonigiriItemColorProvider, CobblemonItems.PONIGIRI)
implementation.registerItemColors(SinisterTeaItemColorProvider, CobblemonItems.SINISTER_TEA)
@@ -38,7 +38,7 @@ import kotlin.math.max
class RideControlsOverlay : Gui(Minecraft.getInstance()) {
companion object {
private const val CONTROLS_FADE_FRAMES = 20F
private const val FADE_FRAMES = 20F
private const val BASELINE_FPS = 60F
private const val HALF_SCALE = 0.5F
@@ -63,9 +63,9 @@ class RideControlsOverlay : Gui(Minecraft.getInstance()) {
private val screenExemptions: List<Class<out Screen>> = listOf(ChatScreen::class.java)
private var controlsMaxDurationFrames = Cobblemon.config.displayControlSeconds * BASELINE_FPS
private var controlsDurationFrames = controlsMaxDurationFrames
private var controlsFadeFrames = CONTROLS_FADE_FRAMES
private var maxDurationFrames = Cobblemon.config.displayControlSeconds * BASELINE_FPS
private var durationFrames = maxDurationFrames
private var fadeFrames = FADE_FRAMES
private var lastMouseX = 0
private var lastMouseY = 0
@@ -88,132 +88,123 @@ class RideControlsOverlay : Gui(Minecraft.getInstance()) {
if (minecraft.options.hideGui || minecraft.debugOverlay.showDebugScreen()) return
minecraft.player?.let { player ->
val riddenEntity = player.vehicle
if (riddenEntity != null && riddenEntity is PokemonEntity) {
// Only show controls to driver
if (riddenEntity === player.controlledVehicle) {
renderControls(minecraft, context, tickCounter, riddenEntity)
}
} else {
resetControlsOverlayState()
val riddenEntity = minecraft.player?.vehicle
if (riddenEntity != null && riddenEntity is PokemonEntity) {
// Update max duration if user has changed config
val configDuration = Cobblemon.config.displayControlSeconds * BASELINE_FPS
if (maxDurationFrames != configDuration) {
maxDurationFrames = configDuration
resetOverlayState()
}
// Don't render if duration config set to 0 or less
if (maxDurationFrames <= 0F) return
val rideBehaviourSettings = riddenEntity.ridingController?.context?.settings ?: return
val ridingBehaviourState = riddenEntity.ridingController?.context?.state ?: return
val rideBehaviourKey = rideBehaviourSettings.key
// Update current ride behaviour if changed
// If composite, get active behaviour instead
if (rideBehaviourKey == CompositeBehaviour.KEY) {
val activeBehaviour = (ridingBehaviourState as CompositeState).activeBehaviour.get()
if (currentBehaviourKey != activeBehaviour) {
currentBehaviourKey = activeBehaviour
resetOverlayState()
}
} else if (currentBehaviourKey != rideBehaviourKey) {
currentBehaviourKey = rideBehaviourKey
resetOverlayState()
}
// Render elements if entity has ride behaviour and if display duration has not ended yet
if (rideBehaviourSettings != null && fadeFrames > 0) {
val tickDelta = tickCounter.realtimeDeltaTicks.takeIf { !minecraft.isPaused } ?: 0F
val updateInterval = (tickDelta / 20F) * BASELINE_FPS
durationFrames = max(durationFrames - updateInterval, 0F)
if (durationFrames == 0F && fadeFrames > 0) fadeFrames = max(fadeFrames - updateInterval, 0F)
var showVerticalMouse = true // Show moving mouse up and down with arrows
var showHorizontalMouse = true // Show moving mouse left and right with arrows
var showSneakKey = true
var showJumpKey = true
var showMovementKeys = true
var disableHorizontalMovementKeys = false // Disable left and right movement keys
// Configure what controls to show for each behaviour
when (currentBehaviourKey) {
BirdBehaviour.KEY -> {}
BoatBehaviour.KEY -> {
showVerticalMouse = false
showHorizontalMouse = false
showSneakKey = false
}
BurstBehaviour.KEY -> {}
DolphinBehaviour.KEY -> {
disableHorizontalMovementKeys = true
showSneakKey = false
showJumpKey = false
}
GliderBehaviour.KEY -> {}
HelicopterBehaviour.KEY -> {}
HorseBehaviour.KEY -> {
showVerticalMouse = false
disableHorizontalMovementKeys = true
showSneakKey = false
}
HoverBehaviour.KEY -> {
showVerticalMouse = false
}
JetBehaviour.KEY -> {
showSneakKey = false
showJumpKey = false
}
MinekartBehaviour.KEY -> {
showVerticalMouse = false
showHorizontalMouse = false
showSneakKey = false
}
RocketBehaviour.KEY -> {
showVerticalMouse = false
showHorizontalMouse = false
}
VehicleBehaviour.KEY -> {}
}
val centerX = minecraft.window.guiScaledWidth / 2
val centerY = minecraft.window.guiScaledHeight / 2
renderMouseControls(
context,
!showMovementKeys && !showJumpKey && !showSneakKey,
showHorizontalMouse,
showVerticalMouse,
centerX,
centerY / 2,
fadeFrames / FADE_FRAMES
)
renderKeyControls(
context,
!showHorizontalMouse && !showVerticalMouse,
showMovementKeys,
disableHorizontalMovementKeys,
showJumpKey,
showSneakKey,
minecraft.player?.input,
centerX,
centerY / 2,
fadeFrames / FADE_FRAMES
)
}
} else {
resetOverlayState()
}
}
private fun renderControls(minecraft: Minecraft, context: GuiGraphics, tickCounter: DeltaTracker, riddenEntity: PokemonEntity) {
// Update max duration if user has changed config
val configDuration = Cobblemon.config.displayControlSeconds * BASELINE_FPS
if (controlsMaxDurationFrames != configDuration) {
controlsMaxDurationFrames = configDuration
resetControlsOverlayState()
}
// Don't render if duration config set to 0 or less
if (controlsMaxDurationFrames <= 0F) return
val rideBehaviourSettings = riddenEntity.ridingController?.context?.settings ?: return
val ridingBehaviourState = riddenEntity.ridingController?.context?.state ?: return
val rideBehaviourKey = rideBehaviourSettings.key
// Update current ride behaviour if changed
// If composite, get active behaviour instead
if (rideBehaviourKey == CompositeBehaviour.KEY) {
val activeBehaviour = (ridingBehaviourState as CompositeState).activeBehaviour.get()
if (currentBehaviourKey != activeBehaviour) {
currentBehaviourKey = activeBehaviour
resetControlsOverlayState()
}
} else if (currentBehaviourKey != rideBehaviourKey) {
currentBehaviourKey = rideBehaviourKey
resetControlsOverlayState()
}
// Render elements if entity has ride behaviour and if display duration has not ended yet
if (rideBehaviourSettings != null && controlsFadeFrames > 0) {
val tickDelta = tickCounter.realtimeDeltaTicks.takeIf { !minecraft.isPaused } ?: 0F
val updateInterval = (tickDelta / 20F) * BASELINE_FPS
controlsDurationFrames = max(controlsDurationFrames - updateInterval, 0F)
if (controlsDurationFrames == 0F && controlsFadeFrames > 0) controlsFadeFrames = max(controlsFadeFrames - updateInterval, 0F)
var showVerticalMouse = true // Show moving mouse up and down with arrows
var showHorizontalMouse = true // Show moving mouse left and right with arrows
var showSneakKey = true
var showJumpKey = true
var showMovementKeys = true
var disableHorizontalMovementKeys = false // Disable left and right movement keys
// Configure what controls to show for each behaviour
when (currentBehaviourKey) {
BirdBehaviour.KEY -> {}
BoatBehaviour.KEY -> {
showVerticalMouse = false
showHorizontalMouse = false
showSneakKey = false
}
BurstBehaviour.KEY -> {}
DolphinBehaviour.KEY -> {
disableHorizontalMovementKeys = true
showSneakKey = false
showJumpKey = false
}
GliderBehaviour.KEY -> {}
HelicopterBehaviour.KEY -> {}
HorseBehaviour.KEY -> {
showVerticalMouse = false
disableHorizontalMovementKeys = true
showSneakKey = false
}
HoverBehaviour.KEY -> {
showVerticalMouse = false
}
JetBehaviour.KEY -> {
showSneakKey = false
showJumpKey = false
}
MinekartBehaviour.KEY -> {
showVerticalMouse = false
showHorizontalMouse = false
showSneakKey = false
}
RocketBehaviour.KEY -> {
showVerticalMouse = false
showHorizontalMouse = false
}
VehicleBehaviour.KEY -> {}
}
val centerX = minecraft.window.guiScaledWidth / 2
val centerY = minecraft.window.guiScaledHeight / 2
renderMouseControls(
context,
!showMovementKeys && !showJumpKey && !showSneakKey,
showHorizontalMouse,
showVerticalMouse,
centerX,
centerY / 2,
controlsFadeFrames / CONTROLS_FADE_FRAMES
)
renderKeyControls(
context,
!showHorizontalMouse && !showVerticalMouse,
showMovementKeys,
disableHorizontalMovementKeys,
showJumpKey,
showSneakKey,
minecraft.player?.input,
centerX,
centerY / 2,
controlsFadeFrames / CONTROLS_FADE_FRAMES
)
}
}
private fun resetControlsOverlayState() {
if (controlsDurationFrames != controlsMaxDurationFrames) controlsDurationFrames = controlsMaxDurationFrames
if (controlsFadeFrames != CONTROLS_FADE_FRAMES) controlsFadeFrames = CONTROLS_FADE_FRAMES
private fun resetOverlayState() {
if (durationFrames != maxDurationFrames) durationFrames = maxDurationFrames
if (fadeFrames != FADE_FRAMES) fadeFrames = FADE_FRAMES
if (mouseMovedUp != null) {
mouseMovedUp = null
lastMouseY = 0
@@ -422,7 +413,7 @@ class RideControlsOverlay : Gui(Minecraft.getInstance()) {
if (showJump || showSneak) {
val offsetY = if (showMovement) 0 else -14
var label: MutableComponent?
var label: MutableComponent? = null
if (showJump && showSneak) {
label = "key.sneak".asTranslated().append("/").append("key.jump".asTranslated())
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pc
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.gui.getPixelRGB
import com.cobblemon.mod.common.api.storage.StorePosition
import com.cobblemon.mod.common.api.storage.party.PartyPosition
import com.cobblemon.mod.common.api.storage.pc.PCPosition
@@ -283,6 +284,20 @@ class StorageWidget(
height = 189,
alpha = if (screenLoaded) 1F else ((pcGui.ticksElapsed).toFloat() / 10F).coerceIn(0F, 1F)
)
} else {
val rgb = getPixelRGB(x + (SCREEN_WIDTH / 2), y + (SCREEN_HEIGHT / 2))
blitk(
matrixStack = matrices,
texture = screenGlowResource,
x = x - 17,
y = y - 17,
width = 208,
height = 189,
red = rgb.first / 255F,
green = rgb.second / 255F,
blue = rgb.third / 255F,
alpha = if (screenLoaded) 1F else ((pcGui.ticksElapsed).toFloat() / 10F).coerceIn(0F, 1F)
)
}
blitk(
@@ -592,10 +592,6 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
}
private fun switchForm(nextIndex: Boolean) {
if (visibleForms.isEmpty() || currentEntry == null) {
return
}
selectedPoseIndex = 0
if (nextIndex) {
@@ -606,8 +602,6 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
else selectedFormIndex = visibleForms.lastIndex
}
selectedFormIndex = selectedFormIndex.coerceIn(0, visibleForms.lastIndex)
setupButtons(currentEntry!!, visibleForms[selectedFormIndex])
updateAspects()
}
@@ -1,26 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft
import com.cobblemon.mod.common.client.integration.vivecraft.party.PartyOnArm
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityManager
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityRegistration
import com.cobblemon.mod.common.client.integration.vivecraft.listener.proximity.PokeRodBaitListener
import org.vivecraft.api.data.VRBodyPart
class CobblemonVRClient {
companion object {
fun init() {
PartyOnArm.init()
ProximityManager.init()
ProximityManager.register(
ProximityRegistration(
bodyA = VRBodyPart.MAIN_HAND,
bodyB = VRBodyPart.OFF_HAND,
distanceThreshold = 0.25f,
angleThreshold = 120f,
listener = PokeRodBaitListener("Main-OffHand")
)
)
}
}
}
@@ -1,40 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.listener.proximity
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityListener
import com.cobblemon.mod.common.client.integration.vivecraft.proximity.ProximityRegistration
import com.cobblemon.mod.common.net.messages.server.pokerod.ApplyBaitPacket
import net.minecraft.client.Minecraft
import net.minecraft.world.InteractionHand
import net.minecraft.world.item.ItemStack
import org.vivecraft.api.data.VRBodyPart
import org.vivecraft.api.data.VRPose
class PokeRodBaitListener(private val name: String) : ProximityListener {
//TODO: Also add that if 1 is Rod the other needs to be seasoning
override fun isActive(registration: ProximityRegistration): Boolean {
val player = Minecraft.getInstance().player ?: return false
val handA: InteractionHand = VRBodyPart.toInteractionHand(registration.bodyA) ?: return false
val itemStackA: ItemStack = player.getItemInHand(handA)
val handB: InteractionHand = VRBodyPart.toInteractionHand(registration.bodyB) ?: return false
val itemStackB: ItemStack = player.getItemInHand(handB)
return itemStackA.`is`(CobblemonItemTags.POKE_RODS) || itemStackB.`is`(CobblemonItemTags.POKE_RODS)
}
override fun onEnter(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose) {
Cobblemon.LOGGER.info("[$name] Enter: $bodyA <-> $bodyB")
}
override fun onExit(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose) {
Cobblemon.LOGGER.info("[$name] Exit: $bodyA <-> $bodyB")
}
override fun onTick(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose) {
Cobblemon.LOGGER.info("[$name] Proximity: $bodyA <-> $bodyB")
CobblemonNetwork.sendToServer(ApplyBaitPacket())
}
}
@@ -1,237 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.listener.swing
import com.cobblemon.mod.common.Cobblemon
import net.minecraft.client.Minecraft
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
import org.vivecraft.api.client.VRClientAPI
import org.vivecraft.api.client.tracker.swing.SwingContext
import org.vivecraft.api.client.tracker.swing.SwingListener
import org.vivecraft.api.data.VRBodyPart
import kotlin.math.abs
/**
* Listener that classifies directional swings (up, down, forward, backward, left, right)
* using Vivecraft VR pose history and invokes handler methods for each direction.
*
* @param forwardDotThreshold Dot product threshold used to classify forward/back/left/right directions.
* @param historyTicks Number of ticks used to compute velocity from historical poses.
*/
abstract class DirectionalSwingListener(
private val forwardDotThreshold: Double = 0.3,
private val historyTicks: Int = 10
) : SwingListener {
protected val minecraft: Minecraft = Minecraft.getInstance()
protected val clientData: VRClientAPI = VRClientAPI.instance()
/**
* Compute the net movement vector for the specified body part over the given number of ticks.
* Returns null if historical pose data is unavailable, insufficient, or movement is negligible.
*
* @param bodyPart The VR body part to compute movement for.
* @param ticks The number of ticks of history to consider.
* @return The movement vector or null if unavailable/insignificant.
*/
private fun changeForVelocity(bodyPart: VRBodyPart, ticks: Int = historyTicks): Vec3? {
val history = clientData.historicalVRPoses ?: return null
if (history.ticksOfHistory() < ticks) return null
val delta = history.netMovement(bodyPart, ticks)
delta?.lengthSqr()?.let { if (it < 1e-6) return null }
return delta
}
/**
* Called when an upward swing is detected.
*
* @param useHand The hand used for the swing.
* @param handVel The velocity vector of the hand during the swing.
* @param player The player performing the swing.
* @return True if the upward action was handled, false otherwise.
*/
protected open fun onUpwardSwing(
useHand: InteractionHand,
player: Player
): Boolean {
Cobblemon.LOGGER.info(
"Ignoring swing: upward movement. player={}, hand={}",
player, useHand
)
return true
}
/**
* Called when a downward swing is detected.
*
* @param useHand The hand used for the swing.
* @param handVel The velocity vector of the hand during the swing.
* @param player The player performing the swing.
* @return True if the downward action was handled, false otherwise.
*/
protected open fun onDownwardSwing(
useHand: InteractionHand,
handVel: Vec3,
player: Player
): Boolean {
Cobblemon.LOGGER.info(
"Ignoring swing: downward movement. handVel={}, player={}, hand={}",
handVel, player, useHand
)
return true
}
/**
* Called when a forward swing is detected.
*
* @param useHand The hand used for the swing.
* @param handVel The velocity vector of the hand during the swing.
* @param player The player performing the swing.
* @return True if the forward action was handled, false otherwise.
*/
protected open fun onForwardSwing(
useHand: InteractionHand,
handVel: Vec3,
player: Player
): Boolean {
return true
}
/**
* Called when a backward swing is detected.
*
* @param useHand The hand used for the swing.
* @param handVel The velocity vector of the hand during the swing.
* @param player The player performing the swing.
* @return True if the backward action was handled, false otherwise.
*/
protected open fun onBackwardSwing(
useHand: InteractionHand,
handVel: Vec3,
player: Player
): Boolean {
Cobblemon.LOGGER.info(
"Ignoring swing: backward movement. handVel={}, player={}, hand={}",
handVel, player, useHand
)
return true
}
/**
* Called when a leftward swing is detected.
*
* @param useHand The hand used for the swing.
* @param handVel The velocity vector of the hand during the swing.
* @param player The player performing the swing.
* @return True if the leftward action was handled, false otherwise.
*/
protected open fun onLeftSwing(
useHand: InteractionHand,
handVel: Vec3,
player: Player
): Boolean {
Cobblemon.LOGGER.info(
"Ignoring swing: leftward movement. handVel={}, player={}, hand={}",
handVel, player, useHand
)
return true
}
/**
* Called when a rightward swing is detected.
*
* @param useHand The hand used for the swing.
* @param handVel The velocity vector of the hand during the swing.
* @param player The player performing the swing.
* @return True if the rightward action was handled, false otherwise.
*/
protected open fun onRightSwing(
useHand: InteractionHand,
handVel: Vec3,
player: Player
): Boolean {
Cobblemon.LOGGER.info(
"Ignoring swing: rightward movement. handVel={}, player={}, hand={}",
handVel, player, useHand
)
return true
}
/**
* Checks if the given item stack is valid for processing by this swing listener.
* Subclasses must implement this to specify which items they handle.
* @param itemStack The item stack to validate.
* @return True if the item stack is valid, false otherwise.
*/
protected abstract fun isValidItem(itemStack: ItemStack): Boolean
/**
* Called when a swing ends. Validates the held item, computes hand velocity from historical poses,
* handles vertical swings first (upward/downward) and then classifies horizontal direction:
* forward/backward by dot with player look direction; left/right by projecting onto a right vector
* computed from world up and forward. Ambiguous swings are ignored.
*
* @param context Vivecraft swing context containing body part information.
*/
override fun onSwingEnd(context: SwingContext?) {
val player = minecraft.player ?: return
val ctx = context ?: return
val useHand: InteractionHand = VRBodyPart.toInteractionHand(ctx.bodyPart) ?: return
val itemStack: ItemStack = player.getItemInHand(useHand)
if (!isValidItem(itemStack)) return
val handVel = changeForVelocity(ctx.bodyPart) ?: run {
Cobblemon.LOGGER.info(
"Ignoring swing: insufficient historical pose data for velocity. bodyPart={}, player={}",
ctx.bodyPart, player
)
return
}
val vertical = handVel.y
if (vertical > 0.0) {
if (onUpwardSwing(useHand, player)) return
} else if (vertical < 0.0) {
if (onDownwardSwing(useHand, handVel, player)) return
}
val forward = player.lookAngle.normalize()
val handDir = handVel.normalize()
val forwardDot = handDir.dot(forward)
val worldUp = Vec3(0.0, 1.0, 0.0)
val right = forward.cross(worldUp).let {
if (it.lengthSqr() < 1e-6) Vec3(1.0, 0.0, 0.0) else it.normalize()
}
val rightDot = handDir.dot(right)
if (forwardDot > forwardDotThreshold) {
if (onForwardSwing(useHand, handVel, player)) return
return
}
if (forwardDot < -forwardDotThreshold) {
if (onBackwardSwing(useHand, handVel, player)) return
return
}
if (abs(rightDot) > forwardDotThreshold) {
if (rightDot > 0.0) {
if (onRightSwing(useHand, handVel, player)) return
} else {
if (onLeftSwing(useHand, handVel, player)) return
}
return
}
Cobblemon.LOGGER.info(
"Ignoring swing: ambiguous direction. forwardDot={}, rightDot={}, handVel={}, player={}",
forwardDot, rightDot, handVel, player
)
}
}
@@ -1,29 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.listener.swing
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
class PokeBallSwingListener : DirectionalSwingListener() {
override fun isValidItem(itemStack: ItemStack): Boolean =
itemStack.`is`(CobblemonItemTags.POKE_BALLS)
override fun onForwardSwing(
useHand: InteractionHand,
handVel: Vec3,
player: Player
): Boolean {
CobblemonNetwork.sendToServer(SendOutPokeBallPacket())
return true
}
override fun onDownwardSwing(useHand: InteractionHand, handVel: Vec3, player: Player): Boolean {
CobblemonNetwork.sendToServer(SendOutPokeBallPacket())
return super.onDownwardSwing(useHand, handVel, player)
}
}
@@ -1,31 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.listener.swing
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.net.messages.server.pokerod.CastPokeRodPacket
import com.cobblemon.mod.common.net.messages.server.pokerod.ReelPokeRodPacket
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.phys.Vec3
class PokeRodSwingListener : DirectionalSwingListener() {
override fun isValidItem(itemStack: ItemStack): Boolean =
itemStack.`is`(CobblemonItemTags.POKE_RODS)
override fun onUpwardSwing(useHand: InteractionHand, player: Player): Boolean {
CobblemonNetwork.sendToServer(ReelPokeRodPacket(useHand == InteractionHand.MAIN_HAND))
return super.onUpwardSwing(useHand, player)
}
override fun onForwardSwing(useHand: InteractionHand, handVel: Vec3, player: Player): Boolean {
CobblemonNetwork.sendToServer(CastPokeRodPacket(useHand == InteractionHand.MAIN_HAND))
return super.onForwardSwing(useHand, handVel, player)
}
override fun onDownwardSwing(useHand: InteractionHand, handVel: Vec3, player: Player): Boolean {
CobblemonNetwork.sendToServer(CastPokeRodPacket(useHand == InteractionHand.MAIN_HAND))
return super.onDownwardSwing(useHand, handVel, player)
}
}
@@ -1,188 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.party
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.platform.events.ClientTickEvent
import com.cobblemon.mod.common.platform.events.PlatformEvents
import com.cobblemon.mod.common.platform.events.RenderEvent
import com.cobblemon.mod.common.pokemon.Pokemon
import com.mojang.math.Axis
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.player.LocalPlayer
import net.minecraft.client.renderer.LightTexture
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.Entity
import net.minecraft.world.phys.Vec3
import org.joml.Vector3f
import org.vivecraft.api.VRAPI
import org.vivecraft.api.client.InteractModule
import org.vivecraft.api.client.VRClientAPI
import org.vivecraft.api.data.VRBodyPartData
import java.util.function.Consumer
class PartyOnArm : InteractModule {
val fakePartyEntities: Array<Entity?> = arrayOfNulls(6)
var selectedIndex = -1
private fun onTick(tickEvent: ClientTickEvent.Post) {
val client = tickEvent.client
client.player ?: return
val playerData = VRClientAPI.instance().postTickWorldPose ?: return
val offHandData = playerData.offHand
// Keep up-to-date fakePartyEntities, which is done so we always have a Pokemon or PokeBall entity available to
// render and keep it ticking so we have proper animations.
val party = CobblemonClient.storage.party
// Handle the selected index, placing either a Pokemon or null
if (selectedIndex > -1) {
val actual = party.get(selectedIndex)
if (actual == null) {
fakePartyEntities[selectedIndex] = null
} else if (fakePartyEntities[selectedIndex] is PokemonEntity) {
fakePartyEntities[selectedIndex]!!.tick()
} else {
fakePartyEntities[selectedIndex] = PokemonEntity(client.level!!, actual)
}
}
// Handle the other indices, placing a pokeball or null
for (i in 0..5) {
if (i != selectedIndex) {
val actual = party.get(i)
if (actual == null) {
fakePartyEntities[i] = null
} else if (fakePartyEntities[i] !is EmptyPokeBallEntity) {
val pokeBall = EmptyPokeBallEntity(actual.caughtBall, client.level!!)
pokeBall.captureState = EmptyPokeBallEntity.CaptureState.FALL
fakePartyEntities[i] = pokeBall
} else {
fakePartyEntities[i]!!.tick()
}
}
}
// Check primary hand for overlap with any of the Pokemon
val centerPos = getCenterPos(offHandData)
selectedIndex = -1
for (i in 0..5) {
if (party.get(i) != null) {
val pokemonPos = getPokemonPos(centerPos, playerData.offHand, i)
if (playerData.mainHand.pos.distanceToSqr(pokemonPos) < DIST_SELECT_SQR) {
selectedIndex = i
break
}
}
}
}
private fun onRender(renderEvent: RenderEvent) {
if (renderEvent.stage != RenderEvent.Stage.AFTER_ENTITIES) return
val mc = Minecraft.getInstance()
val bufferSource = mc.renderBuffers().bufferSource()
val guiGraphics = GuiGraphics(mc, mc.renderBuffers().bufferSource())
val cameraPos = renderEvent.camera.getPosition()
val poseStack = guiGraphics.pose()
val partialTick = renderEvent.tickCounter.getGameTimeDeltaPartialTick(true)
val offHandData = VRClientAPI.instance().getWorldRenderPose()?.offHand ?: return
val centerPos = getCenterPos(offHandData)
for (i in 0..5) {
val pokemon = fakePartyEntities[i]
if (pokemon != null) {
poseStack.pushPose()
val pokemonPos = getPokemonPos(centerPos, offHandData, i)
val renderPos = Vec3(
-cameraPos.x + pokemonPos.x,
-cameraPos.y + pokemonPos.y,
-cameraPos.z + pokemonPos.z,
)
poseStack.translate(renderPos.x, renderPos.y, renderPos.z)
poseStack.scale(0.05f, 0.05f, 0.05f)
poseStack.mulPose(Axis.YN.rotation(offHandData.yaw.toFloat()))
poseStack.mulPose(Axis.XN.rotation(offHandData.pitch.toFloat()))
poseStack.mulPose(Axis.ZP.rotation(offHandData.roll.toFloat() + Math.PI.toFloat()))
mc.entityRenderDispatcher.getRenderer(pokemon).render(pokemon, 0f, partialTick, poseStack, bufferSource,
LightTexture.FULL_BRIGHT)
poseStack.popPose()
}
}
}
private fun getCenterPos(pose: VRBodyPartData): Vec3 {
return pose.pos.subtract(pose.dir.scale(0.125))
}
private fun getPokemonPos(centerPos: Vec3, controllerData: VRBodyPartData, index: Int): Vec3 {
var pos = centerPos
// Move to bottom of hand
var downVecF = Vector3f(0f, -0.0625f, 0f)
downVecF.rotate(Axis.ZP.rotation(controllerData.roll.toFloat()))
downVecF.rotate(Axis.XN.rotation(controllerData.pitch.toFloat()))
downVecF.rotate(Axis.YN.rotation(controllerData.yaw.toFloat()))
pos = pos.add(Vec3(downVecF.x.toDouble(), downVecF.y.toDouble(), downVecF.z.toDouble()))
// Move right or left based on index
val rightF = Vector3f(0f, 0f, 1f) // Default forward vector of Minecraft
rightF.rotate(Axis.YN.rotation(Math.PI.toFloat() / 2f))
rightF.rotate(Axis.ZP.rotation(controllerData.roll.toFloat()))
rightF.rotate(Axis.XN.rotation(controllerData.pitch.toFloat()))
rightF.rotate(Axis.YN.rotation(controllerData.yaw.toFloat()))
val right = Vec3(rightF.x.toDouble(), rightF.y.toDouble(), rightF.z.toDouble())
if (index > 2) {
pos = pos.add(right.scale(-0.0625))
} else {
pos = pos.add(right.scale(0.0625))
}
// Offset by -hand direction if on left, 0 if center, or +hand direction if right
return pos.add(controllerData.dir.scale(DIST_BETWEEN_HORIZONTAL * (index % 3 - 1)))
}
override fun getId(): ResourceLocation {
return INTERACT_ID
}
override fun isActive(
player: LocalPlayer,
hand: InteractionHand,
handPosition: Vec3
): Boolean {
return hand == InteractionHand.MAIN_HAND && selectedIndex > -1
}
override fun onPress(
player: LocalPlayer,
hand: InteractionHand
): Boolean {
// UUID lookup is done at press time since the Pokemon may have switched since initially hovered over, such
// as via commands.
val uuid = CobblemonClient.storage.party.get(selectedIndex)?.uuid ?: return false
CobblemonClient.storage.switchToPokemon(uuid)
return true
}
companion object {
const val DIST_BETWEEN_HORIZONTAL: Double = 0.125
const val DIST_BETWEEN_VERTICAL: Float = 0.05f
const val DIST_SELECT_SQR: Double = 0.1 * 0.1
val INTERACT_ID = ResourceLocation(Cobblemon.MODID, "party_on_arm_interact_module")
private val INSTANCE = PartyOnArm()
fun init() {
PlatformEvents.RENDER.subscribe(Consumer { renderEvent: RenderEvent? -> INSTANCE.onRender(renderEvent!!) })
PlatformEvents.CLIENT_TICK_POST.subscribe(Consumer { tickEvent: ClientTickEvent.Post? ->
INSTANCE.onTick(
tickEvent!!
)
})
VRAPI.instance().register(INSTANCE)
}
}
}
@@ -1,12 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.proximity
import org.vivecraft.api.data.VRBodyPart
import org.vivecraft.api.data.VRPose
// TODO: Make an PR to Vivecraft that adds this feature directly to Vivecraft
interface ProximityListener {
fun isActive(registration: ProximityRegistration): Boolean = true
fun onEnter(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose)
fun onExit(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose)
fun onTick(bodyA: VRBodyPart, bodyB: VRBodyPart, pose: VRPose)
}
@@ -1,79 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.proximity
import com.cobblemon.mod.common.platform.events.ClientTickEvent
import com.cobblemon.mod.common.platform.events.PlatformEvents
import org.vivecraft.api.client.VRClientAPI
import kotlin.math.acos
// TODO: Make an PR to Vivecraft that adds this feature directly to Vivecraft
class ProximityManager {
private val registrations = mutableListOf<ProximityRegistration>()
private val previousInProximity = mutableMapOf<ProximityRegistration, Boolean>()
private val api: VRClientAPI = VRClientAPI.instance()
fun register(registration: ProximityRegistration) {
registrations += registration
previousInProximity.putIfAbsent(registration, false)
}
fun unregister(registration: ProximityRegistration) {
registrations -= registration
previousInProximity.remove(registration)
}
fun clear() {
registrations.clear()
previousInProximity.clear()
}
fun isActive(registration: ProximityRegistration): Boolean {
return registration.listener.isActive(registration)
}
fun onTick(tickEvent: ClientTickEvent.Post) {
val vrPose = api.getPostTickWorldPose() ?: return
for (reg in registrations) {
if (!isActive(reg)) continue
val poseA = vrPose.getBodyPartData(reg.bodyA) ?: continue
val poseB = vrPose.getBodyPartData(reg.bodyB) ?: continue
val distance = poseA.pos.distanceTo(poseB.pos)
val dot = poseA.dir.dot(poseB.dir).coerceIn(-1.0, 1.0)
val angleDeg = Math.toDegrees(acos(dot)).toFloat()
val angleOk = angleDeg <= reg.angleThreshold
val nowInProximity = distance <= reg.distanceThreshold && angleOk
val wasInProximity = previousInProximity[reg] ?: false
if (!wasInProximity && nowInProximity) {
reg.listener.onEnter(reg.bodyA, reg.bodyB, vrPose)
} else if (wasInProximity && !nowInProximity) {
reg.listener.onExit(reg.bodyA, reg.bodyB, vrPose)
}
if (nowInProximity) {
reg.listener.onTick(reg.bodyA, reg.bodyB, vrPose)
}
previousInProximity[reg] = nowInProximity
}
}
companion object {
private val INSTANCE = ProximityManager()
fun init() {
PlatformEvents.CLIENT_TICK_POST.subscribe { tickEvent: ClientTickEvent.Post? ->
INSTANCE.onTick(
tickEvent!!
)
}
}
fun register(registration: ProximityRegistration) = INSTANCE.register(registration)
fun unregister(registration: ProximityRegistration) = INSTANCE.unregister(registration)
fun clearAll() = INSTANCE.clear()
}
}
@@ -1,12 +0,0 @@
package com.cobblemon.mod.common.client.integration.vivecraft.proximity
import org.vivecraft.api.data.VRBodyPart
// TODO: Make an PR to Vivecraft that adds this feature directly to Vivecraft
data class ProximityRegistration(
val bodyA: VRBodyPart,
val bodyB: VRBodyPart,
val distanceThreshold: Float,
val angleThreshold: Float = 180f,
val listener: ProximityListener
)
@@ -38,7 +38,6 @@ object CobblemonKeyBinds {
val PARTY_OVERLAY_DOWN = this.queue(DownShiftPartyBinding)
val PARTY_OVERLAY_UP = this.queue(UpShiftPartyBinding)
val SEND_OUT_POKEMON = this.queue(PartySendBinding)
val RIDING_FREELOOK = this.queue(RidingFreelookBinding)
fun register(registrar: (KeyMapping) -> Unit) {
this.keyBinds.forEach(registrar::invoke)
@@ -1,29 +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.keybind.keybinds
import com.cobblemon.mod.common.client.keybind.CobblemonBlockingKeyBinding
import com.cobblemon.mod.common.client.keybind.KeybindCategories
import com.mojang.blaze3d.platform.InputConstants
object RidingFreelookBinding : CobblemonBlockingKeyBinding(
"key.cobblemon.ridingfreelook",
InputConstants.Type.KEYSYM,
InputConstants.KEY_LALT,
KeybindCategories.COBBLEMON_CATEGORY
) {
override fun onTick() {
}
override fun onRelease() {
}
override fun onPress() {
}
}
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.duck.CameraDuck
import com.cobblemon.mod.common.duck.RidePassenger
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.math.geometry.toRadians
import com.cobblemon.mod.common.util.toVec3d
import com.mojang.blaze3d.Blaze3D
import net.minecraft.client.Camera
import net.minecraft.client.CameraType
@@ -34,7 +35,6 @@ import net.minecraft.world.phys.HitResult
import net.minecraft.world.phys.Vec3
import org.joml.Matrix3f
import org.joml.Quaternionf
import org.joml.Vector3d
import org.joml.Vector3f
import kotlin.math.min
import kotlin.math.sign
@@ -81,6 +81,7 @@ object MountedCameraRenderer {
val currEyeHeight: Double = Mth.lerp(instance.partialTickTime.toDouble(), eyeHeight, eyeHeightOld)
var offset = Vec3(0.0, currEyeHeight - (driver.bbHeight / 2), 0.0)
var eyeOffset = Vec3(0.0, currEyeHeight - (driver.bbHeight / 2), 0.0)
val locatorOffset = Vec3(locator.matrix.getTranslation(Vector3f()))
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.cameraType == CameraType.FIRST_PERSON
@@ -102,17 +103,15 @@ object MountedCameraRenderer {
else Quaternionf()
.rotateY((Math.PI.toFloat() - Mth.lerp(instance.partialTickTime, vehicle.yRotO, vehicle.yRot).toRadians()))
offset = rotation.transform(Vector3d(offset.x, offset.y, offset.z)).let { Vec3(it.x, it.y, it.z) }
eyeOffset = rotation.transform(Vector3d(eyeOffset.x, eyeOffset.y, eyeOffset.z)).let { Vec3(it.x, it.y, it.z) }
offset = rotation.transform(offset.toVector3f()).toVec3d()
eyeOffset = rotation.transform(eyeOffset.toVector3f()).toVec3d()
val eyeLocatorOffset = Vec3(locator.matrix.getTranslation(Vector3f()))
val eyePos = eyeLocatorOffset.add(entityPos)
val eyePos = locatorOffset.add(entityPos)
// Get the camera position before offsets are applied (which are done with maxZoom to account for clipping). 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) { */
Vec3(locator.matrix.getTranslation(Vector3f()))
.add(entityPos)
locatorOffset.add(entityPos)
/* } else {
val pokemonCenter = Vector3f(0f, driver.bbHeight/2, 0f)
@@ -327,7 +326,7 @@ object MountedCameraRenderer {
locatorName: String,
shouldFlip: Boolean = true
): Vec3 {
val offset = if (thirdPersonReverse && cameraOffsets.containsKey(locatorName + "_reverse")) {
var offset = if (thirdPersonReverse && cameraOffsets.containsKey(locatorName + "_reverse")) {
cameraOffsets[locatorName + "_reverse"]!!
} else if (cameraOffsets.containsKey(locatorName)) {
cameraOffsets[locatorName]!!
@@ -337,7 +336,8 @@ object MountedCameraRenderer {
// Don't need to account for this since orientation is derived from camera rotation and that z is already flipped.
// Flip only when not on a rollable.
return if (thirdPersonReverse && shouldFlip) offset.multiply(1.0, 1.0, -1.0) else offset
if (thirdPersonReverse && shouldFlip) offset = offset.multiply(1.0, 1.0, -1.0)
return offset
}
private fun getFirstPersonOffset(model: PosableModel, locatorName: String): Vec3 {
@@ -0,0 +1,120 @@
/*
* 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.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
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.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.ModelPartTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
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 TinkatinkModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BimanualFrame {
override val rootPart = root.registerChildWithAllChildren("tinkatink")
override val head = getPart("head")
override val rightArm = getPart("arm_right")
override val leftArm = getPart("arm_left")
override val rightLeg = getPart("leg_right")
override val leftLeg = getPart("leg_left")
override var portraitScale = 2.0F
override var portraitTranslation = Vec3(0.0, -1.01, 0.0)
override var profileScale = 1.0F
override var profileTranslation = Vec3(0.0, 0.25, 0.0)
lateinit var standing: Pose
lateinit var walking: Pose
lateinit var sleep: Pose
lateinit var battleidle: Pose
lateinit var shoulderLeft: Pose
lateinit var shoulderRight: Pose
val shoulderOffset = 1
override val cryAnimation = CryProvider { bedrockStateful("tinkatink", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("tinkatink", "blink") }
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("tinkatink", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
condition = { !it.isBattling },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "ground_idle")
)
)
walking = registerPose(
poseName = "walking",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "battle_idle")
)
)
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
quirks = arrayOf(blink),
condition = { !it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "shoulder_left")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
quirks = arrayOf(blink),
condition = { !it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "shoulder_right")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, -shoulderOffset)
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walking, battleidle, sleep)) bedrockStateful("tinkatink", "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.gen9
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
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.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.util.isBattling
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class TinkatuffModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BimanualFrame {
override val rootPart = root.registerChildWithAllChildren("tinkatuff")
override val head = getPart("head")
override val rightArm = getPart("arm_right")
override val leftArm = getPart("arm_left")
override val rightLeg = getPart("leg_right")
override val leftLeg = getPart("leg_left")
override var portraitScale = 1.9F
override var portraitTranslation = Vec3(0.0, -0.41, 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 sleep: Pose
lateinit var battleidle: Pose
override val cryAnimation = CryProvider { bedrockStateful("tinkatuff", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("tinkatuff", "blink") }
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("tinkatuff", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
condition = { !it.isBattling },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatuff", "ground_idle")
)
)
walking = registerPose(
poseName = "walking",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatuff", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatuff", "battle_idle")
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walking, battleidle, sleep)) bedrockStateful("tinkatuff", "faint") else null
}
@@ -477,6 +477,8 @@ object VaryingModelRepository {
inbuilt("illumise", ::IllumiseModel)
inbuilt("yamper", ::YamperModel)
inbuilt("boltund", ::BoltundModel)
inbuilt("tinkatink", ::TinkatinkModel)
inbuilt("tinkatuff", ::TinkatuffModel)
inbuilt("fuecoco", :: FuecocoModel)
inbuilt("crocalor", :: CrocalorModel)
inbuilt("skeledirge", :: SkeledirgeModel)
@@ -39,16 +39,15 @@ class FollowWalkTargetTask(
private var lookTargetPos: BlockPos? = null
private var speed = 0f
override fun checkExtraStartConditions(level: ServerLevel, entity: PathfinderMob): Boolean {
override fun checkExtraStartConditions(arg: ServerLevel, arg2: PathfinderMob): Boolean {
if (this.pathUpdateCountdownTicks > 0) {
--this.pathUpdateCountdownTicks
return false
} else {
val brain = entity.brain
val brain = arg2.brain
val walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get()
val hasReached = this.hasReached(entity, walkTarget)
resetPathUpdateCountdownTicks(entity)
if (!hasReached && this.hasFinishedPath(entity, walkTarget, level.gameTime)) {
val hasReached = this.hasReached(arg2, walkTarget)
if (!hasReached && this.hasFinishedPath(arg2, walkTarget, arg.gameTime)) {
this.lookTargetPos = walkTarget.target.currentBlockPosition()
return true
} else {
@@ -62,10 +61,6 @@ class FollowWalkTargetTask(
}
}
fun resetPathUpdateCountdownTicks(entity: PathfinderMob) {
pathUpdateCountdownTicks = entity.random.nextInt(20) + 20
}
override fun canStillUse(arg: ServerLevel, arg2: PathfinderMob, l: Long): Boolean {
if (this.path != null && this.lookTargetPos != null) {
val optional = arg2.brain.getMemory(MemoryModuleType.WALK_TARGET)
@@ -80,7 +75,7 @@ class FollowWalkTargetTask(
override fun stop(world: ServerLevel, entity: PathfinderMob, l: Long) {
val walkTarget = entity.brain.getMemory(MemoryModuleType.WALK_TARGET).orElse(null)
if (walkTarget != null && !this.hasReached(entity, walkTarget) && entity.navigation.isStuck) {
resetPathUpdateCountdownTicks(entity)
this.pathUpdateCountdownTicks = world.getRandom().nextInt(40)
}
entity.navigation.stop()
@@ -186,7 +186,7 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
val blockState = this.world.getBlockState(target)
val path = if (!blockState.isSolid
|| (blockState.`is`(BlockTags.LEAVES) && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES && pather.canPathThroughSaccLeaves())) {
|| (blockState.`is`(BlockTags.LEAVES) && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES && (this.entity as PokemonEntity).canPathThroughSaccLeaves())) {
findPath(target, distance)
} else {
blockPos = target.above()
@@ -269,7 +269,7 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
// If we can fly and we're airborne, return the current Y position
return vec.y
}
if (world.getBlockState(blockPos).block == CobblemonBlocks.SACCHARINE_LEAVES && pather.canPathThroughSaccLeaves()) {
if (world.getBlockState(blockPos).block == CobblemonBlocks.SACCHARINE_LEAVES && (this.entity as PokemonEntity).canPathThroughSaccLeaves()) {
return vec.y + 0.5
}
return if ((canFloat()) && blockGetter.getFluidState(blockPos).`is`(FluidTags.WATER)) vec.y + 0.5 else super.getGroundY(vec)
@@ -802,14 +802,13 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
spawnAction.complete()
val result = spawnAction.future
val resultingSpawn = result.get()
if (resultingSpawn == null) {
if (result.isCompletedExceptionally) {
noBite(player)
return false
}
var spawnedPokemon: PokemonEntity? = null
val resultingSpawn = result.get()
if (resultingSpawn is EntitySpawnResult) {
for (entity in resultingSpawn.entities) {
@@ -547,11 +547,6 @@ open class PokemonEntity(
ifRidingAvailable { _, _, state -> pokemon.rideStamina = state.stamina.get() }
ridingController?.context?.state?.reset()
ridingAnimationData.clear()
// reset riding orientation
if (this is OrientationControllable) {
this.orientationController.reset()
}
}
}
@@ -1282,7 +1277,7 @@ open class PokemonEntity(
}
override fun shouldBeSaved(): Boolean {
if (ownerUUID == null && !pokemon.isNPCOwned() && (Cobblemon.config.savePokemonToWorld || isPersistenceRequired)) {
if (ownerUUID == null && !pokemon.isNPCOwned() && (Cobblemon.config.savePokemonToWorld || isPersistenceRequired || this.pokemon.canDropHeldItem)) {
CobblemonEvents.POKEMON_ENTITY_SAVE_TO_WORLD.postThen(PokemonEntitySaveToWorldEvent(this)) {
return true
}
@@ -10,11 +10,8 @@ package com.cobblemon.mod.common.entity.pokemon.ai.sensors
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getMemorySafely
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.Mob
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities
import net.minecraft.world.entity.ai.sensing.Sensor
@@ -31,17 +28,8 @@ class DefendOwnerSensor : Sensor<PokemonEntity>(10) {
}
private fun setNearestAttacker(entity: PokemonEntity, visibleMobs: NearestVisibleLivingEntities, owner: LivingEntity) {
val nearestAttacker = visibleMobs.findClosest { livingEntity ->
// Prevents Pokémons from attacking players as owned Pokémons are currently invulnerable
if (livingEntity is ServerPlayer) return@findClosest false
if (livingEntity.lastHurtMob == owner) return@findClosest true
if (livingEntity is Mob && livingEntity.target == owner) return@findClosest true
val mobAttackTarget = livingEntity.brain.getMemorySafely(MemoryModuleType.ATTACK_TARGET)
if (mobAttackTarget.isPresent && mobAttackTarget.get() == owner) return@findClosest true
return@findClosest false
val nearestAttacker = visibleMobs.findClosest { mob ->
mob.lastHurtMob == owner
}.map { mob -> mob as LivingEntity }
entity.brain.setMemory(CobblemonMemories.NEAREST_VISIBLE_ATTACKER, nearestAttacker)
@@ -10,10 +10,18 @@ package com.cobblemon.mod.common.entity.pokemon.ai.tasks
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.google.common.collect.ImmutableMap
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.ai.behavior.Behavior
import net.minecraft.world.entity.ai.behavior.OneShot
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.MemoryStatus
import net.minecraft.world.entity.ai.memory.WalkTarget
import net.minecraft.world.entity.ai.targeting.TargetingConditions
object DefendOwnerTask {
fun create(): OneShot<PokemonEntity> {
@@ -52,9 +52,8 @@ object PlaceHoneyInHiveTask {
if (blockEntity.isFull) {
// Erase Hive memory and give the bee a moment to locate a new hive
entity.brain.eraseMemory(CobblemonMemories.HIVE_LOCATION)
} else {
blockEntity.addOccupant(entity)
}
blockEntity.addOccupant(entity)
}
return@Trigger true
@@ -1,16 +0,0 @@
package com.cobblemon.mod.common.integration.vivecraft
import com.cobblemon.mod.common.client.integration.vivecraft.listener.swing.PokeBallSwingListener
import com.cobblemon.mod.common.client.integration.vivecraft.listener.swing.PokeRodSwingListener
import org.vivecraft.api.VRAPI
class CobblemonVR {
fun init() {
VRAPI.instance()
.register(PokeBallSwingListener())
VRAPI.instance()
.register(PokeRodSwingListener())
}
}
@@ -23,7 +23,7 @@ import net.minecraft.world.level.Level
import kotlin.math.cos
class PokeBallItem(
val pokeBall: PokeBall
val pokeBall: PokeBall
) : CobblemonItem(Properties().apply {
when (pokeBall.name) {
// Master balls are a netherite product and should be fire immune
@@ -43,7 +43,7 @@ class PokeBallItem(
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
}
fun throwPokeBall(world: Level, player: ServerPlayer) {
private fun throwPokeBall(world: Level, player: ServerPlayer) {
val pokeBallEntity = EmptyPokeBallEntity(pokeBall, player.level(), player).apply {
val overhandFactor: Float = if (player.xRot < 0) {
5f * cos(player.xRot.toRadians())
@@ -57,5 +57,4 @@ class PokeBallItem(
}
world.addFreshEntity(pokeBallEntity)
}
}
@@ -75,8 +75,7 @@ class PokerodItem(val pokeRodId: ResourceLocation, settings: Properties) : Fishi
if (baitCount > 1) {
baitStack.count = baitCount - 1
stack.set(
CobblemonItemComponents.BAIT, RodBaitComponent(baitStack)
stack.set(CobblemonItemComponents.BAIT, RodBaitComponent(baitStack)
)
}
}
@@ -150,163 +149,90 @@ class PokerodItem(val pokeRodId: ResourceLocation, settings: Properties) : Fishi
}
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
val itemStack = user.getItemInHand(hand)
val offHandItem = user.getItemInHand(InteractionHand.OFF_HAND)
attemptApplyOffhandBait(world, user, itemStack, offHandItem)?.let { return it }
// Check if offhand item is valid bait and the rod is not in use, if so then apply bait from offhand
if (!world.isClientSide && user.fishing == null && SpawnBaitEffects.isFishingBait(offHandItem)) {
CobblemonEvents.BAIT_SET_PRE.postThen(BaitSetEvent(itemStack, offHandItem), { event ->
return InteractionResultHolder.fail(itemStack)
}, {
playAttachSound(user)
if (user.fishing != null) {
attemptReel(world, user, hand, itemStack)?.let { return it }
} else {
attemptCast(world, user, hand, itemStack)?.let { return it }
// if there is bait on the rod already then drop it on the ground before applying offhand bait
val baitStack = getBaitStackOnRod(itemStack)
if (baitStack != ItemStack.EMPTY && offHandItem.item != baitStack.item) {
user.drop(baitStack, true) // Drop the full stack
// apply single bait item from offhand
val singleBait = offHandItem.copy()
singleBait.count = 1
setBait(itemStack, singleBait)
offHandItem.shrink(1)
}
})
}
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
}
fun applyBait(
rodStack: ItemStack,
baitSource: ItemStack,
player: Player?
): Boolean {
if (baitSource.isEmpty || !SpawnBaitEffects.isFishingBait(baitSource)) return false
val existingBait = getBaitStackOnRod(rodStack)
if (!existingBait.isEmpty && existingBait.item == baitSource.item) return false
var applied = false
CobblemonEvents.BAIT_SET_PRE.postThen(
BaitSetEvent(rodStack, baitSource),
{ return false },
{
if (!existingBait.isEmpty && player != null) {
player.drop(existingBait, true)
}
val singleBait = baitSource.copy()
singleBait.count = 1
setBait(rodStack, singleBait)
baitSource.shrink(1)
applied = true
var i: Int
if (user.fishing != null) { // if the bobber is out yet
if (!world.isClientSide) {
CobblemonEvents.POKEROD_REEL.postThen(
PokerodReelEvent(user, itemStack),
{ event -> return InteractionResultHolder.fail(itemStack) },
{ event ->
i = user.fishing!!.retrieve(itemStack)
itemStack.hurtAndBreak(i, user, hand.toEquipmentSlot())
world.playSoundServer(
Vec3(user.x,
user.y,
user.z),
CobblemonSounds.FISHING_ROD_REEL_IN,
SoundSource.PLAYERS,
1.0f,
1.0f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
)
}
)
}
)
return applied
}
fun attemptApplyOffhandBait(
world: Level,
user: Player,
rodStack: ItemStack,
offHandItem: ItemStack
): InteractionResultHolder<ItemStack>? {
if (world.isClientSide) return null
if (user.fishing != null) return null
world.playSound(null as Player?, user.x, user.y, user.z, CobblemonSounds.FISHING_ROD_REEL_IN, SoundSource.PLAYERS, 1.0f, 1.0f)
user.gameEvent(GameEvent.ITEM_INTERACT_FINISH)
} else { // if the bobber is not out yet
val applied = applyBait(
rodStack = rodStack,
baitSource = offHandItem,
player = user
)
if (!world.isClientSide) {
val lureLevel = world.enchantmentRegistry.getHolder(Enchantments.LURE).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
val luckLevel = world.enchantmentRegistry.getHolder(Enchantments.LUCK_OF_THE_SEA).map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }.orElse(0)
if (applied) {
playAttachSound(user)
return InteractionResultHolder.sidedSuccess(rodStack, false)
val bobberEntity = PokeRodFishingBobberEntity(
user,
pokeRodId,
getBaitStackOnRod(itemStack),
world,
luckLevel,
lureLevel,
itemStack
)
CobblemonEvents.POKEROD_CAST_PRE.postThen(
PokerodCastEvent.Pre(itemStack, bobberEntity, getBaitStackOnRod(itemStack)),
{ event -> return InteractionResultHolder.fail(itemStack) },
{ event ->
world.addFreshEntity(bobberEntity)
var baitId = getBaitStackOnRod(itemStack).takeUnless { it.isEmpty }?.itemHolder?.unwrapKey()?.orElse(null)?.location() ?: cobblemonResource("empty_bait")
CobblemonCriteria.CAST_POKE_ROD.trigger(user as ServerPlayer, CastPokeRodContext(baitId))
CobblemonEvents.POKEROD_CAST_POST.post(
PokerodCastEvent.Post(itemStack, bobberEntity, getBaitStackOnRod(itemStack))
)
}
)
}
user.awardStat(Stats.ITEM_USED.get(this))
user.gameEvent(GameEvent.ITEM_INTERACT_START)
}
return null
}
fun attemptReel(
world: Level,
user: Player,
hand: InteractionHand,
itemStack: ItemStack
): InteractionResultHolder<ItemStack>? {
if (user.fishing == null) return null
if (!world.isClientSide) {
CobblemonEvents.POKEROD_REEL.postThen(
PokerodReelEvent(user, itemStack),
{ event -> return InteractionResultHolder.fail(itemStack) },
{ event ->
val i = user.fishing!!.retrieve(itemStack)
itemStack.hurtAndBreak(i, user, hand.toEquipmentSlot())
world.playSoundServer(
Vec3(user.x, user.y, user.z),
CobblemonSounds.FISHING_ROD_REEL_IN,
SoundSource.PLAYERS,
1.0f,
1.0f / (world.getRandom().nextFloat() * 0.4f + 0.8f)
)
}
)
}
world.playSound(
null as Player?,
user.x,
user.y,
user.z,
CobblemonSounds.FISHING_ROD_REEL_IN,
SoundSource.PLAYERS,
1.0f,
1.0f
)
user.gameEvent(GameEvent.ITEM_INTERACT_FINISH)
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
}
fun attemptCast(
world: Level,
user: Player,
hand: InteractionHand,
itemStack: ItemStack
): InteractionResultHolder<ItemStack>? {
if (user.fishing != null) return null
if (!world.isClientSide) {
val lureLevel = world.enchantmentRegistry.getHolder(Enchantments.LURE)
.map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }
.orElse(0)
val luckLevel = world.enchantmentRegistry.getHolder(Enchantments.LUCK_OF_THE_SEA)
.map { EnchantmentHelper.getItemEnchantmentLevel(it, itemStack) }
.orElse(0)
val bobberEntity = PokeRodFishingBobberEntity(
user,
pokeRodId,
getBaitStackOnRod(itemStack),
world,
luckLevel,
lureLevel,
itemStack
)
CobblemonEvents.POKEROD_CAST_PRE.postThen(
PokerodCastEvent.Pre(itemStack, bobberEntity, getBaitStackOnRod(itemStack)),
{ event -> return InteractionResultHolder.fail(itemStack) },
{ event ->
world.addFreshEntity(bobberEntity)
val baitId = getBaitStackOnRod(itemStack).takeUnless { it.isEmpty }
?.itemHolder?.unwrapKey()?.orElse(null)?.location()
?: cobblemonResource("empty_bait")
CobblemonCriteria.CAST_POKE_ROD.trigger(user as ServerPlayer, CastPokeRodContext(baitId))
CobblemonEvents.POKEROD_CAST_POST.post(
PokerodCastEvent.Post(itemStack, bobberEntity, getBaitStackOnRod(itemStack))
)
}
)
}
user.awardStat(Stats.ITEM_USED.get(this))
user.gameEvent(GameEvent.ITEM_INTERACT_START)
return InteractionResultHolder.sidedSuccess(itemStack, world.isClientSide)
}
@@ -23,6 +23,7 @@ import net.minecraft.world.level.Level
class PonigiriItem : Item(
Properties().stacksTo(64)
.food(FoodProperties.Builder()
.alwaysEdible()
.nutrition(2)
.saturationModifier(0.55f)
.build())
@@ -1,16 +0,0 @@
package com.cobblemon.mod.common.net.messages.server.pokeball
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class SendOutPokeBallPacket() : NetworkPacket<SendOutPokeBallPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
}
companion object {
val ID = cobblemonResource("send_out_pokeball")
fun decode(buffer: RegistryFriendlyByteBuf) = SendOutPokeBallPacket()
}
}
@@ -1,16 +0,0 @@
package com.cobblemon.mod.common.net.messages.server.pokerod
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class ApplyBaitPacket() : NetworkPacket<ApplyBaitPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
}
companion object {
val ID = cobblemonResource("apply_bait")
fun decode(buffer: RegistryFriendlyByteBuf) = ApplyBaitPacket()
}
}
@@ -1,17 +0,0 @@
package com.cobblemon.mod.common.net.messages.server.pokerod
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class CastPokeRodPacket(val mainHand: Boolean) : NetworkPacket<CastPokeRodPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeBoolean(mainHand)
}
companion object {
val ID = cobblemonResource("cast_pokerod")
fun decode(buffer: RegistryFriendlyByteBuf) = CastPokeRodPacket(buffer.readBoolean())
}
}
@@ -1,17 +0,0 @@
package com.cobblemon.mod.common.net.messages.server.pokerod
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class ReelPokeRodPacket(val mainHand: Boolean) : NetworkPacket<ReelPokeRodPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeBoolean(mainHand)
}
companion object {
val ID = cobblemonResource("reel_pokerod")
fun decode(buffer: RegistryFriendlyByteBuf) = ReelPokeRodPacket(buffer.readBoolean())
}
}
@@ -1,29 +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.serverhandling.pokeball
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
import com.cobblemon.mod.common.util.isServerSide
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
object SendOutPokeBallHandler : ServerNetworkPacketHandler<SendOutPokeBallPacket> {
override fun handle(packet: SendOutPokeBallPacket, server: MinecraftServer, player: ServerPlayer) {
(player.mainHandItem.item as? PokeBallItem)?.let { pokeball ->
if (player.level().isServerSide()) {
pokeball.throwPokeBall(player.level(), player)
}
// TODO: player.mainHandItem.consume(1, player)
}
}
}
@@ -1,41 +0,0 @@
package com.cobblemon.mod.common.net.serverhandling.pokerod
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.item.interactive.PokerodItem
import com.cobblemon.mod.common.net.messages.server.pokerod.ApplyBaitPacket
import com.cobblemon.mod.common.util.isServerSide
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
object ApplyBaitHandler : ServerNetworkPacketHandler<ApplyBaitPacket> {
override fun handle(packet: ApplyBaitPacket, server: MinecraftServer, player: ServerPlayer) {
val mainHandItem = player.getItemInHand(InteractionHand.MAIN_HAND)
val offHandItem = player.getItemInHand(InteractionHand.OFF_HAND)
println("[ApplyBaitHandler] Main hand: ${mainHandItem.item}")
println("[ApplyBaitHandler] Off hand: ${offHandItem.item}")
(mainHandItem.item as? PokerodItem)?.let { pokerod ->
if (player.level().isServerSide()) {
pokerod.applyBait(
mainHandItem,
offHandItem,
player
)
}
}
(offHandItem.item as? PokerodItem)?.let { pokerod ->
if (player.level().isServerSide()) {
pokerod.applyBait(
offHandItem,
mainHandItem,
player
)
}
}
}
}
@@ -1,35 +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.serverhandling.pokerod
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.item.interactive.PokerodItem
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
import com.cobblemon.mod.common.net.messages.server.pokerod.CastPokeRodPacket
import com.cobblemon.mod.common.util.isServerSide
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
object CastPokeRodHandler : ServerNetworkPacketHandler<CastPokeRodPacket> {
override fun handle(packet: CastPokeRodPacket, server: MinecraftServer, player: ServerPlayer) {
val hand = if (packet.mainHand) InteractionHand.MAIN_HAND else InteractionHand.OFF_HAND
(player.getItemInHand(hand).item as? PokerodItem)?.let { pokerod ->
if (player.level().isServerSide()) pokerod.attemptCast(
player.level(),
player,
hand,
player.getItemInHand(hand)
)
}
}
}
@@ -1,36 +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.serverhandling.pokerod
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.item.interactive.PokerodItem
import com.cobblemon.mod.common.net.messages.server.pokeball.SendOutPokeBallPacket
import com.cobblemon.mod.common.net.messages.server.pokerod.CastPokeRodPacket
import com.cobblemon.mod.common.net.messages.server.pokerod.ReelPokeRodPacket
import com.cobblemon.mod.common.util.isServerSide
import net.minecraft.server.MinecraftServer
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.InteractionHand
object ReelPokeRodHandler : ServerNetworkPacketHandler<ReelPokeRodPacket> {
override fun handle(packet: ReelPokeRodPacket, server: MinecraftServer, player: ServerPlayer) {
val hand = if (packet.mainHand) InteractionHand.MAIN_HAND else InteractionHand.OFF_HAND
(player.getItemInHand(hand).item as? PokerodItem)?.let { pokerod ->
if (player.level().isServerSide()) pokerod.attemptReel(
player.level(),
player,
hand,
player.getItemInHand(hand)
)
}
}
}
@@ -32,7 +32,6 @@ data class RenderEvent(
/** Represents when a layer is rendered by [LevelRenderer.renderLevel]. Ordinal corresponds with its render order. */
enum class Stage {
AFTER_ENTITIES,
TRANSLUCENT
}
}
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.util
import net.minecraft.core.BlockPos
import net.minecraft.world.phys.Vec3
import org.joml.Vector3f
import kotlin.math.sqrt
/**
* For conversion from Vec3dto BlockPos, loses accuracy
@@ -23,17 +22,9 @@ fun Vec3.toBlockPos(): BlockPos {
fun Vec3.toVec3f(): Vector3f = Vector3f(x.toFloat(), y.toFloat(), z.toFloat())
fun Vector3f.toVec3d(): Vec3 =
Vec3(x.toDouble(), y.toDouble(), z.toDouble())
fun Vector3f.set(vec3d: Vec3): Vector3f {
x = vec3d.x.toFloat()
y = vec3d.y.toFloat()
z = vec3d.z.toFloat()
return this
}
fun Vector3f.distance(other: Vector3f): Float {
val dx = other.x - x
val dy = other.y - y
val dz = other.z - z
return sqrt(dx * dx + dy * dy + dz * dz)
}
@@ -297,11 +297,6 @@
"1.0833": [0, 0, 0]
}
}
},
"sound_effects": {
"0.25": {
"effect": "pokemon.ditto.cry"
}
}
},
"animation.ditto.blink": {
@@ -3,7 +3,7 @@
"animations": {
"animation.metagross.ground_idle": {
"loop": true,
"animation_length": 0,
"animation_length": 11.4167,
"bones": {
"body2": {
"position": [0, -11.9, 0]
@@ -299,14 +299,6 @@
"rotation": [0, 0, 15]
}
}
},
"animation.eelektrik.cry": {
"animation_length": 1.25,
"sound_effects": {
"0.0417": {
"effect": "pokemon.eelektrik.cry"
}
}
}
}
}
@@ -869,14 +869,6 @@
"position": [-0.1, 0, 0]
}
}
},
"animation.eelektross.cry": {
"animation_length": 1.25,
"sound_effects": {
"0.0417": {
"effect": "pokemon.eelektross.cry"
}
}
}
}
}
@@ -84,7 +84,7 @@
"position": [0, "0+Math.cos((query.anim_time) * 90 * 8 - 60) * -0.1", 0]
},
"hair3": {
"rotation": ["-2+Math.cos((query.anim_time) * 90 * 8 - 100) * 3", 0, 0]
"rotation": ["0+Math.cos((query.anim_time) * 90 * 8 - 100) * 3", 0, 0]
},
"hair": {
"rotation": ["0+Math.cos((query.anim_time) * 90 * 8 - 120) * 10", 12.5, "0+Math.cos((query.anim_time) * 90 * 4 - 180) * 10"]
@@ -356,7 +356,7 @@
"position": [-1.63659, -1.07651, 3.16823]
},
"arm_right": {
"rotation": [-99.86576, -52.80463, 0.06108]
"rotation": [-80.89079, -82.69097, -6.55875]
},
"finger_right": {
"rotation": [0, 0, 17.5]
@@ -375,21 +375,6 @@
},
"arm_hammer_left": {
"rotation": [-85, 100, 0]
},
"hand_right": {
"rotation": [0, 0, -22.5]
},
"brow_right": {
"position": [0, -0.75, 0]
},
"brow_left": {
"position": [0, -0.75, 0]
},
"eyes_ditto": {
"position": [0, 0, 0.1]
},
"eyes_blink_ditto": {
"position": [0, 0, -0.1]
}
}
},
@@ -475,26 +460,40 @@
"1.875": [0, 0, 0]
}
},
"eyelid_right": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, 0, -0.125],
"0.625": [0, 0, -0.125],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, 0, -0.125],
"1.5833": [0, 0, -0.125],
"1.625": [0, 0, 0],
"1.7083": [0, 0, 0],
"1.75": [0, 0, -0.125]
}
},
"eyelid_left": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, 0, -0.1],
"0.625": [0, 0, -0.1],
"0.4167": [0, 0, -0.125],
"0.625": [0, 0, -0.125],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, 0, -0.1],
"1.5833": [0, 0, -0.1],
"1.625": [0, 0, 1],
"0.875": [0, 0, -0.125],
"1.5833": [0, 0, -0.125],
"1.625": [0, 0, 0],
"1.7083": [0, 0, 0],
"1.75": [0, 0, -0.1]
"1.75": [0, 0, -0.125]
}
},
"mouth_open_cry": {
"mouth_open": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.875": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"1.9167": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
"0.875": [0, 0, -0.125],
"1.875": [0, 0, -0.125],
"1.9167": [0, 0, 0]
}
},
"arm_left": {
@@ -557,6 +556,13 @@
"1.75": [0, 0, 0]
}
},
"eye_right": {
"scale": {
"1.5833": [1, 1, 1],
"1.625": [1.4, 1.4, 3.3],
"1.7083": [1, 1, 1]
}
},
"eye_left": {
"scale": {
"1.5833": [1, 1, 1],
@@ -716,55 +722,6 @@
"1.7083": [1, 1, 1]
}
},
"leg_left": {
"rotation": {
"0.0": [0, 0, 0],
"0.2917": [0, -20, -2.5],
"0.4167": [-5.68, -13.75, -2.5],
"0.5833": [-32.36, -7.5, -2.5],
"0.7083": [-40.5, 2.5, -2.5],
"0.75": [-33.83, 2.5, -2.5],
"0.8333": [-30.5, 2.5, -2.5]
},
"position": {
"0.4167": [0, 0, 0],
"0.5833": [0, 0, -0.75],
"1.5833": [0, 0, -0.75],
"1.625": [1.25, 0, -0.75],
"1.75": [0, 0, 0]
}
},
"arm_hammer_left": {
"rotation": {
"0.0": [0, 0, 17.5],
"0.25": [0, -25, 5],
"0.4167": [0, -32.5, 3.5],
"0.5": [-11.25, 40.75, -16.75],
"0.5833": [-22.5, 46.75, -37],
"0.7083": [-25, 44, -40.75]
}
},
"eye_right": {
"scale": {
"1.5833": [1, 1, 1],
"1.625": [1.4, 1.4, 3.3],
"1.7083": [1, 1, 1]
}
},
"eyelid_right": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, 0, -0.1],
"0.625": [0, 0, -0.1],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, 0, -0.1],
"1.5833": [0, 0, -0.1],
"1.625": [0, 0, 1],
"1.7083": [0, 0, 0],
"1.75": [0, 0, -0.1]
}
},
"arm_right": {
"rotation": {
"0.0": [0, 0, -20],
@@ -796,6 +753,24 @@
"finger_right3": {
"rotation": [0, 0, -22.5]
},
"leg_left": {
"rotation": {
"0.0": [0, 0, 0],
"0.2917": [0, -20, -2.5],
"0.4167": [-5.68, -13.75, -2.5],
"0.5833": [-32.36, -7.5, -2.5],
"0.7083": [-40.5, 2.5, -2.5],
"0.75": [-33.83, 2.5, -2.5],
"0.8333": [-30.5, 2.5, -2.5]
},
"position": {
"0.4167": [0, 0, 0],
"0.5833": [0, 0, -0.75],
"1.5833": [0, 0, -0.75],
"1.625": [1.25, 0, -0.75],
"1.75": [0, 0, 0]
}
},
"leg_right": {
"rotation": {
"0.0": [0, 0, 0],
@@ -814,146 +789,33 @@
"1.75": [-0.5, 0, 0]
}
},
"brow_left": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, -0.75, 0],
"0.625": [0, -0.75, 0],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, -0.75, 0],
"1.5833": [0, -0.75, 0],
"1.625": [0, 0, 0],
"1.7083": [0, 0, 0],
"1.75": [0, -0.75, 0]
}
},
"brow_right": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, -0.75, 0],
"0.625": [0, -0.75, 0],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, -0.75, 0],
"1.5833": [0, -0.75, 0],
"1.625": [0, 0, 0],
"1.7083": [0, 0, 0],
"1.75": [0, -0.75, 0]
}
},
"mouth_closed": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, -0.5, 0]},
"1.875": {"pre": [0, -0.5, 0], "post": [0, -0.5, 0]},
"1.9167": {"pre": [0, -0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_lip_top": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.875": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
"1.9167": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_ditto": {
"position": {
"0.375": [0, 0, 0],
"0.4167": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"0.625": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
"0.6667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]},
"0.8333": {"pre": [0, 0, 0], "post": [0, 0, 0]},
"0.875": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.5833": {"pre": [0, 0, 0.1], "post": [0, 0, 0]},
"1.75": {"pre": [0, 0, 0], "post": [0, 0, 0.1]}
},
"scale": {
"1.5833": [1, 1, 1],
"1.625": [1.4, 1.4, 3.3],
"1.7083": [1, 1, 1]
}
},
"eyes_blink_ditto": {
"position": {
"0.375": [0, 0, 0],
"0.4167": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"0.625": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"0.6667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]},
"0.8333": {"pre": [0, 0, 0], "post": [0, 0, 0]},
"0.875": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.5833": {"pre": [0, 0, -0.1], "post": [0, 0, 0]},
"1.75": {"pre": [0, 0, 0], "post": [0, 0, -0.1]}
}
},
"mouth_ditto": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.875": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
"1.9167": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_open_ditto": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.875": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"1.9167": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
"arm_hammer_left": {
"rotation": {
"0.0": [0, 0, 17.5],
"0.25": [0, -25, 5],
"0.4167": [0, -32.5, 3.5],
"0.5": [-11.25, 40.75, -16.75],
"0.5833": [-22.5, 46.75, -37],
"0.7083": [-25, 44, -40.75]
}
}
}
},
"animation.tinkatink.blink": {
"animation_length": 0.1667,
"animation_length": 0.16667,
"bones": {
"eyelid_right": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
"0.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
},
"brow_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"brow_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eye_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 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.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
}
}
}
@@ -961,6 +823,38 @@
"animation.tinkatink.cry": {
"animation_length": 1.5,
"bones": {
"neck": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": [10, 0, 0],
"1.25": [10, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, -2, 0],
"1.25": [0, -2, 0],
"1.5": [0, 0, 0]
}
},
"mouth2": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, -5, 0],
"1.25": [0, -5, 0],
"1.5": [0, 0, 0]
}
},
"jaw": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, -3, 0],
"1.25": [0, -3, 0],
"1.5": [0, 0, 0]
}
},
"head": {
"rotation": {
"0.0": [0, 0, 0],
@@ -969,12 +863,60 @@
"1.5": [0, 0, 0]
}
},
"mouth_open_cry": {
"head2": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": [-15, 0, 0],
"1.25": [-15, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth_closed2": {
"position": {
"0.25": [0, 0, -0.1],
"0.3333": [0, 0, 0],
"1.1667": [0, 0, 0],
"1.25": [0, 0, -0.1]
}
},
"mouth_open2": {
"position": {
"0.0": [0, 0, 0.1],
"0.25": [0, 0, 0],
"1.25": [0, 0, 0],
"1.5": [0, 0, 0.1]
}
},
"head3": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": [-15, 0, 0],
"1.25": [-15, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth_closed3": {
"position": {
"0.25": [0, 0, -0.1],
"0.3333": [0, 0, 0],
"1.1667": [0, 0, 0],
"1.25": [0, 0, -0.1]
}
},
"mouth_open3": {
"position": {
"0.0": [0, 0, 0.1],
"0.25": [0, 0, 0],
"1.25": [0, 0, 0],
"1.5": [0, 0, 0.1]
}
},
"mouth_open": {
"position": {
"0.0833": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.25": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
"0.1667": [0, 0, -0.15],
"1.25": [0, 0, -0.15],
"1.3333": [0, 0, 0]
}
},
"arm_left": {
@@ -1006,38 +948,10 @@
"1.25": [0, 0, -2.4],
"1.5": [0, 0, 0]
}
},
"mouth_closed": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, -0.5, 0]},
"1.3333": {"pre": [0, -0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_lip_top": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.3333": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.3333": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
},
"sound_effects": {
"0.0": {
"0.25": {
"effect": "pokemon.tinkatink.cry"
}
}
@@ -1148,128 +1062,6 @@
"rotation": [0, 0, 32.5]
}
}
},
"animation.tinkatink.ditto_face": {
"loop": true,
"bones": {
"face": {
"position": [0, 0, 0.1],
"scale": 0
},
"face_ditto": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatink.happy": {
"loop": true,
"bones": {
"brow_left": {
"position": [0, 0, 0.1]
},
"brow_right": {
"position": [0, 0, 0.1]
},
"eye_left": {
"position": [0, 0, 0.1]
},
"eye_right": {
"position": [0, 0, 0.1]
},
"mouth_closed": {
"position": [0, 0, 0.1]
},
"mouth_lip_top": {
"position": [0, 0, 0.1]
},
"mouth_open_happy": {
"position": [0, 0, -0.1]
},
"eyelid_happy_left": {
"position": [0, 0, -0.1]
},
"eyelid_happy_right": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatink.angry": {
"loop": true,
"bones": {
"eye_emote_left": {
"scale": [1, 0.5, 1]
},
"eye_emote_right": {
"scale": [1, 0.5, 1]
},
"eye_emote_left2": {
"position": [0.25, 0, 0],
"scale": [0.5, 1, 1]
},
"eye_emote_right2": {
"position": [-0.25, 0, 0],
"scale": [0.5, 1, 1]
}
}
},
"animation.tinkatink.very_sad": {
"loop": true,
"bones": {
"eye_emote_left": {
"scale": [1, 0.5, 1]
},
"eye_emote_right": {
"scale": [1, 0.5, 1]
},
"eye_emote_left2": {
"position": [-0.25, 0, 0],
"scale": [0.5, 1, 1]
},
"eye_emote_right2": {
"position": [0.25, 0, 0],
"scale": [0.5, 1, 1]
}
}
},
"animation.tinkatink.hurt": {
"loop": true,
"bones": {
"brow_left": {
"position": [0, 0, 0.1]
},
"brow_right": {
"position": [0, 0, 0.1]
},
"eye_left": {
"position": [0, 0, 0.1]
},
"eye_right": {
"position": [0, 0, 0.1]
},
"eyelid_hurt_left": {
"position": [0, 0, -0.1]
},
"eyelid_hurt_right": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatink.disinterested": {
"loop": true,
"bones": {
"eye_emote_left": {
"scale": [1, 0.5, 1]
},
"eye_emote_right": {
"scale": [1, 0.5, 1]
},
"eye_emote_left2": {
"position": [0, 0, 0.1]
},
"eye_emote_right2": {
"position": [0, 0, 0.1]
}
}
}
}
}
@@ -4,6 +4,12 @@
"animation.tinkatuff.ground_idle": {
"loop": true,
"bones": {
"tail": {
"rotation": [12.5, 0, 0]
},
"tail2": {
"rotation": [12.5, 0, 0]
},
"arm_right": {
"rotation": [55.98303, 0.22836, "-40.7651+Math.cos((query.anim_time) * 90 * 2 - 120) * 1"],
"position": [-0.25, -0.5, 0]
@@ -15,8 +21,7 @@
"rotation": [0, 0, -5]
},
"finger_right2": {
"rotation": [0, -17.5, 37.5],
"position": [-0.25, 0, 0]
"rotation": [0, -10, 37.5]
},
"arm_left": {
"rotation": [-84.39003, 4.58778, "53.5046+Math.cos((query.anim_time) * 90 * 2 - 120) * 1"]
@@ -25,11 +30,17 @@
"rotation": [0, -15, 55]
},
"finger_left": {
"rotation": [0, 0, -40]
"rotation": [0, 0, -25]
},
"finger_left2": {
"rotation": [20, 0, 0]
},
"hand_left": {
"rotation": [0, 17.5, 0]
},
"hand_right": {
"rotation": [0, -17.5, 0]
},
"leg_left": {
"rotation": [0, -12.5, -5]
},
@@ -37,7 +48,7 @@
"rotation": [0, 12.5, 5]
},
"finger_left3": {
"rotation": [0, 0, 67.5]
"rotation": [0, 0, 57.5]
},
"finger_right3": {
"rotation": [0, 0, -20]
@@ -67,6 +78,9 @@
"head": {
"rotation": ["12.5+Math.cos((query.anim_time) * 90 * 2 - 50) * 2", 0, 0]
},
"mouth_closed": {
"position": [0, 0, 0]
},
"ponytail": {
"rotation": ["0+Math.cos((query.anim_time) * 90 * 2 - 120) * 1", 0, 0]
},
@@ -173,24 +187,10 @@
}
},
"finger_right2": {
"rotation": [7.5, 0, 42.5],
"position": [-0.25, 0.25, 0]
"rotation": [7.5, 0, 10]
},
"finger_right3": {
"rotation": [-0.88045, -9.96156, 5.07673]
},
"finger_left": {
"rotation": [0, 0, -55],
"position": [0, 0.5, 0]
},
"finger_left2": {
"rotation": [0, 0, -17.5]
},
"finger_left3": {
"rotation": [0, 0, 22.5]
},
"finger_right": {
"rotation": [0, 0, 20]
}
}
},
@@ -210,7 +210,7 @@
"rotation": [-15, -2.5, 62.5]
},
"finger_left3": {
"rotation": [0, 0, 22.5]
"rotation": [0, 0, 52.5]
},
"arm_right": {
"rotation": [22.5, -10, -35],
@@ -299,29 +299,18 @@
},
"arm_hammer_right2": {
"rotation": [0, -70, 0]
},
"finger_left": {
"rotation": [0, 0, -52.5],
"position": [0, 0.75, 0]
},
"finger_left2": {
"rotation": [0, 0, -15]
},
"finger_right": {
"rotation": [0, 0, 20]
},
"finger_right2": {
"rotation": [7.5, 0, 37.5],
"position": [-0.25, 0.25, 0]
},
"finger_right3": {
"rotation": [0, 0, -32.5]
}
}
},
"animation.tinkatuff.battle_idle": {
"loop": true,
"bones": {
"tail": {
"rotation": [12.5, 0, 0]
},
"tail2": {
"rotation": [12.5, 0, 0]
},
"arm_right": {
"rotation": [40.98303, 0.22836, "-45.7651+Math.cos((query.anim_time) * 90 * 2 - 40) * 2"]
},
@@ -329,8 +318,7 @@
"rotation": [0, -52.5, 0]
},
"finger_right": {
"rotation": [0, 0, 37.5],
"position": [0, 0.25, 0]
"rotation": [0, 0, -5]
},
"finger_right2": {
"rotation": [0, 0, 37.5]
@@ -342,12 +330,17 @@
"rotation": [0, 0, "55+Math.cos((query.anim_time) * 90 * 2 - 40) * -2"]
},
"finger_left": {
"rotation": [0, 0, -47.5],
"position": [0, 0.5, 0]
"rotation": [0, 0, -25]
},
"finger_left2": {
"rotation": [20, 0, 0]
},
"hand_left": {
"rotation": [0, 17.5, 0]
},
"hand_right": {
"rotation": [0, -17.5, 0]
},
"leg_left": {
"rotation": ["-11.2025+Math.cos((query.anim_time) * 90 * 2) * 3", -21.49336, -9.33448]
},
@@ -355,11 +348,10 @@
"rotation": ["-13.5954+Math.cos((query.anim_time) * 90 * 2) * 3", 22.38126, 10.45107]
},
"finger_left3": {
"rotation": [0, 0, 42.5],
"position": [-0.5, -0.25, 0]
"rotation": [0, 0, 57.5]
},
"finger_right3": {
"rotation": [0, 0, -40]
"rotation": [0, 0, -20]
},
"hammer": {
"rotation": [-12.18122, -2.58318, 113.79667]
@@ -424,8 +416,7 @@
"position": [-0.5, 0, 0]
},
"hammer": {
"rotation": [15, 0, 0],
"position": [0, 0.5, 3.75]
"rotation": [15, 0, 0]
},
"hammer2": {
"rotation": ["90+Math.cos((query.anim_time) * 90 * 1) * -1", 0, 0],
@@ -465,18 +456,43 @@
},
"leg_right": {
"rotation": [-90, 20, 0]
},
"eyes_ditto": {
"position": [0, 0, 0.1]
},
"eyes_blink_ditto": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatuff.faint": {
"animation_length": 3,
"bones": {
"arm_right": {
"rotation": {
"0.0": [40.98303, 0.22836, -45.7651],
"0.2083": [5.98, 0.23, -45.77],
"0.2917": [35.98, 0.23, -45.77],
"0.75": [18.48, 5.23, -23.27],
"0.9167": [60.98, -12.27, -35.77],
"1.2083": [30.98, -59.77, -35.77],
"1.3333": [32.05, -62.98, -35.77],
"1.5": [33.48, -67.27, -35.77],
"1.8333": [15.98, -79.77, -35.77],
"1.9167": [67.65, -129.77, -110.77],
"1.9583": [93.48, -154.77, -148.27],
"2.0833": [93.48, -174.77, -168.27],
"2.3333": [93.48, -169.77, -168.27]
}
},
"arm_right2": {
"rotation": {
"0.0": [0, -52.5, 0],
"1.0": [0, -52.5, 0],
"1.2083": [0, -57.5, 0],
"1.5": [0, -30, 0]
}
},
"finger_right": {
"rotation": [0, 0, -5]
},
"finger_right2": {
"rotation": [0, 0, 37.5]
},
"arm_left": {
"rotation": {
"0.0": [-84.39003, 24.58778, 53.5046],
@@ -531,9 +547,30 @@
"2.375": [-30.37, 0, -5]
}
},
"leg_right": {
"rotation": {
"0.0": [-13.6, 22.38, 10.45],
"0.1667": [-31.1, 22.38, 10.45],
"0.25": [-26.1, 22.38, 10.45],
"0.5": [-3.6, 22.38, 10.45],
"0.7917": [6.4, 22.38, 10.45],
"0.9167": [-31.1, 22.38, 10.45],
"1.2083": [-31.1, 42.38, 10.45],
"1.375": [-30, 0, 0],
"1.6667": [-30, 0, 5],
"1.875": [70, 0, 5],
"2.0417": [40.36, 0, 5],
"2.1667": [-30, 0, 5],
"2.25": [-45, 0, 5],
"2.375": [-35, 0, 5]
}
},
"finger_left3": {
"rotation": [0, 0, 57.5]
},
"finger_right3": {
"rotation": [0, 0, -20]
},
"hammer": {
"rotation": {
"0.0": [-0.78, -6.26, 38.97],
@@ -556,6 +593,9 @@
"skirt_left": {
"rotation": [0, 0, -15]
},
"skirt_right": {
"rotation": [-10, 0, 15]
},
"leg_left2": {
"rotation": {
"0.0": [20, 0, 0],
@@ -571,6 +611,18 @@
"2.0417": [15, 0, 0]
}
},
"leg_right2": {
"rotation": {
"0.0": [15, 0, -10],
"0.1667": [35, 0, -10],
"0.25": [-10, 0, -10],
"0.5": [27.5, 0, 5],
"0.7917": [5, 0, 5],
"0.9167": [35, 0, 5],
"1.375": [35, 0, 0],
"1.6667": [22.5, 0, 0]
}
},
"body": {
"rotation": {
"0.9167": [0, 0, 0],
@@ -799,517 +851,132 @@
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.4167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"1.7917": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
}
}
},
"mouth_top": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0.5, 0]
},
"0.9167": {
"pre": [0, 0.5, 0],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0.5, 0]
},
"2.0417": {
"pre": [0, 0.5, 0],
"post": [0, 0, 0]
}
"0.2083": [0, 0, 0],
"0.25": [0, 0, -0.15],
"0.375": [0, 0, -0.15],
"0.4167": [0, 0, 0],
"0.9167": [0, 0, 0],
"0.9583": [0, 0, -0.15],
"1.75": [0, 0, -0.15],
"1.7917": [0, 0, 0],
"2.0": [0, 0, 0],
"2.0417": [0, 0, -0.15]
}
},
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.4167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"1.7917": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
}
"0.2083": [0, 0, 0],
"0.25": [0, 0, -0.15],
"0.375": [0, 0, -0.15],
"0.4167": [0, 0, 0],
"0.9167": [0, 0, 0],
"0.9583": [0, 0, -0.15],
"1.75": [0, 0, -0.15],
"1.7917": [0, 0, 0],
"2.0": [0, 0, 0],
"2.0417": [0, 0, -0.15]
}
},
"mouth_open": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.9167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"2.0417": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
"0.2083": [0, 0, 0],
"0.25": [0, 0, -0.15],
"0.875": [0, 0, -0.15],
"0.9167": [0, 0, 0],
"1.25": [0, 0, 0],
"1.2917": [0, 0, -0.15],
"2.0": [0, 0, -0.15],
"2.0417": [0, 0, 0]
}
},
"arm_right": {
"rotation": {
"0.0": [40.98303, 0.22836, -45.7651],
"0.2083": [5.98, 0.23, -45.77],
"0.2917": [35.98, 0.23, -45.77],
"0.75": [18.48, 5.23, -23.27],
"0.9167": [60.98, -12.27, -35.77],
"1.2083": [30.98, -59.77, -35.77],
"1.3333": [32.05, -62.98, -35.77],
"1.5": [33.48, -67.27, -35.77],
"1.8333": [15.98, -79.77, -35.77],
"1.9167": [67.65, -129.77, -110.77],
"1.9583": [93.48, -154.77, -148.27],
"2.0833": [93.48, -174.77, -168.27],
"2.3333": [93.48, -169.77, -168.27]
}
},
"arm_right2": {
"rotation": {
"0.0": [0, -52.5, 0],
"1.0": [0, -52.5, 0],
"1.2083": [0, -57.5, 0],
"1.5": [0, -30, 0]
}
},
"finger_right": {
"rotation": [0, 0, -5]
},
"finger_right2": {
"rotation": [0, 0, 37.5]
},
"finger_right3": {
"rotation": [0, 0, -20]
},
"skirt_right": {
"rotation": [-10, 0, 15]
},
"leg_right": {
"rotation": {
"0.0": [-13.6, 22.38, 10.45],
"0.1667": [-31.1, 22.38, 10.45],
"0.25": [-26.1, 22.38, 10.45],
"0.5": [-3.6, 22.38, 10.45],
"0.7917": [6.4, 22.38, 10.45],
"0.9167": [-31.1, 22.38, 10.45],
"1.2083": [-31.1, 42.38, 10.45],
"1.375": [-30, 0, 0],
"1.6667": [-30, 0, 5],
"1.875": [70, 0, 5],
"2.0417": [40.36, 0, 5],
"2.1667": [-30, 0, 5],
"2.25": [-45, 0, 5],
"2.375": [-35, 0, 5]
}
},
"leg_right2": {
"rotation": {
"0.0": [15, 0, -10],
"0.1667": [35, 0, -10],
"0.25": [-10, 0, -10],
"0.5": [27.5, 0, 5],
"0.7917": [5, 0, 5],
"0.9167": [35, 0, 5],
"1.375": [35, 0, 0],
"1.6667": [22.5, 0, 0]
}
},
"brow_left": {
"mouth_closed": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
"0.2083": [0, 0, 0],
"0.25": [0, 0, 0.1],
"0.875": [0, 0, 0.1],
"0.9167": [0, 0, 0],
"1.25": [0, 0, 0],
"1.2917": [0, 0, 0.1],
"2.0": [0, 0, 0.1],
"2.0417": [0, 0, 0]
}
},
"brow_right": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"mouth_bottom": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, -0.5, 0]
},
"0.9167": {
"pre": [0, -0.5, 0],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, -0.5, 0]
},
"2.0417": {
"pre": [0, -0.5, 0],
"post": [0, 0, 0]
}
}
},
"eye_emote_left": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"eye_emote_right": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"eyes_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"eyes_blink_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.4167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"1.7917": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.9167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"2.0417": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.9167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"2.0417": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
}
}
},
"animation.tinkatuff.cry": {
"animation_length": 1.5,
"bones": {
"head": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": [-15, 0, 0],
"1.25": [-15, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth_open": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
},
"mouth_top": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0.5, 0]},
"1.3333": {"pre": [0, 0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_bottom": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, -0.5, 0]},
"1.3333": {"pre": [0, -0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.3333": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
},
"sound_effects": {
"0.0": {
"effect": "pokemon.tinkatuff.cry"
}
}
},
"animation.tinkatuff.blink": {
"animation_length": 0.1667,
"animation_length": 0.16667,
"bones": {
"eyelid_right": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
"0.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"brow_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"brow_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"eye_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 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.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
}
}
}
},
"animation.tinkatuff.ditto_face": {
"loop": true,
"animation.tinkatuff.cry": {
"animation_length": 0.91667,
"bones": {
"face": {
"position": [0, 0, 0.1],
"scale": 0
"head": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [-15, 0, 0],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [-15, 0, 0],
"lerp_mode": "catmullrom"
},
"0.9167": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"face_ditto": {
"position": [0, 0, -0.1]
"mouth_closed": {
"position": {
"0.25": [0, 0, 0],
"0.3333": [0, 0, 0.1],
"0.5833": [0, 0, 0.1],
"0.6667": [0, 0, 0]
}
},
"mouth_open": {
"position": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [0, 0, -0.1],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [0, 0, -0.1],
"lerp_mode": "catmullrom"
},
"0.9167": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
}
},
"sound_effects": {
"0.1667": {
"effect": "pokemon.tinkatuff.cry"
}
}
}
@@ -90,7 +90,7 @@
"parent": "chest",
"pivot": [0, 17, -5],
"cubes": [
{"origin": [-2.25, 16, -7.5], "size": [5, 5, 5], "uv": [22, 0]},
{"origin": [-2.75, 16, -7.5], "size": [5.5, 5, 5], "uv": [22, 0]},
{"origin": [0, 18, -2.5], "size": [0, 4, 2], "uv": [30, 37]}
]
},
@@ -486,7 +486,7 @@
"parent": "eye_left",
"pivot": [4.2, 34.1, -10.53],
"cubes": [
{"origin": [4.98, 34.01, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [132, 116]}
{"origin": [4.98, 33.99, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [132, 116]}
]
},
{
@@ -782,7 +782,7 @@
"parent": "eye_right",
"pivot": [-4.2, 34.1, -10.53],
"cubes": [
{"origin": [-7.98, 34.01, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [140, 116]}
{"origin": [-7.98, 33.99, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [140, 116]}
]
},
{
@@ -15,58 +15,18 @@
"name": "tinkatink",
"pivot": [0, 0, 0]
},
{
"name": "locator_root",
"parent": "tinkatink",
"pivot": [0, 0, 0],
"locators": {
"root": [0, 0, 0]
}
},
{
"name": "locator_top",
"parent": "tinkatink",
"pivot": [0, 14, 0],
"locators": {
"top": [0, 14, 0]
}
},
{
"name": "locator_special",
"parent": "tinkatink",
"pivot": [0, 6, -7],
"locators": {
"special": [0, 6, -7]
}
},
{
"name": "body",
"parent": "tinkatink",
"pivot": [0, 3.75, 0]
},
{
"name": "locator_target",
"parent": "body",
"pivot": [0, 6, -6],
"locators": {
"target": [0, 6, -6]
}
},
{
"name": "locator_middle",
"parent": "body",
"pivot": [0, 6, 0],
"locators": {
"middle": [0, 6, 0]
}
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 2.5, -0.25],
"pivot": [0, 1.75, -0.25],
"cubes": [
{"origin": [-1.5, 2, -1.5], "size": [3, 3, 3], "uv": [30, 6]},
{"origin": [-1, 1.5, -2.5], "size": [2, 2, 1], "pivot": [0, 2.5, -2], "rotation": [0, 0, 45], "uv": [47, 12]}
{"origin": [-2, 1.5, -2], "size": [4, 3, 4], "uv": [0, 12]},
{"origin": [-1, 2, -2.75], "size": [2, 2, 1], "pivot": [0, 3, -2.25], "rotation": [0, 0, 45], "uv": [12, 12]}
]
},
{
@@ -74,509 +34,199 @@
"parent": "torso",
"pivot": [0, 4.25, -0.25],
"cubes": [
{"origin": [-4, 4.25, -3.75], "size": [8, 7, 7], "uv": [0, 0]}
]
},
{
"name": "locator_item_hat",
"parent": "head",
"pivot": [0, 12.25, -0.25],
"locators": {
"item_hat": [0, 12.25, -0.25]
}
},
{
"name": "locator_head",
"parent": "head",
"pivot": [0, 11.25, -3.25],
"locators": {
"head": [0, 11.25, -3.25]
}
},
{
"name": "locator_mouth",
"parent": "head",
"pivot": [0, 5.7, -3.75],
"locators": {
"mouth": [0, 5.7, -3.75]
}
},
{
"name": "locator_item_face",
"parent": "head",
"pivot": [0, 8.25, -3.75],
"locators": {
"item_face": [0, 8.25, -3.75]
}
},
{
"name": "locator_face",
"parent": "head",
"pivot": [0, 7.25, -3.75],
"locators": {
"face": [0, 7.25, -3.75]
}
},
{
"name": "face_ditto",
"parent": "head",
"pivot": [0, 7, -3.65]
},
{
"name": "eyes_ditto",
"parent": "face_ditto",
"pivot": [0, 7.75, -3.67],
"cubes": [
{"origin": [-3, 7.25, -3.67], "size": [6, 1, 0], "uv": [51, 23]}
]
},
{
"name": "eyes_blink_ditto",
"parent": "face_ditto",
"pivot": [0, 7.75, -3.57],
"cubes": [
{"origin": [-3.5, 7.25, -3.57], "size": [7, 1, 0], "uv": [49, 27]},
{"origin": [-3, 7.75, -3.58], "size": [6, 1, 0], "uv": [51, 21]}
]
},
{
"name": "mouth_ditto",
"parent": "face_ditto",
"pivot": [0, 6, -3.65],
"cubes": [
{"origin": [-2.5, 5.25, -3.66], "size": [5, 1, 0], "uv": [53, 19]},
{"origin": [-3.5, 5.75, -3.66], "size": [7, 1, 0], "uv": [49, 25]}
]
},
{
"name": "mouth_open_ditto",
"parent": "face_ditto",
"pivot": [0, 5.75, -3.56],
"cubes": [
{"origin": [-3.5, 4.75, -3.56], "size": [7, 2, 0], "uv": [49, 29]}
]
},
{
"name": "face",
"parent": "head",
"pivot": [0, 6.75, -3.75]
},
{
"name": "eyes",
"parent": "face",
"pivot": [0, 6.75, -3.26]
},
{
"name": "brow_left",
"parent": "eyes",
"pivot": [2.25, 8.5, -3.25],
"cubes": [
{"origin": [1.75, 8, -3.75], "size": [1, 1, 1], "inflate": 0.01, "pivot": [2.25, 8.5, -3.25], "rotation": [0, 0, 5], "uv": [32, 29]}
]
},
{
"name": "brow_right",
"parent": "eyes",
"pivot": [-2.25, 8.5, -3.25],
"cubes": [
{"origin": [-2.75, 8, -3.75], "size": [1, 1, 1], "inflate": 0.01, "pivot": [-2.25, 8.5, -3.25], "rotation": [0, 0, -5], "uv": [32, 25]}
]
},
{
"name": "eye_left",
"parent": "eyes",
"pivot": [2.5, 7.75, -3.26],
"cubes": [
{"origin": [2, 6.75, -3.75], "size": [1, 1, 1], "inflate": 0.01, "uv": [28, 29]}
]
},
{
"name": "locator_eye_left",
"parent": "eye_left",
"pivot": [2.5, 7.7, -3.75],
"locators": {
"eye2": [2.5, 7.7, -3.75]
}
},
{
"name": "eye_emote_left",
"parent": "eye_left",
"pivot": [2.5, 7.75, -3.75],
"cubes": [
{"origin": [2, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.025, "uv": [24, 29]}
]
},
{
"name": "eye_emote_left2",
"parent": "eye_left",
"pivot": [2.5, 7.75, -3.75],
"cubes": [
{"origin": [2, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.02, "uv": [20, 29]}
]
},
{
"name": "eye_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.26],
"cubes": [
{"origin": [-3, 6.75, -3.75], "size": [1, 1, 1], "inflate": 0.01, "uv": [28, 25]}
]
},
{
"name": "locator_eye_right",
"parent": "eye_right",
"pivot": [-2.5, 7.7, -3.75],
"locators": {
"eye1": [-2.5, 7.7, -3.75]
}
},
{
"name": "eye_emote_right",
"parent": "eye_right",
"pivot": [-2.5, 7.75, -3.75],
"cubes": [
{"origin": [-3, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.025, "uv": [24, 25]}
]
},
{
"name": "eye_emote_right2",
"parent": "eye_right",
"pivot": [-2.5, 7.75, -3.75],
"cubes": [
{"origin": [-3, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.02, "uv": [20, 25]}
]
},
{
"name": "eyelid_left",
"parent": "eyes",
"pivot": [2.5, 7.75, -3.16],
"cubes": [
{"origin": [1.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [0, 28]}
]
},
{
"name": "eyelid_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.16],
"cubes": [
{"origin": [-3.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [0, 24]}
]
},
{
"name": "eyelid_happy_left",
"parent": "eyes",
"pivot": [2.5, 7.75, -3.16],
"cubes": [
{"origin": [1, 6.75, -3.66], "size": [3, 2, 1], "uv": [12, 28]}
]
},
{
"name": "eyelid_happy_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.16],
"cubes": [
{"origin": [-4, 6.75, -3.66], "size": [3, 2, 1], "uv": [12, 24]}
]
},
{
"name": "eyelid_hurt_left",
"parent": "eyes",
"pivot": [2.5, 7.75, -3.16],
"cubes": [
{"origin": [1.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [6, 28]}
]
},
{
"name": "eyelid_hurt_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.16],
"cubes": [
{"origin": [-3.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [6, 24]}
]
},
{
"name": "mouths",
"parent": "face",
"pivot": [0, 4.25, -0.75]
},
{
"name": "mouth_closed",
"parent": "mouths",
"pivot": [0, 5.75, -3.25],
"cubes": [
{"origin": [-1.5, 4.75, -3.76], "size": [3, 1, 1], "inflate": 0.02, "uv": [38, 13]},
{"origin": [-0.5, 5.25, -3.76], "size": [1, 1, 1], "inflate": 0.04, "uv": [46, 16]}
]
},
{
"name": "mouth_lip_top",
"parent": "mouth_closed",
"pivot": [0, 6.25, -3.25],
"cubes": [
{"origin": [-1, 5.75, -3.77], "size": [2, 1, 1], "uv": [39, 16]},
{"origin": [-2, 5.25, -3.76], "size": [4, 1, 1], "uv": [29, 22]}
]
},
{
"name": "mouth_open_cry",
"parent": "mouths",
"pivot": [0.4, 4.25, -1.75],
"cubes": [
{"origin": [-2, 4.75, -3.65], "size": [4, 2, 1], "inflate": 0.01, "uv": [29, 19]}
]
},
{
"name": "mouth_open_happy",
"parent": "mouths",
"pivot": [0.4, 4.25, -1.75],
"cubes": [
{"origin": [-2, 4.75, -3.65], "size": [4, 2, 1], "inflate": 0.01, "uv": [40, 19]},
{"origin": [-1.5, 4.75, -3.65], "size": [3, 1, 1], "inflate": 0.02, "uv": [40, 22]},
{"origin": [-0.5, 5.4, -3.65], "size": [1, 1, 1], "inflate": 0.03, "uv": [42, 7]}
]
},
{
"name": "hair_main",
"parent": "head",
"pivot": [0, 10.75, -0.75]
},
{
"name": "hair",
"parent": "hair_main",
"pivot": [0, 10.75, -0.75],
"rotation": [12.5, 0, 0],
"cubes": [
{"origin": [-0.5, 10.25, -1.75], "size": [1, 2, 1], "uv": [25, 15]}
]
},
{
"name": "hair2",
"parent": "hair",
"pivot": [1, 12.25, -0.75],
"rotation": [35, 0, 0],
"cubes": [
{"origin": [-1, 12.25, -2.25], "size": [2, 3, 2], "inflate": 0.01, "uv": [30, 13]}
{"origin": [-3.5, 4.25, -3.25], "size": [7, 6, 6], "uv": [0, 0]}
]
},
{
"name": "hair3",
"parent": "hair_main",
"pivot": [0, 11.25, -0.75],
"rotation": [-2.5, 0, 0],
"parent": "head",
"pivot": [0, 10.25, -0.25],
"rotation": [-5, 0, 0],
"cubes": [
{"origin": [-2.5, 11.25, -3.75], "size": [5, 0, 3], "uv": [34, 25]}
{"origin": [-2.5, 10.25, -3.25], "size": [5, 0, 3], "uv": [11, 21]}
]
},
{
"name": "hair4",
"parent": "hair3",
"pivot": [0, 11.25, -3.75],
"rotation": [-7.5, 0, 0],
"pivot": [0, 10.25, -3.25],
"rotation": [-15, 0, 0],
"cubes": [
{"origin": [-3, 9.25, -3.75], "size": [6, 2, 0], "uv": [36, 29]},
{"origin": [-0.5, 9.25, -3.75], "size": [1, 2, 0], "inflate": 0.01, "uv": [43, 10]}
{"origin": [-2.5, 8.25, -3.25], "size": [5, 2, 0], "uv": [43, 0]}
]
},
{
"name": "arms",
"parent": "torso",
"pivot": [0, 3.25, 0]
},
{
"name": "arm_left",
"parent": "arms",
"pivot": [1.5, 3.25, 0],
"name": "eye_right",
"parent": "head",
"pivot": [-2.75, 6.5, -2.76],
"rotation": [0, 0, -5],
"cubes": [
{"origin": [1.25, 2.25, -1], "size": [2, 2, 2], "uv": [8, 19]}
{"origin": [-2.75, 6, -3.26], "size": [1, 2, 1], "uv": [51, 2]}
]
},
{
"name": "hand_left",
"parent": "arm_left",
"pivot": [3.25, 3.25, 0],
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-0.5, 3.5, -0.15],
"cubes": [
{"origin": [3.25, 2.25, -1.5], "size": [3, 2, 3], "inflate": 0.25, "uv": [12, 14]}
{"origin": [-2.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [47, 2]}
]
},
{
"name": "locator_hand_secondary",
"parent": "hand_left",
"pivot": [6, 3.25, 0],
"rotation": [0, -90, 0],
"locators": {
"hand_secondary": [6, 3.25, 0]
}
},
{
"name": "fingers_left",
"parent": "hand_left",
"pivot": [6.5, 3.85, 0]
},
{
"name": "finger_left",
"parent": "fingers_left",
"pivot": [6.5, 3.85, 0],
"name": "eye_left",
"parent": "head",
"pivot": [2.75, 6.5, -2.76],
"rotation": [0, 0, 5],
"cubes": [
{"origin": [6.5, 2.85, -0.5], "size": [1, 1, 1], "inflate": 0.1, "uv": [20, 21]}
{"origin": [1.75, 6, -3.26], "size": [1, 2, 1], "uv": [26, 7]}
]
},
{
"name": "finger_left2",
"parent": "fingers_left",
"pivot": [6.5, 3.85, -0.6],
"rotation": [0, 17.5, 0],
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [0.5, 3.5, -0.15],
"cubes": [
{"origin": [6.5, 2.85, -1.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [16, 21]}
{"origin": [1.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [32, 8]}
]
},
{
"name": "finger_left3",
"parent": "fingers_left",
"pivot": [6.5, 3.85, 0.6],
"rotation": [0, -17.5, 0],
"name": "hair",
"parent": "head",
"pivot": [0, 10.25, 0.25],
"rotation": [12.5, 0, 0],
"cubes": [
{"origin": [6.5, 2.85, 0.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [24, 21]}
{"origin": [0, 9.75, -0.75], "size": [0, 2, 1], "uv": [4, 0]}
]
},
{
"name": "arm_right",
"parent": "arms",
"pivot": [-1.5, 3.25, 0],
"name": "hair2",
"parent": "hair",
"pivot": [0, 11.75, 0.25],
"rotation": [22.5, 0, 0],
"cubes": [
{"origin": [-3.25, 2.25, -1], "size": [2, 2, 2], "uv": [0, 19]}
{"origin": [0, 11.75, -1.75], "size": [0, 3, 2], "inflate": 0.01, "uv": [0, 10]}
]
},
{
"name": "hand_right",
"parent": "arm_right",
"pivot": [-3.25, 3.25, 0],
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 4.25, -0.25],
"cubes": [
{"origin": [-6.25, 2.25, -1.5], "size": [3, 2, 3], "inflate": 0.25, "uv": [0, 14]}
{"origin": [-2.5, 4.75, -3.2575], "size": [5, 2, 0], "inflate": 0.001, "uv": [26, 5]}
]
},
{
"name": "locator_hand_primary",
"parent": "hand_right",
"pivot": [-6, 3.25, 0],
"rotation": [0, 90, 0],
"locators": {
"hand_primary": [-6, 3.25, 0]
}
},
{
"name": "locator_item",
"parent": "hand_right",
"pivot": [-6, 2.25, 0],
"locators": {
"item": [-6, 2.25, 0]
}
},
{
"name": "fingers_right",
"parent": "hand_right",
"pivot": [-6.5, 3.85, 0]
},
{
"name": "finger_right",
"parent": "fingers_right",
"pivot": [-6.5, 3.85, 0],
"name": "mouth_open",
"parent": "head",
"pivot": [-0.1, 4.25, -1.25],
"cubes": [
{"origin": [-7.5, 2.85, -0.5], "size": [1, 1, 1], "inflate": 0.1, "uv": [20, 19]}
]
},
{
"name": "finger_right2",
"parent": "fingers_right",
"pivot": [-6.5, 3.85, -0.6],
"rotation": [0, -17.5, 0],
"cubes": [
{"origin": [-7.5, 2.85, -1.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [16, 19]}
]
},
{
"name": "finger_right3",
"parent": "fingers_right",
"pivot": [-6.5, 3.85, 0.6],
"rotation": [0, 17.5, 0],
"cubes": [
{"origin": [-7.5, 2.85, 0.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [24, 19]}
{"origin": [-1.5, 4.75, -3.1575], "size": [3, 2, 0], "uv": [25, 12]}
]
},
{
"name": "arm_hammer_left",
"parent": "arms",
"pivot": [1.5, 3.25, 0]
"parent": "torso",
"pivot": [2, 3.25, 0]
},
{
"name": "hammer",
"parent": "arm_hammer_left",
"pivot": [7.25, 3, -0.5]
"pivot": [6.75, 3, -0.5]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [7.5, 7.41875, -0.525],
"pivot": [6.75, 7.41875, -0.525],
"cubes": [
{"origin": [7, 1.25, -1], "size": [1, 4, 1], "uv": [54, 12]},
{"origin": [7, 1.25, -1], "size": [1, 4, 1], "inflate": 0.1, "uv": [59, 12]}
{"origin": [5.25, 5.25, -2], "size": [3, 6, 3], "uv": [16, 12]},
{"origin": [6.25, 1.75, -1], "size": [1, 4, 1], "uv": [0, 0]},
{"origin": [5.75, 7, -5.65], "size": [2, 0, 2], "pivot": [6.5, 6.4375, -2.575], "rotation": [-90, 0, 0], "uv": [22, 22]},
{"origin": [6.25, 6.925, -5.8], "size": [1, 0, 1], "pivot": [6.5, 6.4375, -2.575], "rotation": [-90, 0, 0], "uv": [23, 21]}
]
},
{
"name": "rattle",
"parent": "hammer2",
"pivot": [7.5, 9.75, -2],
"name": "arm_left",
"parent": "torso",
"pivot": [2, 3.25, 0],
"cubes": [
{"origin": [7, 9.25, -2.5], "size": [1, 1, 1], "inflate": 0.01, "pivot": [7.5, 9.75, -2], "rotation": [0, 0, 45], "uv": [60, 1]},
{"origin": [6.5, 7.25, -2.4], "size": [2, 2, 1], "inflate": 0.11, "pivot": [7.5, 8.25, -1.9], "rotation": [0, 0, 45], "uv": [46, 0]},
{"origin": [5.5, 4.75, -2.5], "size": [4, 7, 4], "uv": [48, 0]}
{"origin": [2, 2.25, -1.5], "size": [4, 2, 3], "uv": [0, 19]}
]
},
{
"name": "locator_physical",
"parent": "rattle",
"pivot": [7.5, 11.75, -0.5],
"locators": {
"physical": [7.5, 11.75, -0.5]
}
"name": "finger_left",
"parent": "arm_left",
"pivot": [6, 3.5, 0],
"cubes": [
{"origin": [6, 2.5, -0.5], "size": [1, 1, 1], "uv": [26, 10]}
]
},
{
"name": "legs",
"parent": "body",
"pivot": [0, 1.5, 0]
"name": "finger_left2",
"parent": "arm_left",
"pivot": [6, 3.5, -0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [6, 2.5, -1.5], "size": [1, 1, 1], "uv": [43, 2]}
]
},
{
"name": "finger_left3",
"parent": "arm_left",
"pivot": [6, 3.5, 0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [6, 2.5, 0.5], "size": [1, 1, 1], "uv": [11, 19]}
]
},
{
"name": "arm_right",
"parent": "torso",
"pivot": [-2, 3.25, 0],
"cubes": [
{"origin": [-6, 2.25, -1.5], "size": [4, 2, 3], "uv": [20, 0]}
]
},
{
"name": "finger_right",
"parent": "arm_right",
"pivot": [-6, 3.5, 0],
"cubes": [
{"origin": [-7, 2.5, -0.5], "size": [1, 1, 1], "uv": [28, 14]}
]
},
{
"name": "finger_right2",
"parent": "arm_right",
"pivot": [-6, 3.5, -0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-7, 2.5, -1.5], "size": [1, 1, 1], "uv": [56, 9]}
]
},
{
"name": "finger_right3",
"parent": "arm_right",
"pivot": [-6, 3.5, 0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-7, 2.5, 0.5], "size": [1, 1, 1], "uv": [52, 9]}
]
},
{
"name": "leg_left",
"parent": "legs",
"pivot": [1.25, 1.5, 0],
"parent": "body",
"pivot": [0.75, 1.5, 0],
"cubes": [
{"origin": [-0.25, -0.25, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [35, 0]}
{"origin": [0.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [35, 0]}
]
},
{
"name": "locator_foot_secondary",
"parent": "leg_left",
"pivot": [1.4, 0.5, 0.1],
"rotation": [90, 0, 0],
"locators": {
"foot_secondary": [1.4, 0.5, 0.1]
}
},
{
"name": "leg_right",
"parent": "legs",
"pivot": [-1.25, 1.5, 0],
"parent": "body",
"pivot": [-0.75, 1.5, 0],
"cubes": [
{"origin": [-2.75, -0.25, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [23, 0]}
{"origin": [-2.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [52, 3]}
]
},
{
"name": "locator_foot_primary",
"parent": "leg_right",
"pivot": [-1.4, 0.5, 0.1],
"rotation": [90, 0, 0],
"locators": {
"foot_primary": [-1.4, 0.5, 0.1]
}
}
]
}
@@ -0,0 +1,233 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.tinkatink_dot",
"texture_width": 64,
"texture_height": 32,
"visible_bounds_width": 2,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "tinkatink",
"pivot": [0, 0, 0]
},
{
"name": "body",
"parent": "tinkatink",
"pivot": [0, 3.75, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 1.75, -0.25],
"cubes": [
{"origin": [-2, 1.5, -2], "size": [4, 3, 4], "uv": [0, 12]},
{"origin": [-1, 2, -2.75], "size": [2, 2, 1], "pivot": [0, 3, -2.25], "rotation": [0, 0, 45], "uv": [12, 12]}
]
},
{
"name": "head",
"parent": "torso",
"pivot": [0, 4.25, -0.25],
"cubes": [
{"origin": [-3.5, 4.25, -3.25], "size": [7, 6, 6], "uv": [0, 0]}
]
},
{
"name": "hair3",
"parent": "head",
"pivot": [0, 10.25, -0.25],
"rotation": [-5, 0, 0],
"cubes": [
{"origin": [-2.5, 10.25, -3.25], "size": [5, 0, 3], "uv": [11, 21]}
]
},
{
"name": "hair4",
"parent": "hair3",
"pivot": [0, 10.25, -3.25],
"rotation": [-15, 0, 0],
"cubes": [
{"origin": [-2.5, 8.25, -3.25], "size": [5, 2, 0], "uv": [43, 0]}
]
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.75, 6.5, -2.76],
"rotation": [0, 0, -5],
"cubes": [
{"origin": [-2.75, 6, -3.26], "size": [1, 2, 1], "uv": [51, 2]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-0.5, 3.5, -0.15],
"cubes": [
{"origin": [-2.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [47, 2]}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.75, 6.5, -2.76],
"rotation": [0, 0, 5],
"cubes": [
{"origin": [1.75, 6, -3.26], "size": [1, 2, 1], "uv": [26, 7]}
]
},
{
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [0.5, 3.5, -0.15],
"cubes": [
{"origin": [1.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [32, 8]}
]
},
{
"name": "hair",
"parent": "head",
"pivot": [0, 10.25, 0.25],
"rotation": [12.5, 0, 0],
"cubes": [
{"origin": [0, 9.75, -0.75], "size": [0, 2, 1], "uv": [4, 0]}
]
},
{
"name": "hair2",
"parent": "hair",
"pivot": [0, 11.75, 0.25],
"rotation": [22.5, 0, 0],
"cubes": [
{"origin": [0, 11.75, -1.75], "size": [0, 3, 2], "inflate": 0.01, "uv": [0, 10]}
]
},
{
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 4.25, -0.25],
"cubes": [
{"origin": [-2.5, 4.75, -3.2575], "size": [5, 2, 0], "inflate": 0.001, "uv": [26, 5]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [-0.1, 4.25, -1.25],
"cubes": [
{"origin": [-1.5, 4.75, -3.1575], "size": [3, 2, 0], "uv": [25, 12]}
]
},
{
"name": "arm_hammer_left",
"parent": "torso",
"pivot": [2, 3.25, 0]
},
{
"name": "hammer",
"parent": "arm_hammer_left",
"pivot": [6.75, 3, -0.5]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [6.75, 7.41875, -0.525],
"cubes": [
{"origin": [5.25, 5.25, -2], "size": [3, 6, 3], "uv": [16, 12]},
{"origin": [6.25, 1.75, -1], "size": [1, 4, 1], "uv": [0, 0]},
{"origin": [5.75, 8.2625, -3.0125], "size": [2, 0, 2], "pivot": [6.75, 8.2625, -2.0125], "rotation": [-90, 0, 45], "uv": [-2, 24]}
]
},
{
"name": "arm_left",
"parent": "torso",
"pivot": [2, 3.25, 0],
"cubes": [
{"origin": [2, 2.25, -1.5], "size": [4, 2, 3], "uv": [0, 19]}
]
},
{
"name": "finger_left",
"parent": "arm_left",
"pivot": [6, 3.5, 0],
"cubes": [
{"origin": [6, 2.5, -0.5], "size": [1, 1, 1], "uv": [26, 10]}
]
},
{
"name": "finger_left2",
"parent": "arm_left",
"pivot": [6, 3.5, -0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [6, 2.5, -1.5], "size": [1, 1, 1], "uv": [43, 2]}
]
},
{
"name": "finger_left3",
"parent": "arm_left",
"pivot": [6, 3.5, 0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [6, 2.5, 0.5], "size": [1, 1, 1], "uv": [11, 19]}
]
},
{
"name": "arm_right",
"parent": "torso",
"pivot": [-2, 3.25, 0],
"cubes": [
{"origin": [-6, 2.25, -1.5], "size": [4, 2, 3], "uv": [20, 0]}
]
},
{
"name": "finger_right",
"parent": "arm_right",
"pivot": [-6, 3.5, 0],
"cubes": [
{"origin": [-7, 2.5, -0.5], "size": [1, 1, 1], "uv": [28, 14]}
]
},
{
"name": "finger_right2",
"parent": "arm_right",
"pivot": [-6, 3.5, -0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-7, 2.5, -1.5], "size": [1, 1, 1], "uv": [56, 9]}
]
},
{
"name": "finger_right3",
"parent": "arm_right",
"pivot": [-6, 3.5, 0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-7, 2.5, 0.5], "size": [1, 1, 1], "uv": [52, 9]}
]
},
{
"name": "leg_left",
"parent": "body",
"pivot": [0.75, 1.5, 0],
"cubes": [
{"origin": [0.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [35, 0]}
]
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-0.75, 1.5, 0],
"cubes": [
{"origin": [-2.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [52, 3]}
]
}
]
}
]
}
@@ -4,7 +4,7 @@
{
"description": {
"identifier": "geometry.tinkatuff",
"texture_width": 128,
"texture_width": 64,
"texture_height": 64,
"visible_bounds_width": 3,
"visible_bounds_height": 2.5,
@@ -15,680 +15,289 @@
"name": "tinkatuff",
"pivot": [0, 0, 0]
},
{
"name": "locator_root",
"parent": "tinkatuff",
"pivot": [0, 0, 0],
"locators": {
"root": [0, 0, 0]
}
},
{
"name": "locator_top",
"parent": "tinkatuff",
"pivot": [0, 22, 0],
"locators": {
"top": [0, 22, 0]
}
},
{
"name": "locator_special",
"parent": "tinkatuff",
"pivot": [0, 8, -8],
"locators": {
"special": [0, 8, -8]
}
},
{
"name": "body",
"parent": "tinkatuff",
"pivot": [0, 6.25, 0]
},
{
"name": "locator_target",
"parent": "body",
"pivot": [0, 8, -6],
"locators": {
"target": [0, 8, -6]
}
},
{
"name": "locator_middle",
"parent": "body",
"pivot": [0, 9, 0],
"locators": {
"middle": [0, 9, 0]
}
"pivot": [0, 6, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 4.5, 0],
"pivot": [0, 4.25, 0],
"cubes": [
{"origin": [-2.5, 3.25, -2], "size": [5, 3, 4], "inflate": 0.25, "uv": [0, 14]},
{"origin": [-2.5, 3.25, -2], "size": [5, 3, 4], "inflate": 0.5, "uv": [18, 14]}
{"origin": [-2, 7.5, -1.5], "size": [4, 3, 3], "uv": [41, 41]},
{"origin": [-2.5, 3, -2], "size": [5, 5, 4], "uv": [36, 0]}
]
},
{
"name": "chest",
"name": "skirt_left",
"parent": "torso",
"pivot": [0, 6, 0],
"pivot": [2.5, 3, 0],
"rotation": [0, 0, 45],
"cubes": [
{"origin": [-2, 5.75, -2], "size": [4, 4, 4], "uv": [24, 0]}
{"origin": [2.5, 3, -1.5], "size": [3, 0, 3], "uv": [6, 15]}
]
},
{
"name": "head",
"parent": "chest",
"pivot": [0, 8.75, 0.5],
"name": "skirt_right",
"parent": "torso",
"pivot": [-2.5, 3, 0],
"rotation": [0, 0, -45],
"cubes": [
{"origin": [-4, 8.75, -4], "size": [8, 6, 8], "uv": [0, 0]}
{"origin": [-5.5, 3, -1.5], "size": [3, 0, 3], "uv": [0, 15]}
]
},
{
"name": "locator_mouth",
"parent": "head",
"pivot": [0, 9.75, -4],
"locators": {
"mouth": [0, 9.75, -4]
}
},
{
"name": "locator_item_face",
"parent": "head",
"pivot": [0, 12.25, -4],
"locators": {
"item_face": [0, 12.25, -4]
}
},
{
"name": "locator_face",
"parent": "head",
"pivot": [0, 11.75, -4],
"locators": {
"face": [0, 11.75, -4]
}
},
{
"name": "face_ditto",
"parent": "head",
"pivot": [0, 11, -3.9]
},
{
"name": "eyes_ditto",
"parent": "face_ditto",
"pivot": [0, 11.75, -3.92],
"cubes": [
{"origin": [-3, 11.25, -3.92], "size": [6, 1, 0], "uv": [22, 49]}
]
},
{
"name": "eyes_blink_ditto",
"parent": "face_ditto",
"pivot": [0, 11.75, -3.82],
"cubes": [
{"origin": [-3.5, 11.25, -3.82], "size": [7, 1, 0], "uv": [21, 51]},
{"origin": [-3, 11.75, -3.83], "size": [6, 1, 0], "uv": [22, 53]}
]
},
{
"name": "mouth_ditto",
"parent": "face_ditto",
"pivot": [0, 10, -3.9],
"cubes": [
{"origin": [-2.5, 9.25, -3.91], "size": [5, 1, 0], "uv": [23, 57]},
{"origin": [-3.5, 9.75, -3.91], "size": [7, 1, 0], "uv": [21, 55]}
]
},
{
"name": "mouth_open_ditto",
"parent": "face_ditto",
"pivot": [0, 9.75, -3.81],
"cubes": [
{"origin": [-3.5, 8.75, -3.81], "size": [7, 2, 0], "uv": [21, 59]}
]
},
{
"name": "face",
"parent": "head",
"pivot": [0, 11.75, -4.01]
},
{
"name": "eyes",
"parent": "face",
"pivot": [0, 12, -3.51]
},
{
"name": "brow_left",
"parent": "eyes",
"pivot": [2.25, 12.75, -3.5],
"cubes": [
{"origin": [1.75, 12.25, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [16, 52]}
]
},
{
"name": "brow_right",
"parent": "eyes",
"pivot": [-2.25, 12.75, -3.5],
"cubes": [
{"origin": [-2.75, 12.25, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [11, 52], "mirror": true}
]
},
{
"name": "eye_left",
"parent": "eyes",
"pivot": [2.5, 12, -3.51],
"cubes": [
{"origin": [2, 11, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [6, 52]}
]
},
{
"name": "locator_eye_left",
"parent": "eye_left",
"pivot": [2.5, 12, -4],
"locators": {
"eye2": [2.5, 12, -4]
}
},
{
"name": "eye_emote_left",
"parent": "eye_left",
"pivot": [2.5, 12, -4],
"cubes": [
{"origin": [2, 12, -4], "size": [1, 1, 1], "inflate": 0.025, "uv": [6, 49]}
]
},
{
"name": "eye_emote_left2",
"parent": "eye_left",
"pivot": [2.5, 12, -4],
"cubes": [
{"origin": [2, 12, -4], "size": [1, 1, 1], "inflate": 0.02, "uv": [16, 49]}
]
},
{
"name": "eye_right",
"parent": "eyes",
"pivot": [-2.5, 12, -3.51],
"cubes": [
{"origin": [-3, 11, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [1, 52], "mirror": true}
]
},
{
"name": "locator_eye_right",
"parent": "eye_right",
"pivot": [-2.5, 12, -4],
"locators": {
"eye1": [-2.5, 12, -4]
}
},
{
"name": "eye_emote_right",
"parent": "eye_right",
"pivot": [-2.5, 12, -4],
"cubes": [
{"origin": [-3, 12, -4], "size": [1, 1, 1], "inflate": 0.025, "uv": [1, 49], "mirror": true}
]
},
{
"name": "eye_emote_right2",
"parent": "eye_right",
"pivot": [-2.5, 12, -4],
"cubes": [
{"origin": [-3, 12, -4], "size": [1, 1, 1], "inflate": 0.02, "uv": [11, 49], "mirror": true}
]
},
{
"name": "eyelid_left",
"parent": "eyes",
"pivot": [2.5, 12, -3.41],
"cubes": [
{"origin": [1.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [8, 45]}
]
},
{
"name": "eyelid_right",
"parent": "eyes",
"pivot": [-2.5, 12, -3.41],
"cubes": [
{"origin": [-3.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [1, 45], "mirror": true}
]
},
{
"name": "eyelid_hurt_left",
"parent": "eyes",
"pivot": [2.5, 12, -3.41],
"cubes": [
{"origin": [1.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [22, 45]}
]
},
{
"name": "eyelid_hurt_right",
"parent": "eyes",
"pivot": [-2.5, 12, -3.41],
"cubes": [
{"origin": [-3.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [15, 45], "mirror": true}
]
},
{
"name": "eyelid_happy_left",
"parent": "eyes",
"pivot": [2.5, 12, -3.41],
"cubes": [
{"origin": [1, 11, -3.91], "size": [3, 2, 1], "uv": [38, 45]}
]
},
{
"name": "eyelid_happy_right",
"parent": "eyes",
"pivot": [-2.5, 12, -3.41],
"cubes": [
{"origin": [-4, 11, -3.91], "size": [3, 2, 1], "uv": [29, 45], "mirror": true}
]
},
{
"name": "mouths",
"parent": "face",
"pivot": [0, 10.25, -3.91],
"cubes": [
{"origin": [-1.5, 9.75, -4], "size": [3, 1, 1], "inflate": 0.01, "uv": [1, 55]}
]
},
{
"name": "mouth_top",
"parent": "mouths",
"pivot": [0, 11.25, -4.01],
"cubes": [
{"origin": [-0.5, 10.27, -4], "size": [1, 1, 1], "inflate": 0.03, "uv": [10, 55]}
]
},
{
"name": "mouth_bottom",
"parent": "mouths",
"pivot": [0, 10.25, -4.01],
"cubes": [
{"origin": [-0.5, 9.23, -4], "size": [1, 1, 1], "inflate": 0.03, "uv": [10, 59]}
]
},
{
"name": "mouth_open",
"parent": "mouths",
"pivot": [0, 10.25, -3.91],
"cubes": [
{"origin": [-1.5, 9.25, -3.9], "size": [3, 2, 1], "inflate": 0.02, "uv": [1, 58]}
]
},
{
"name": "hair",
"parent": "head",
"pivot": [0, 17.25, 0.7],
"rotation": [-10, 0, 0],
"cubes": [
{"origin": [4.5, 10.25, -3.8], "size": [0, 3, 9], "pivot": [4.5, 13.25, 0.7], "rotation": [0, 0, 9], "uv": [49, 47]},
{"origin": [-4.5, 10.25, -3.8], "size": [0, 3, 9], "pivot": [-4.5, 13.25, 0.7], "rotation": [0, 0, -9], "uv": [49, 51], "mirror": true},
{"origin": [-4.5, 13.25, -3.8], "size": [9, 4, 9], "uv": [33, 0]},
{"origin": [-2.5, 10.25, -3.8], "size": [5, 3, 0], "pivot": [0, 13.25, -3.8], "rotation": [13.5, 0, 0], "uv": [53, 48]},
{"origin": [0.5, 10.25, 5.2], "size": [4, 3, 0], "pivot": [4.5, 13.25, 5.2], "rotation": [0, 0, 9], "uv": [49, 52]},
{"origin": [-4.5, 10.25, 5.2], "size": [4, 3, 0], "pivot": [-4.5, 13.25, 5.2], "rotation": [0, 0, -9], "uv": [59, 52], "mirror": true}
]
},
{
"name": "locator_head",
"parent": "hair",
"pivot": [0, 16.25, -3.8],
"locators": {
"head": [0, 16.25, -3.8]
}
},
{
"name": "locator_item_hat",
"parent": "hair",
"pivot": [0, 17.25, 0.7],
"locators": {
"item_hat": [0, 17.25, 0.7]
}
},
{
"name": "hair2",
"parent": "hair",
"pivot": [4.5, 14.25, -0.8],
"rotation": [22.5, -90, 0]
},
{
"name": "hair3",
"parent": "hair2",
"pivot": [4.5, 14.25, -0.8],
"cubes": [
{"origin": [2.5, 14.25, -0.8], "size": [4, 7, 0], "uv": [40, 56]}
]
},
{
"name": "ponytail",
"parent": "hair",
"pivot": [0, 16.25, 1.2],
"rotation": [-20, 0, 0],
"cubes": [
{"origin": [-4, 15.25, 0.2], "size": [8, 7, 7], "uv": [37, 13]}
]
},
{
"name": "ponytail2",
"parent": "ponytail",
"pivot": [0, 18.25, 6.7],
"rotation": [-22.5, 0, 0],
"cubes": [
{"origin": [-3, 15.75, 5.2], "size": [6, 5, 7], "uv": [39, 27]}
]
},
{
"name": "ponytail3",
"parent": "ponytail2",
"pivot": [0, 17.75, 11.2],
"rotation": [52.5, 0, 0],
"cubes": [
{"origin": [-1.5, 16.25, 10.7], "size": [3, 3, 5], "uv": [60, 0]}
]
},
{
"name": "arms",
"parent": "chest",
"pivot": [0, 7.5, 0]
},
{
"name": "arm_left",
"parent": "arms",
"pivot": [2, 7.5, 0],
"parent": "torso",
"pivot": [2, 8, 0],
"cubes": [
{"origin": [1, 6.5, -1.5], "size": [4, 2, 3], "uv": [14, 28]}
{"origin": [1, 7, -1], "size": [4, 2, 2], "uv": [35, 47]}
]
},
{
"name": "arm_left2",
"parent": "arm_left",
"pivot": [5, 8.5, 1],
"pivot": [5, 9, 1],
"cubes": [
{"origin": [5, 6, -2], "size": [4, 3, 4], "inflate": 0.001, "uv": [16, 21]}
{"origin": [5, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 35]}
]
},
{
"name": "locator_hand_secondary",
"parent": "arm_left2",
"pivot": [8.5, 7.45, 0],
"rotation": [0, -90, 0],
"locators": {
"hand_secondary": [8.5, 7.45, 0]
}
},
{
"name": "fingers_left",
"parent": "arm_left2",
"pivot": [9, 7.25, -0.5]
},
{
"name": "finger_left",
"parent": "fingers_left",
"pivot": [9, 7.75, -0.75],
"parent": "arm_left2",
"pivot": [9, 7.75, -0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [9, 7.75, -1.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [0, 23]}
{"origin": [9, 7.75, -1.5], "size": [1, 1, 1], "uv": [33, 44]}
]
},
{
"name": "finger_left2",
"parent": "fingers_left",
"pivot": [9, 7.75, 0.75],
"parent": "arm_left2",
"pivot": [9, 7.75, 0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [9, 7.75, 0.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [12, 23]}
{"origin": [9, 7.75, 0.5], "size": [1, 1, 1], "uv": [40, 30]}
]
},
{
"name": "finger_left3",
"parent": "fingers_left",
"pivot": [9, 7.25, 0],
"parent": "arm_left2",
"pivot": [9, 8, 0],
"cubes": [
{"origin": [9, 6.25, -0.5], "size": [1, 1, 1], "inflate": 0.25, "uv": [16, 23]}
{"origin": [9, 7, -0.5], "size": [1, 1, 1], "uv": [36, 30]}
]
},
{
"name": "arm_hammer_right",
"parent": "torso",
"pivot": [-2, 8, 0]
},
{
"name": "arm_hammer_right2",
"parent": "arm_hammer_right",
"pivot": [-5, 9, 1]
},
{
"name": "hammer",
"parent": "arm_hammer_right2",
"pivot": [-9.75, 8, 0]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [-9.55, 7.9675, -9.0675],
"cubes": [
{"origin": [-11, 6.5, -20], "size": [3, 3, 6], "uv": [30, 9]},
{"origin": [-10.5, 6.475, -18.25], "size": [2, 0, 2], "uv": [-1, 54]},
{"origin": [-10, 6.4, -18.4], "size": [1, 0, 1], "uv": [-1, 54]},
{"origin": [-11, 6.5, -12.5], "size": [3, 3, 3], "uv": [0, 47]},
{"origin": [-10, 7.5, -14.5], "size": [1, 1, 18], "inflate": 0.001, "uv": [0, 0]},
{"origin": [-15.5, 4.025, -18.525], "size": [12, 11, 0], "pivot": [-9.5, 9.525, -18.525], "rotation": [-90, -180, 0], "uv": [0, 36]},
{"origin": [-15.5, 3.5, -30.5], "size": [0, 8, 5], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [34, 31]},
{"origin": [-15.5, 3.5, -30.5], "size": [3, 8, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [47, 47]},
{"origin": [-7.5, 2.5, -30.5], "size": [4, 9, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [12, 47]},
{"origin": [-3.5, 2.525, -20.025], "size": [0, 9, 5], "pivot": [-3.5, 7.025, -17.525], "rotation": [90, 180, 0], "uv": [24, 31]},
{"origin": [-13.5, 12.5, -29.5], "size": [8, 1, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [0, 7]},
{"origin": [-13.5, 7.525, -26.025], "size": [8, 0, 4], "pivot": [-9.5, 7.525, -24.025], "rotation": [90, 180, 0], "uv": [17, 19]}
]
},
{
"name": "arm_right",
"parent": "arms",
"pivot": [-2, 7.5, 0],
"parent": "torso",
"pivot": [-2, 8, 0],
"cubes": [
{"origin": [-5, 6.5, -1.5], "size": [4, 2, 3], "uv": [0, 28], "mirror": true}
{"origin": [-5, 7, -1], "size": [4, 2, 2], "uv": [0, 32]}
]
},
{
"name": "arm_right2",
"parent": "arm_right",
"pivot": [-5, 8.5, 1.5],
"pivot": [-5, 9, 1],
"cubes": [
{"origin": [-9, 6, -2], "size": [4, 3, 4], "inflate": 0.001, "uv": [0, 21], "mirror": true}
{"origin": [-9, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 30]}
]
},
{
"name": "locator_hand_primary",
"parent": "arm_right2",
"pivot": [-8.5, 7.45, 0],
"rotation": [0, 90, 0],
"locators": {
"hand_primary": [-8.5, 7.45, 0]
}
},
{
"name": "fingers_right",
"parent": "arm_right2",
"pivot": [-9, 7.25, -0.5]
},
{
"name": "finger_right",
"parent": "fingers_right",
"pivot": [-9, 7.75, -0.75],
"parent": "arm_right2",
"pivot": [-9, 7.75, -0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-10, 7.75, -1.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [0, 21], "mirror": true}
{"origin": [-10, 7.75, -1.5], "size": [1, 1, 1], "uv": [36, 2]}
]
},
{
"name": "finger_right2",
"parent": "fingers_right",
"pivot": [-9, 7.75, 0.75],
"parent": "arm_right2",
"pivot": [-9, 7.75, 0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-10, 7.75, 0.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [12, 21], "mirror": true}
{"origin": [-10, 7.75, 0.5], "size": [1, 1, 1], "uv": [36, 0]}
]
},
{
"name": "finger_right3",
"parent": "fingers_right",
"pivot": [-9, 7.25, 0],
"parent": "arm_right2",
"pivot": [-9, 8, 0],
"cubes": [
{"origin": [-10, 6.25, -0.5], "size": [1, 1, 1], "inflate": 0.25, "uv": [16, 21], "mirror": true}
{"origin": [-10, 7, -0.5], "size": [1, 1, 1], "uv": [10, 32]}
]
},
{
"name": "arm_hammer_right",
"parent": "arms",
"pivot": [-2, 7.5, 0]
},
{
"name": "arm_hammer_right2",
"parent": "arm_hammer_right",
"pivot": [-5, 8.5, 1.5]
},
{
"name": "hammer",
"parent": "arm_hammer_right2",
"pivot": [-10, 7.5, 0]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [-10.05, 7.5, -11.25],
"cubes": [
{"origin": [-11, 6.5, -11.85], "size": [2, 2, 16], "inflate": -0.1, "uv": [91, 18]}
]
},
{
"name": "ball",
"parent": "hammer2",
"pivot": [-10, 7.5, -14.75],
"cubes": [
{"origin": [-11.5, 6, -14.75], "size": [3, 3, 3], "uv": [94, 27]},
{"origin": [-11.5, 6, -14.75], "size": [3, 3, 3], "inflate": 0.1, "uv": [112, 27]}
]
},
{
"name": "rattle",
"parent": "hammer2",
"pivot": [-10, 7.5, -15.25],
"cubes": [
{"origin": [-11.5, 6, -22.75], "size": [3, 3, 6], "uv": [84, 37]},
{"origin": [-10.5, 7, -16.75], "size": [1, 1, 2], "uv": [97, 23]},
{"origin": [-10.5, 6, -21.25], "size": [1, 1, 1], "inflate": 0.02, "pivot": [-10, 6.5, -20.75], "rotation": [0, -45, 0], "uv": [97, 40]},
{"origin": [-11, 6, -20.25], "size": [2, 1, 2], "inflate": 0.02, "pivot": [-10, 6.5, -19.25], "rotation": [0, -45, 0], "uv": [81, 38]},
{"origin": [-11, 6, -20.75], "size": [2, 1, 2], "inflate": 0.01, "uv": [114, 23]}
]
},
{
"name": "locator_item",
"parent": "rattle",
"pivot": [-10, 5.3, -19],
"locators": {
"item": {
"offset": [-10, 5.3, -19],
"rotation": [0, 135, 0]
}
}
},
{
"name": "plates",
"parent": "hammer2",
"pivot": [-10, 9.025, -20.275]
},
{
"name": "plate_top",
"parent": "plates",
"pivot": [-3.5, 9.525, -20.275],
"cubes": [
{"origin": [-4, 4.5, -20.26], "size": [6, 8, 0], "pivot": [-4, 10, -20.25], "rotation": [-90, -180, 0], "uv": [115, 46]},
{"origin": [0, -1.5, -20.26], "size": [4, 8, 0], "pivot": [-2, 4, -20.25], "rotation": [-90, -180, 0], "uv": [117, 37]},
{"origin": [8, 4.5, -20.26], "size": [0, 8, 6], "pivot": [2, 10, -20.25], "rotation": [-90, -180, 0], "uv": [115, 49]}
]
},
{
"name": "plate_middle",
"parent": "plates",
"pivot": [-6.5, 9.525, -21.775],
"cubes": [
{"origin": [-10, 4.5, -21.75], "size": [8, 9, 0], "pivot": [-8, 10, -21.75], "rotation": [-90, -180, 0], "uv": [85, 47]},
{"origin": [-10, 4.5, -30.75], "size": [8, 0, 6], "pivot": [-8, 10, -30.75], "rotation": [-90, -180, 0], "uv": [79, 57]}
]
},
{
"name": "plate_bottom",
"parent": "plates",
"pivot": [-16.5, 10.525, -20.775],
"cubes": [
{"origin": [-21, 4.5, -20.74], "size": [5, 8, 0], "pivot": [-16, 10, -20.75], "rotation": [-90, 180, 0], "uv": [103, 46]},
{"origin": [-24, -1.5, -20.74], "size": [4, 8, 0], "pivot": [-18, 4, -20.75], "rotation": [-90, 180, 0], "uv": [104, 37], "mirror": true},
{"origin": [-28, 4.5, -20.74], "size": [0, 8, 6], "pivot": [-22, 10, -20.75], "rotation": [-90, 180, 0], "uv": [102, 49], "mirror": true}
]
},
{
"name": "locator_physical",
"parent": "plate_bottom",
"pivot": [-16, 7, -19],
"locators": {
"physical": [-16, 7, -19]
}
},
{
"name": "bandage",
"parent": "plates",
"pivot": [-8, 10, -22.25],
"cubes": [
{"origin": [-10.75, 10.2, -23.25], "size": [2, 0, 6], "pivot": [-9.75, 13, -20.25], "rotation": [0, 45, 0], "uv": [74, 57]},
{"origin": [-10.75, 10.1, -23.25], "size": [2, 0, 6], "pivot": [-9.75, 13, -20.25], "rotation": [0, -55, 0], "uv": [69, 57]}
]
},
{
"name": "skirt",
"name": "head",
"parent": "torso",
"pivot": [0, 3, 0]
},
{
"name": "skirt_left",
"parent": "skirt",
"pivot": [2.7, 3, -0.5],
"rotation": [0, 0, 30],
"pivot": [0, 9, 0.5],
"cubes": [
{"origin": [2.7, 3, -2], "size": [3, 0, 3], "uv": [65, 60]}
{"origin": [-3.5, 9, -3.5], "size": [7, 6, 7], "uv": [0, 19]},
{"origin": [-4, 17.30092, -3.63266], "size": [8, 0, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [12, 0]},
{"origin": [4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [20, 0]},
{"origin": [-4, 10.30092, 4.36734], "size": [8, 7, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]},
{"origin": [-4, 11.30092, -3.63266], "size": [8, 6, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [42, 9]},
{"origin": [-4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]}
]
},
{
"name": "skirt_right",
"parent": "skirt",
"pivot": [-2.7, 3, -0.5],
"rotation": [0, 0, -30],
"name": "eye_left",
"parent": "head",
"pivot": [2.25, 12.25, -3.01],
"rotation": [0, 0, -7.5],
"cubes": [
{"origin": [-5.7, 3, -2], "size": [3, 0, 3], "uv": [65, 56], "mirror": true}
{"origin": [1.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [21, 23]}
]
},
{
"name": "legs",
"parent": "body",
"pivot": [-0.2, 4.5, 0]
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [2.25, 12.25, -2.91],
"cubes": [
{"origin": [1.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [26, 15]}
]
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.25, 12.25, -3.01],
"rotation": [0, 0, 7.5],
"cubes": [
{"origin": [-2.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [0, 21]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-2.25, 12.25, -2.91],
"cubes": [
{"origin": [-2.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [3, 23]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [0, 10.5, -3.41],
"cubes": [
{"origin": [-1.5, 9.5, -3.41], "size": [3, 2, 0], "uv": [20, 15]}
]
},
{
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 10.5, -3.51],
"cubes": [
{"origin": [-1.5, 9.5, -3.51], "size": [3, 2, 0], "uv": [0, 19]}
]
},
{
"name": "ponytail",
"parent": "head",
"pivot": [0, 16.81524, 1.82582],
"rotation": [2.5, 0, 0],
"cubes": [
{"origin": [-2, 16.62133, -0.28751], "size": [4, 4, 8], "uv": [20, 24]}
]
},
{
"name": "ponytail2",
"parent": "ponytail",
"pivot": [0, 16.62133, 3.71249],
"cubes": [
{"origin": [-2, 9.62133, 3.71249], "size": [4, 7, 4], "inflate": -0.001, "uv": [36, 19]}
]
},
{
"name": "ponytail3",
"parent": "ponytail2",
"pivot": [0, 11.62133, 7.71249],
"cubes": [
{"origin": [-2, 9.62133, 7.71249], "size": [4, 2, 3], "inflate": -0.002, "uv": [21, 45]}
]
},
{
"name": "hair2",
"parent": "head",
"pivot": [3.25, 16.625, -1.925],
"rotation": [-30, 0, 27.5]
},
{
"name": "hair3",
"parent": "hair2",
"pivot": [3.25, 16.625, -1.925],
"cubes": [
{"origin": [1.25, 16.625, -1.925], "size": [4, 6, 0], "uv": [48, 15]}
]
},
{
"name": "leg_left",
"parent": "legs",
"pivot": [1.55, 4, 0],
"parent": "body",
"pivot": [1.25, 4, 0],
"cubes": [
{"origin": [0.05, 1.5, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [12, 33]}
{"origin": [0.25, 2, -1], "size": [2, 2, 2], "uv": [28, 50]}
]
},
{
"name": "leg_left2",
"parent": "leg_left",
"pivot": [1.55, 1.7, -1.4],
"pivot": [1.25, 2, -1],
"cubes": [
{"origin": [0.05, 0, -1.5], "size": [3, 2, 3], "uv": [12, 39]}
{"origin": [0.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [50, 0]}
]
},
{
"name": "locator_foot_secondary",
"parent": "leg_left2",
"pivot": [1.6, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_secondary": [1.6, 0.5, 0]
}
},
{
"name": "leg_right",
"parent": "legs",
"pivot": [-1.55, 4, 0],
"parent": "body",
"pivot": [-1.25, 4, 0],
"cubes": [
{"origin": [-3.05, 1.5, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [0, 33], "mirror": true}
{"origin": [-2.25, 2, -1], "size": [2, 2, 2], "uv": [20, 50]}
]
},
{
"name": "leg_right2",
"parent": "leg_right",
"pivot": [-1.55, 1.7, -1.4],
"pivot": [-1.25, 2, -1],
"cubes": [
{"origin": [-3.05, 0, -1.5], "size": [3, 2, 3], "uv": [0, 39], "mirror": true}
{"origin": [-2.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [12, 32]}
]
},
{
"name": "locator_foot_primary",
"parent": "leg_right2",
"pivot": [-1.6, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_primary": [-1.6, 0.5, 0]
}
}
]
}
@@ -0,0 +1,305 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.tinkatuff_dot",
"texture_width": 64,
"texture_height": 64,
"visible_bounds_width": 3,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "tinkatuff",
"pivot": [0, 0, 0]
},
{
"name": "body",
"parent": "tinkatuff",
"pivot": [0, 6, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 4.25, 0],
"cubes": [
{"origin": [-2, 7.5, -1.5], "size": [4, 3, 3], "uv": [41, 41]},
{"origin": [-2.5, 3, -2], "size": [5, 5, 4], "uv": [36, 0]}
]
},
{
"name": "skirt_left",
"parent": "torso",
"pivot": [2.5, 3, 0],
"rotation": [0, 0, 45],
"cubes": [
{"origin": [2.5, 3, -1.5], "size": [3, 0, 3], "uv": [6, 15]}
]
},
{
"name": "skirt_right",
"parent": "torso",
"pivot": [-2.5, 3, 0],
"rotation": [0, 0, -45],
"cubes": [
{"origin": [-5.5, 3, -1.5], "size": [3, 0, 3], "uv": [0, 15]}
]
},
{
"name": "arm_left",
"parent": "torso",
"pivot": [2, 8, 0],
"cubes": [
{"origin": [1, 7, -1], "size": [4, 2, 2], "uv": [35, 47]}
]
},
{
"name": "arm_left2",
"parent": "arm_left",
"pivot": [5, 9, 1],
"cubes": [
{"origin": [5, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 35]}
]
},
{
"name": "finger_left",
"parent": "arm_left2",
"pivot": [9, 7.75, -0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [9, 7.75, -1.5], "size": [1, 1, 1], "uv": [33, 44]}
]
},
{
"name": "finger_left2",
"parent": "arm_left2",
"pivot": [9, 7.75, 0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [9, 7.75, 0.5], "size": [1, 1, 1], "uv": [40, 30]}
]
},
{
"name": "finger_left3",
"parent": "arm_left2",
"pivot": [9, 8, 0],
"cubes": [
{"origin": [9, 7, -0.5], "size": [1, 1, 1], "uv": [36, 30]}
]
},
{
"name": "arm_hammer_right",
"parent": "torso",
"pivot": [-2, 8, 0]
},
{
"name": "arm_hammer_right2",
"parent": "arm_hammer_right",
"pivot": [-5, 9, 1]
},
{
"name": "hammer",
"parent": "arm_hammer_right2",
"pivot": [-9.75, 8, 0]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [-9.55, 7.9675, -9.0675],
"cubes": [
{"origin": [-11, 6.5, -20], "size": [3, 3, 6], "uv": [30, 9]},
{"origin": [-10.5, 6.475, -18], "size": [2, 0, 2], "pivot": [-9.5, 6.475, -17], "rotation": [0, 45, 0], "uv": [-1, 54]},
{"origin": [-11, 6.5, -12.5], "size": [3, 3, 3], "uv": [0, 47]},
{"origin": [-10, 7.5, -14.5], "size": [1, 1, 18], "inflate": 0.001, "uv": [0, 0]},
{"origin": [-15.5, 4.025, -18.525], "size": [12, 11, 0], "pivot": [-9.5, 9.525, -18.525], "rotation": [-90, -180, 0], "uv": [0, 36]},
{"origin": [-15, 6.53, -18.04], "size": [7, 7, 0], "pivot": [-11, 9.53, -18.04], "rotation": [90, -45, -180], "uv": [42, 56]},
{"origin": [-15.5, 3.5, -30.5], "size": [0, 8, 5], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [34, 31]},
{"origin": [-15.5, 3.5, -30.5], "size": [3, 8, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [47, 47]},
{"origin": [-7.5, 2.5, -30.5], "size": [4, 9, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [12, 47]},
{"origin": [-3.5, 2.525, -20.025], "size": [0, 9, 5], "pivot": [-3.5, 7.025, -17.525], "rotation": [90, 180, 0], "uv": [24, 31]},
{"origin": [-13.5, 12.5, -29.5], "size": [8, 1, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [0, 7]},
{"origin": [-13.5, 7.525, -26.025], "size": [8, 0, 4], "pivot": [-9.5, 7.525, -24.025], "rotation": [90, 180, 0], "uv": [17, 19]}
]
},
{
"name": "arm_right",
"parent": "torso",
"pivot": [-2, 8, 0],
"cubes": [
{"origin": [-5, 7, -1], "size": [4, 2, 2], "uv": [0, 32]}
]
},
{
"name": "arm_right2",
"parent": "arm_right",
"pivot": [-5, 9, 1],
"cubes": [
{"origin": [-9, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 30]}
]
},
{
"name": "finger_right",
"parent": "arm_right2",
"pivot": [-9, 7.75, -0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-10, 7.75, -1.5], "size": [1, 1, 1], "uv": [36, 2]}
]
},
{
"name": "finger_right2",
"parent": "arm_right2",
"pivot": [-9, 7.75, 0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-10, 7.75, 0.5], "size": [1, 1, 1], "uv": [36, 0]}
]
},
{
"name": "finger_right3",
"parent": "arm_right2",
"pivot": [-9, 8, 0],
"cubes": [
{"origin": [-10, 7, -0.5], "size": [1, 1, 1], "uv": [10, 32]}
]
},
{
"name": "head",
"parent": "torso",
"pivot": [0, 9, 0.5],
"cubes": [
{"origin": [-3.5, 9, -3.5], "size": [7, 6, 7], "uv": [0, 19]},
{"origin": [-4, 17.30092, -3.63266], "size": [8, 0, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [12, 0]},
{"origin": [4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [20, 0]},
{"origin": [-4, 10.30092, 4.36734], "size": [8, 7, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]},
{"origin": [-4, 11.30092, -3.63266], "size": [8, 6, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [42, 9]},
{"origin": [-4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.25, 12.25, -3.01],
"rotation": [0, 0, -7.5],
"cubes": [
{"origin": [1.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [21, 23]}
]
},
{
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [2.25, 12.25, -2.91],
"cubes": [
{"origin": [1.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [26, 15]}
]
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.25, 12.25, -3.01],
"rotation": [0, 0, 7.5],
"cubes": [
{"origin": [-2.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [0, 21]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-2.25, 12.25, -2.91],
"cubes": [
{"origin": [-2.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [3, 23]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [0, 10.5, -3.41],
"cubes": [
{"origin": [-1.5, 9.5, -3.41], "size": [3, 2, 0], "uv": [20, 15]}
]
},
{
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 10.5, -3.51],
"cubes": [
{"origin": [-1.5, 9.5, -3.51], "size": [3, 2, 0], "uv": [0, 19]}
]
},
{
"name": "ponytail",
"parent": "head",
"pivot": [0, 16.81524, 1.82582],
"rotation": [2.5, 0, 0],
"cubes": [
{"origin": [-2, 16.62133, -0.28751], "size": [4, 4, 8], "uv": [20, 24]}
]
},
{
"name": "ponytail2",
"parent": "ponytail",
"pivot": [0, 16.62133, 3.71249],
"cubes": [
{"origin": [-2, 9.62133, 3.71249], "size": [4, 7, 4], "inflate": -0.001, "uv": [36, 19]}
]
},
{
"name": "ponytail3",
"parent": "ponytail2",
"pivot": [0, 11.62133, 7.71249],
"cubes": [
{"origin": [-2, 9.62133, 7.71249], "size": [4, 2, 3], "inflate": -0.002, "uv": [21, 45]}
]
},
{
"name": "hair2",
"parent": "head",
"pivot": [3.25, 16.625, -1.925],
"rotation": [-30, 0, 27.5]
},
{
"name": "hair3",
"parent": "hair2",
"pivot": [3.25, 16.625, -1.925],
"cubes": [
{"origin": [1.25, 16.625, -1.925], "size": [4, 6, 0], "uv": [48, 15]}
]
},
{
"name": "leg_left",
"parent": "body",
"pivot": [1.25, 4, 0],
"cubes": [
{"origin": [0.25, 2, -1], "size": [2, 2, 2], "uv": [28, 50]}
]
},
{
"name": "leg_left2",
"parent": "leg_left",
"pivot": [1.25, 2, -1],
"cubes": [
{"origin": [0.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [50, 0]}
]
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-1.25, 4, 0],
"cubes": [
{"origin": [-2.25, 2, -1], "size": [2, 2, 2], "uv": [20, 50]}
]
},
{
"name": "leg_right2",
"parent": "leg_right",
"pivot": [-1.25, 2, -1],
"cubes": [
{"origin": [-2.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [12, 32]}
]
}
]
}
]
}
@@ -0,0 +1,650 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.tinkaton_dot",
"texture_width": 128,
"texture_height": 128,
"visible_bounds_width": 5,
"visible_bounds_height": 4.5,
"visible_bounds_offset": [0, 1.75, 0]
},
"bones": [
{
"name": "bb_main",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-2, 0, 0], "size": [2, 2, 2], "uv": [0, 0]}
]
},
{
"name": "tinkaton",
"pivot": [0, 0, 0]
},
{
"name": "body_hammer",
"parent": "tinkaton",
"pivot": [0, 7, 0]
},
{
"name": "torso_hammer",
"parent": "body_hammer",
"pivot": [0, 4, 0]
},
{
"name": "arms_hammer",
"parent": "torso_hammer",
"pivot": [0, 7, 0]
},
{
"name": "arm_hammer_right",
"parent": "arms_hammer",
"pivot": [-1.5, 6.5, 0]
},
{
"name": "hand_hammer_right",
"parent": "arm_hammer_right",
"pivot": [-4.5, 6.5, 1.5]
},
{
"name": "hammer",
"parent": "hand_hammer_right",
"pivot": [-8, 5.125, -0.5]
},
{
"name": "hammer_handle",
"parent": "hammer",
"pivot": [-8, 5.375, -15.75],
"cubes": [
{"origin": [-8, 1.25, -23], "size": [0, 4, 4], "uv": [64, 48]},
{"origin": [-9.5, 5.25, -23], "size": [3, 4, 5], "inflate": -0.001, "uv": [87, 0]},
{"origin": [-9.5, 3.25, -19], "size": [3, 5, 4], "uv": [88, 34]},
{"origin": [-9, 4.25, -15], "size": [2, 2, 21], "uv": [0, 27]}
]
},
{
"name": "hammer_middle",
"parent": "hammer_handle",
"pivot": [-8.8, 5.25, -29],
"cubes": [
{"origin": [-14, 12.252, -35], "size": [12, 0, 12], "inflate": 0.001, "uv": [37, 27]},
{"origin": [-14, -0.752, -35], "size": [12, 0, 12], "inflate": 0.001, "uv": [13, 27]},
{"origin": [-14, -0.75, -35], "size": [12, 13, 0], "inflate": 0.001, "uv": [80, 60]},
{"origin": [-14, -0.75, -35], "size": [0, 13, 12], "inflate": 0.001, "uv": [24, 50]},
{"origin": [-14, -0.75, -23], "size": [12, 13, 0], "inflate": 0.001, "uv": [20, 75]},
{"origin": [-2, -0.75, -35], "size": [0, 13, 12], "inflate": 0.001, "uv": [0, 38]},
{"origin": [-8, -2.75, -46], "size": [0, 12, 11], "uv": [48, 51]},
{"origin": [-9.3375, 5.7875, -30.025], "size": [2, 0, 2], "pivot": [-8.3375, 5.7875, -29.025], "rotation": [0, -45, -90], "uv": [93, 14]},
{"origin": [-13, -0.75, -24], "size": [10, 13, 0], "uv": [68, 83]},
{"origin": [-13, -0.75, -34], "size": [0, 13, 10], "uv": [0, 53]},
{"origin": [-3, -0.75, -34], "size": [0, 13, 10], "uv": [0, 17]},
{"origin": [-13, -0.75, -34], "size": [10, 13, 0], "uv": [0, 76]},
{"origin": [-13, -0.75, -34], "size": [10, 0, 10], "uv": [47, 0]},
{"origin": [-13, 12.25, -34], "size": [10, 0, 10], "uv": [36, 39]},
{"origin": [-10.5, 0.75, -28], "size": [1, 8, 1], "pivot": [-10, 5.75, -27.5], "rotation": [90, 0, 0], "uv": [20, 63]},
{"origin": [-11.5, 2.75, -30.5], "size": [3, 6, 3], "pivot": [-10, 5.75, -29], "rotation": [90, 0, -90], "uv": [57, 10]}
]
},
{
"name": "hammer_front",
"parent": "hammer_middle",
"pivot": [-7.4, 12.3, -28.5],
"cubes": [
{"origin": [-12, 12.25, -33], "size": [8, 3, 8], "uv": [64, 41]},
{"origin": [-17.5, 15.25, -38.25], "size": [19, 8, 19], "uv": [0, 0]},
{"origin": [-17.5, 15.25, -40.25], "size": [0, 8, 2], "uv": [16, 38]},
{"origin": [-17.5, 15.25, -40.25], "size": [5, 0, 2], "uv": [0, 46]},
{"origin": [-17.5, 23.25, -40.25], "size": [5, 0, 2], "uv": [0, 17]},
{"origin": [-17.5, 15.25, -40.25], "size": [15, 8, 0], "uv": [73, 52]}
]
},
{
"name": "nail",
"parent": "hammer_front",
"pivot": [-5.5, 20.25, -38.25],
"rotation": [10, 0, 0],
"cubes": [
{"origin": [-6.5, 19.25, -42.25], "size": [2, 2, 5], "uv": [88, 73]},
{"origin": [-8, 17.75, -43.25], "size": [5, 5, 1], "uv": [24, 56]}
]
},
{
"name": "locator_hammer",
"parent": "hammer_front",
"pivot": [-8, 23, -28.75],
"rotation": [90, 0, 0],
"locators": {
"hammer": [-8, 23, -28.75],
"physical": [-8, 23, -28.75],
"special2": [-8, 23, -28.75]
}
},
{
"name": "hammer_back",
"parent": "hammer_middle",
"pivot": [-8, -1, -29],
"cubes": [
{"origin": [-11, -3.75, -32], "size": [6, 3, 6], "uv": [44, 77]},
{"origin": [-12.5, -7.75, -33.5], "size": [9, 4, 9], "uv": [37, 49]}
]
},
{
"name": "seat_1_locator",
"parent": "hammer_middle",
"pivot": [-8, 0, -35],
"rotation": [105, 0, 0],
"locators": {
"seat_1": [-8, 0, -35]
}
},
{
"name": "body",
"parent": "tinkaton",
"pivot": [0, 7, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 4, 0],
"cubes": [
{"origin": [-2, 6.5, -1.5], "size": [4, 3, 3], "inflate": 0.001, "uv": [88, 43]},
{"origin": [-2.5, 3, -2], "size": [5, 4, 4], "uv": [0, 0]}
]
},
{
"name": "skirt_front_right",
"parent": "torso",
"pivot": [-1.75, 3, -1.25],
"rotation": [30, 45, 0],
"cubes": [
{"origin": [-3.25, 3, -4.25], "size": [3, 0, 3], "uv": [37, 50]}
]
},
{
"name": "skirt_front_left",
"parent": "torso",
"pivot": [1.75, 3, -1.25],
"rotation": [30, -45, 0],
"cubes": [
{"origin": [0.25, 3, -4.25], "size": [3, 0, 3], "uv": [36, 45]}
]
},
{
"name": "skirt_back_left",
"parent": "torso",
"pivot": [1.75, 3, 1.25],
"rotation": [-30, 45, 0],
"cubes": [
{"origin": [0.25, 3, 1.25], "size": [3, 0, 3], "uv": [36, 42]}
]
},
{
"name": "skirt_back_right",
"parent": "torso",
"pivot": [-1.75, 3, 1.25],
"rotation": [-30, -45, 0],
"cubes": [
{"origin": [-3.25, 3, 1.25], "size": [3, 0, 3], "uv": [36, 39]}
]
},
{
"name": "head",
"parent": "torso",
"pivot": [0, 7.75, 0],
"cubes": [
{"origin": [-3.5, 7.75, -3.5], "size": [7, 7, 7], "uv": [73, 20]},
{"origin": [-3.5, 9.25, -4], "size": [0, 6, 8], "inflate": 0.01, "uv": [24, 42]},
{"origin": [3.5, 9.25, -4], "size": [0, 6, 8], "inflate": 0.01, "uv": [0, 32]},
{"origin": [-3.5, 8.25, 4], "size": [7, 7, 0], "inflate": 0.01, "uv": [88, 80]},
{"origin": [-3.5, 11.25, -4], "size": [7, 4, 0], "inflate": 0.01, "uv": [28, 88]},
{"origin": [-3.5, 15.25, -4], "size": [7, 0, 8], "inflate": 0.01, "uv": [17, 39]}
]
},
{
"name": "ear_left",
"parent": "head",
"pivot": [0, 14.75, 0],
"rotation": [0, 0, 10],
"cubes": [
{"origin": [0, 14.75, -1], "size": [3, 6, 2], "uv": [0, 89]}
]
},
{
"name": "ear_left2",
"parent": "head",
"pivot": [3, 14.75, 0],
"rotation": [0, 0, 20],
"cubes": [
{"origin": [3, 13.75, 0], "size": [2, 3, 0], "uv": [44, 78]}
]
},
{
"name": "ear_right",
"parent": "head",
"pivot": [0, 14.75, 0],
"rotation": [0, 0, -10],
"cubes": [
{"origin": [-3, 14.75, -1], "size": [3, 6, 2], "uv": [88, 87]}
]
},
{
"name": "ear_right2",
"parent": "head",
"pivot": [-3, 14.75, 0],
"cubes": [
{"origin": [-5, 13.75, 0], "size": [2, 3, 0], "pivot": [-3, 14.75, -0.5], "rotation": [0, 0, -20], "uv": [76, 22]}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.5, 11.25, -3.025],
"cubes": [
{"origin": [2, 10.25, -3.525], "size": [1, 2, 1], "uv": [14, 0]}
]
},
{
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [2.5, 11.25, -2.925],
"cubes": [
{"origin": [2, 10.25, -3.425], "size": [1, 2, 1], "inflate": 0.01, "uv": [76, 19]}
]
},
{
"name": "locator_eye_left",
"parent": "eye_left",
"pivot": [-2.5, 11.25, -3.5],
"locators": {
"eye1": [-2.5, 11.25, -3.5]
}
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.5, 11.25, -3.025],
"cubes": [
{"origin": [-3, 10.25, -3.525], "size": [1, 2, 1], "uv": [0, 0]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-2.5, 11.25, -2.925],
"cubes": [
{"origin": [-3, 10.25, -3.425], "size": [1, 2, 1], "inflate": 0.01, "uv": [20, 72]}
]
},
{
"name": "locator_eye_right",
"parent": "eye_right",
"pivot": [2.5, 11.25, -3.5],
"locators": {
"eye2": [2.5, 11.25, -3.5]
}
},
{
"name": "mouths",
"parent": "head",
"pivot": [0, 9.25, -3.525]
},
{
"name": "mouth_open",
"parent": "mouths",
"pivot": [0, 9.25, -3.61],
"cubes": [
{"origin": [-2.5, 8.25, -3.41], "size": [5, 2, 0], "uv": [77, 0]}
]
},
{
"name": "locator_mouth",
"parent": "mouth_open",
"pivot": [0, 9.25, -3.5],
"locators": {
"mouth": [0, 9.25, -3.5]
}
},
{
"name": "mouth_closed",
"parent": "mouths",
"pivot": [0, 9.25, -3.41],
"cubes": [
{"origin": [-3.5, 8.25, -3.51], "size": [7, 2, 0], "uv": [48, 74]}
]
},
{
"name": "hair_right",
"parent": "head",
"pivot": [-3.5, 13.75, 0],
"cubes": [
{"origin": [-7, 9.75, -3], "size": [4, 5, 6], "uv": [14, 88]}
]
},
{
"name": "hair_right2",
"parent": "hair_right",
"pivot": [-3, 9.5, 0],
"cubes": [
{"origin": [-8, 0.75, -4], "size": [5, 9, 8], "uv": [69, 2]}
]
},
{
"name": "hair_right3",
"parent": "hair_right2",
"pivot": [-5.5, 0.75, 0],
"cubes": [
{"origin": [-5.5, -3.25, -4.5], "size": [0, 4, 9], "uv": [0, 4]}
]
},
{
"name": "hair_left",
"parent": "head",
"pivot": [3.5, 14.25, 0],
"cubes": [
{"origin": [3, 10.25, -3], "size": [4, 5, 6], "uv": [38, 86]}
]
},
{
"name": "hair_left2",
"parent": "hair_left",
"pivot": [3, 10, 0],
"cubes": [
{"origin": [3, 1.25, -4], "size": [5, 9, 8], "uv": [62, 66]}
]
},
{
"name": "hair_left3",
"parent": "hair_left2",
"pivot": [5.5, 1.25, 0],
"cubes": [
{"origin": [5.5, -2.75, -4.5], "size": [0, 4, 9], "uv": [0, 0]}
]
},
{
"name": "locator_head",
"parent": "head",
"pivot": [0, 15.25, -2.5],
"locators": {
"head": [0, 15.25, -2.5]
}
},
{
"name": "locator_item_hat",
"parent": "head",
"pivot": [0, 16.25, 0],
"locators": {
"item_hat": [0, 16.25, 0]
}
},
{
"name": "locator_tera_hat",
"parent": "head",
"pivot": [0, 15.25, 0],
"locators": {
"tera_hat": [0, 15.25, 0]
}
},
{
"name": "locator_face",
"parent": "head",
"pivot": [0, 10.25, -3.5],
"locators": {
"face": [0, 10.25, -3.5]
}
},
{
"name": "locator_item_face",
"parent": "head",
"pivot": [0, 11.5, -3.5],
"locators": {
"item_face": [0, 11.5, -3.5]
}
},
{
"name": "arms",
"parent": "torso",
"pivot": [0, 7, 0]
},
{
"name": "arm_left",
"parent": "arms",
"pivot": [1.5, 6.5, 0],
"cubes": [
{"origin": [1.5, 5.5, -1.5], "size": [3, 2, 3], "uv": [94, 16]}
]
},
{
"name": "hand_left",
"parent": "arm_left",
"pivot": [4.5, 6.5, 1.5],
"cubes": [
{"origin": [4.5, 5.5, -2], "size": [4, 2, 4], "inflate": 0.01, "uv": [52, 86]}
]
},
{
"name": "locator_hand_secondary",
"parent": "hand_left",
"pivot": [7.75, 6.5, 0],
"rotation": [0, -90, 0],
"locators": {
"hand_secondary": [7.75, 6.5, 0]
}
},
{
"name": "locator_item",
"parent": "hand_left",
"pivot": [9.5, 5.75, 0],
"locators": {
"item": [9.5, 5.75, 0]
}
},
{
"name": "finger_left",
"parent": "hand_left",
"pivot": [8.25, 7, -1.5],
"rotation": [0, 17.5, 0],
"cubes": [
{"origin": [8.25, 6, -2], "size": [2, 1, 1], "uv": [44, 76]}
]
},
{
"name": "finger_left2",
"parent": "hand_left",
"pivot": [8.5, 7, -0.5],
"rotation": [0, 5, 0],
"cubes": [
{"origin": [8.5, 6, -1], "size": [2, 1, 1], "uv": [73, 60]}
]
},
{
"name": "finger_left3",
"parent": "hand_left",
"pivot": [8.5, 7, 0.5],
"rotation": [0, -5, 0],
"cubes": [
{"origin": [8.5, 6, 0], "size": [2, 1, 1], "uv": [66, 47]}
]
},
{
"name": "finger_left4",
"parent": "hand_left",
"pivot": [8.25, 7, 1.5],
"rotation": [0, -17.5, 0],
"cubes": [
{"origin": [8.25, 6, 1], "size": [2, 1, 1], "uv": [66, 45]}
]
},
{
"name": "thumb_left",
"parent": "hand_left",
"pivot": [5, 5.5, -0.5],
"rotation": [0, 0, 42.5],
"cubes": [
{"origin": [5, 5.5, -1.5], "size": [2, 1, 2], "inflate": 0.01, "uv": [94, 24]}
]
},
{
"name": "arm_right",
"parent": "arms",
"pivot": [-1.5, 6.5, 0],
"cubes": [
{"origin": [-4.5, 5.5, -1.5], "size": [3, 2, 3], "uv": [58, 93]}
]
},
{
"name": "hand_right",
"parent": "arm_right",
"pivot": [-4.5, 6.5, 1.5],
"cubes": [
{"origin": [-8.5, 5.5, -2], "size": [4, 2, 4], "inflate": 0.01, "uv": [69, 35]}
]
},
{
"name": "locator_hand_primary",
"parent": "hand_right",
"pivot": [-7.75, 6.5, 0],
"rotation": [0, 90, 0],
"locators": {
"hand_primary": [-7.75, 6.5, 0]
}
},
{
"name": "finger_right",
"parent": "hand_right",
"pivot": [-8.25, 7, -1.5],
"rotation": [0, -17.5, 0],
"cubes": [
{"origin": [-10.25, 6, -2], "size": [2, 1, 1], "uv": [66, 43]}
]
},
{
"name": "finger_right2",
"parent": "hand_right",
"pivot": [-8.5, 7, -0.5],
"rotation": [0, -5, 0],
"cubes": [
{"origin": [-10.5, 6, -1], "size": [2, 1, 1], "uv": [66, 41]}
]
},
{
"name": "finger_right3",
"parent": "hand_right",
"pivot": [-8.5, 7, 0.5],
"rotation": [0, 5, 0],
"cubes": [
{"origin": [-10.5, 6, 0], "size": [2, 1, 1], "uv": [64, 56]}
]
},
{
"name": "finger_right4",
"parent": "hand_right",
"pivot": [-8.25, 7, 1.5],
"rotation": [0, 17.5, 0],
"cubes": [
{"origin": [-10.25, 6, 1], "size": [2, 1, 1], "uv": [12, 17]}
]
},
{
"name": "thumb_right",
"parent": "hand_right",
"pivot": [-5, 5.5, -0.5],
"rotation": [0, 0, -42.5],
"cubes": [
{"origin": [-7, 5.5, -1.5], "size": [2, 1, 2], "inflate": 0.01, "uv": [94, 21]}
]
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-1.25, 4, 0],
"cubes": [
{"origin": [-2.25, 2, -1], "size": [2, 2, 2], "uv": [10, 89]}
]
},
{
"name": "leg_right2",
"parent": "leg_right",
"pivot": [-1.25, 2, -1],
"cubes": [
{"origin": [-2.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [81, 34]}
]
},
{
"name": "locator_foot_primary",
"parent": "leg_right2",
"pivot": [-1.25, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_primary": [-1.25, 0.5, 0]
}
},
{
"name": "leg_left",
"parent": "body",
"pivot": [1.25, 4, 0],
"cubes": [
{"origin": [0.25, 2, -1], "size": [2, 2, 2], "uv": [70, 62]}
]
},
{
"name": "leg_left2",
"parent": "leg_left",
"pivot": [1.25, 2, -1],
"cubes": [
{"origin": [0.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [38, 54]}
]
},
{
"name": "locator_foot_secondary",
"parent": "leg_left2",
"pivot": [1.25, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_secondary": [1.25, 0.5, 0]
}
},
{
"name": "locator_middle",
"parent": "body",
"pivot": [0, 7, 0],
"locators": {
"middle": [0, 7, 0]
}
},
{
"name": "locator_target",
"parent": "body",
"pivot": [0, 7, -6],
"locators": {
"target": [0, 7, -6]
}
},
{
"name": "locator_root",
"parent": "tinkaton",
"pivot": [0, 0, 0],
"locators": {
"root": [0, 0, 0]
}
},
{
"name": "locator_special",
"parent": "tinkaton",
"pivot": [0, 7, -8],
"locators": {
"special": [0, 7, -8]
}
},
{
"name": "locator_top",
"parent": "tinkaton",
"pivot": [0, 23, 0],
"locators": {
"top": [0, 23, 0]
}
}
]
}
]
}
@@ -41,7 +41,7 @@
},
"walking": {
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.in_air && !q.is_sprinting",
"condition": "!q.in_air && q.has_entity ? !q.is_sprinting : 1.0",
"animations": [
"q.bedrock('heracross', 'ground_walk')",
{
@@ -53,7 +53,7 @@
},
"running": {
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.in_air && q.is_sprinting",
"condition": "!q.in_air && q.has_entity ? q.is_sprinting : 0.0",
"animations": [
"q.bedrock('heracross', 'ground_run')",
{
@@ -5,7 +5,8 @@
"profileTranslation": [0, 0.46, 0],
"rootBone": "mudkip",
"animations": {
"cry": "q.bedrock_stateful('mudkip', 'cry')"
"cry": "q.bedrock_stateful('mudkip', 'cry')",
"recoil": "q.bedrock_stateful('mudkip', 'recoil')"
},
"poses": {
"standing": {
@@ -5,7 +5,8 @@
"profileTranslation": [0, 0.65, 0],
"rootBone": "marshtomp",
"animations": {
"cry": "q.bedrock_stateful('marshtomp', 'cry')"
"cry": "q.bedrock_stateful('marshtomp', 'cry')",
"recoil": "q.bedrock_stateful('marshtomp', 'recoil')"
},
"poses": {
"standing": {
@@ -5,7 +5,8 @@
"profileTranslation": [0, 0.96, 0],
"rootBone": "swampert",
"animations": {
"cry": "q.bedrock_stateful('swampert', 'cry')"
"cry": "q.bedrock_stateful('swampert', 'cry')",
"recoil": "q.bedrock_stateful('swampert', 'recoil')"
},
"poses": {
"standing": {
@@ -1,8 +1,16 @@
{
"portraitScale": 2.48,
"portraitTranslation": [-0.33, -0.93, 0],
"portraitTranslation": [
-0.33,
-0.93,
0
],
"profileScale": 0.7,
"profileTranslation": [0.02, 0.76, 0],
"profileTranslation": [
0.02,
0.76,
0
],
"rootBone": "rufflet",
"animations": {
"cry": "q.bedrock_stateful('rufflet', 'cry')",
@@ -10,7 +18,13 @@
},
"poses": {
"standing": {
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"poseTypes": [
"STAND",
"NONE",
"PORTRAIT",
"PROFILE"
],
"isBattle": false,
"animations": [
"q.look('head')",
"q.bedrock('rufflet', 'ground_idle')"
@@ -22,7 +36,10 @@
]
},
"walking": {
"poseTypes": ["WALK", "SWIM"],
"poseTypes": [
"WALK",
"SWIM"
],
"animations": [
"q.look('head')",
"q.bedrock('rufflet', 'ground_walk')"
@@ -34,7 +51,9 @@
]
},
"hover": {
"poseTypes": ["HOVER"],
"poseTypes": [
"HOVER"
],
"animations": [
"q.pitch_tilt('body', 1)",
"q.look('head')",
@@ -46,7 +65,9 @@
]
},
"fly": {
"poseTypes": ["FLY"],
"poseTypes": [
"FLY"
],
"animations": [
"q.pitch_tilt('body', 1)",
"q.look('head')",
@@ -60,9 +81,6 @@
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('rufflet', 'sleep')"],
"transformTicks": 10
}
@@ -22,6 +22,7 @@
"poses": {
"standing": {
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"isBattle": false,
"animations": [
"q.look('neck1', 1, 1, 5, -5, 10, -10)",
"q.look('neck2', 1, 1, 35, -10, 15, -15)",
@@ -95,9 +96,6 @@
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('braviary', 'sleep')"],
"transformTicks": 10
}
@@ -22,6 +22,7 @@
"poses": {
"standing": {
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"isBattle": false,
"animations": [
"q.look('neck', 1, 1, 3, -20, 10, -10)",
"q.look('neck2', 1, 1, 1, -35, 15, -15)",
@@ -95,9 +96,6 @@
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('braviary_hisuian', 'sleep')"],
"transformTicks": 10
}
@@ -19,9 +19,28 @@
"cry": "q.bedrock_stateful('mudsdale', 'cry')"
},
"poses": {
"standing": {
"poseName": "standing",
"poseTypes": ["STAND", "FLOAT", "NONE", "PORTRAIT", "PROFILE"],
"condition": "q.has_entity ? !q.in_air : 1.0",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
"q.look('head', 0.4, 0.25, 5, -5, 10, -10)",
"q.bedrock('mudsdale', 'ground_idle')",
"q.bedrock_stateful('mudsdale', 'blink')"
],
"transformTicks": 10
},
"sleep": {
"poseName": "sleep",
"poseTypes": ["SLEEP"],
"animations": ["q.bedrock('mudsdale', 'sleep')"]
},
"in-air": {
"poseTypes": ["STAND", "WALK"],
"condition": "q.in_air",
"isBattle": false,
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
@@ -33,37 +52,10 @@
"transformTicks": 5,
"transformToTicks": 5
},
"standing": {
"poseTypes": ["STAND", "FLOAT", "NONE", "PORTRAIT", "PROFILE"],
"condition": "!q.in_air",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
"q.look('head', 0.4, 0.25, 5, -5, 10, -10)",
"q.bedrock('mudsdale', 'ground_idle')",
"q.bedrock_stateful('mudsdale', 'blink')"
],
"transformTicks": 5
},
"run": {
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.in_air && q.is_sprinting",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
"q.look('head', 0.4, 0.25, 5, -5, 10, -10)",
"q.bedrock('mudsdale', 'ground_run')",
"q.bedrock_stateful('mudsdale', 'blink')",
{
"condition": "q.is_ridden && q.has_entity && !q.in_air",
"animation": "q.bedrock('mudsdale', 'ride_ground_run')"
}
],
"transformTicks": 5
},
"walk": {
"poseName": "walk",
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.in_air && !q.is_sprinting",
"condition": "!q.is_sprinting",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
@@ -75,14 +67,23 @@
"animation": "q.bedrock('mudsdale', 'ride_ground_walk')"
}
],
"transformTicks": 5
"transformTicks": 10
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('mudsdale', 'sleep')"]
"run": {
"poseTypes": ["WALK", "SWIM"],
"condition": "q.is_sprinting",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
"q.look('head', 0.4, 0.25, 5, -5, 10, -10)",
"q.bedrock('mudsdale', 'ground_run')",
"q.bedrock_stateful('mudsdale', 'blink')",
{
"condition": "q.is_ridden && q.has_entity && !q.in_air",
"animation": "q.bedrock('mudsdale', 'ride_ground_run')"
}
],
"transformTicks": 10
}
}
}
@@ -38,7 +38,7 @@
"q.bedrock_quirk('ceruledge', 'blink')"
],
"transitions": {
"battle-standing": "q.bedrock_primary('ceruledge', 'battle_intro', q.curve('one'))"
"battle-standing": "q.bedrock_primary('ceruledge', 'battle_intro')q.curve('symmetrical_wide'))"
}
},
"walking": {

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