Compare commits

...
134 changed files with 7167 additions and 1748 deletions
@@ -35,6 +35,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
@JvmField
val DISC_SHELF: BlockEntityType<DiscShelfBlockEntity> = this.create("disc_shelf", BlockEntityType.Builder.of(::DiscShelfBlockEntity, CobblemonBlocks.DISC_SHELF).build(null))
@JvmField
val SILK_THREAD: BlockEntityType<SilkThreadBlockEntity> = this.create("silk_thread", BlockEntityType.Builder.of(::SilkThreadBlockEntity, CobblemonBlocks.SILK_THREAD).build(null))
@JvmField
val BERRY = this.create("berry", BlockEntityType.Builder.of(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
@@ -248,6 +248,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
val BIG_ROOT = this.create("big_root", BigRootBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.BIG_ROOT_SOUNDS)))
@JvmField
val REVIVAL_HERB = this.create("revival_herb", RevivalHerbBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).mapColor(MapColor.PLANT).ignitedByLava().noCollission().instabreak().sound(CobblemonSounds.REVIVAL_HERB_SOUNDS)))
@JvmField
val SILK_THREAD = this.create("silk_thread", SilkThreadBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.WOOL).noCollission().instabreak().sound(SoundType.WOOL)))
@JvmField
val POKE_CAKE = this.create("poke_cake", PokeSnackBlock(BlockBehaviour.Properties.of().forceSolidOn().strength(0.5F).sound(SoundType.WOOL).pushReaction(PushReaction.DESTROY).lightLevel { if (it.getValue(BlockStateProperties.LIT)) 3 else 0 }, false))
@@ -957,7 +959,8 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
Triple(SACCHARINE_FENCE, 5, 20),
Triple(SACCHARINE_FENCE_GATE, 5, 20),
Triple(SACCHARINE_SLAB, 5, 20),
Triple(SACCHARINE_STAIRS, 5, 20)
Triple(SACCHARINE_STAIRS, 5, 20),
Triple(SILK_THREAD, 30, 60)
).onEach{ data -> setFlammable(data.first, data.second, data.third) }
}
@@ -49,6 +49,8 @@ object CobblemonMemories {
@JvmField
val PATH_COOLDOWN = register<Boolean>("path_cooldown")
@JvmField
val POKEMON_SLEEP_SEARCH_FAILED = register<Boolean>("pokemon_sleep_search_failed")
@JvmField
val TARGETED_BATTLE_POKEMON = register<UUID>("targeted_battle_pokemon")
@JvmField
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
@@ -106,4 +108,4 @@ object CobblemonMemories {
memories[id] = memoryModule
return memoryModule
}
}
}
@@ -45,6 +45,7 @@ class FindRestingPlaceTaskConfig : SingleTaskConfig {
behaviourConfigurationContext.addMemories(
CobblemonMemories.PATH_COOLDOWN,
CobblemonMemories.POKEMON_DROWSY,
CobblemonMemories.POKEMON_SLEEPING,
MemoryModuleType.WALK_TARGET
)
behaviourConfigurationContext.addSensors(CobblemonSensors.POKEMON_DROWSY)
@@ -175,4 +175,4 @@ interface TaskConfig {
fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<MoLangConfigVariable>
/** Given the entity in construction, returns a list of tasks. */
fun createTasks(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext): List<BehaviorControl<in LivingEntity>>
}
}
@@ -28,6 +28,7 @@ import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
import com.cobblemon.mod.common.util.cloneFrom
import com.cobblemon.mod.common.util.getStringOrNull
import com.cobblemon.mod.common.util.withQueryValue
import net.minecraft.core.Direction
object PokemonEntityMoLangFunctions : AbstractMoLangFunctionHolder<PokemonEntity>() {
override fun PokemonEntity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
@@ -37,6 +38,10 @@ object PokemonEntityMoLangFunctions : AbstractMoLangFunctionHolder<PokemonEntity
map["in_battle"] = { DoubleValue(pokemonEntity.isBattling) }
map["is_moving"] = { DoubleValue((pokemonEntity.moveControl as? PokemonMoveControl)?.hasWanted() == true) }
map["is_flying"] = { DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
map["cling_face"] = {
val face = pokemonEntity.entityData.get(PokemonEntity.CLINGING_FACE)
StringValue(if (face == Direction.DOWN) "none" else face.getName())
}
map["get_riding_state"] = { params ->
val name = params.getStringOrNull(0)
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
@@ -145,4 +150,4 @@ object PokemonEntityMoLangFunctions : AbstractMoLangFunctionHolder<PokemonEntity
}
return map
}
}
}
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.api.entity.Despawner
import com.cobblemon.mod.common.api.spawning.condition.AreaSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.BasicSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.ClingingSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.FishingSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.GroundedSpawningCondition
import com.cobblemon.mod.common.api.spawning.condition.SeafloorSpawningCondition
@@ -26,14 +27,18 @@ import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
import com.cobblemon.mod.common.api.spawning.position.ClingingSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.FishingSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.GroundedSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.HangingSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.LavafloorSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.SeafloorSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.SubmergedSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.SurfaceSpawnablePosition
import com.cobblemon.mod.common.api.spawning.position.calculators.ClingingSpawnablePositionCalculator
import com.cobblemon.mod.common.api.spawning.position.calculators.GroundedSpawnablePositionCalculator
import com.cobblemon.mod.common.api.spawning.position.calculators.HangingSpawnablePositionCalculator
import com.cobblemon.mod.common.api.spawning.position.calculators.LavafloorSpawnablePositionCalculator
import com.cobblemon.mod.common.api.spawning.position.calculators.SeafloorSpawnablePositionCalculator
import com.cobblemon.mod.common.api.spawning.position.calculators.SpawnablePositionCalculator
@@ -97,6 +102,7 @@ object BestSpawner {
SpawningCondition.register(AreaSpawningCondition.NAME, AreaSpawningCondition::class.java)
SpawningCondition.register(SubmergedSpawningCondition.NAME, SubmergedSpawningCondition::class.java)
SpawningCondition.register(GroundedSpawningCondition.NAME, GroundedSpawningCondition::class.java)
SpawningCondition.register(ClingingSpawningCondition.NAME, ClingingSpawningCondition::class.java)
SpawningCondition.register(SurfaceSpawningCondition.NAME, SurfaceSpawningCondition::class.java)
SpawningCondition.register(SeafloorSpawningCondition.NAME, SeafloorSpawningCondition::class.java)
SpawningCondition.register(FishingSpawningCondition.NAME, FishingSpawningCondition::class.java)
@@ -104,12 +110,16 @@ object BestSpawner {
LOGGER.info("Loaded ${SpawningCondition.conditionTypes.size} spawning condition types.")
SpawnablePositionCalculator.register(GroundedSpawnablePositionCalculator)
SpawnablePositionCalculator.register(HangingSpawnablePositionCalculator)
SpawnablePositionCalculator.register(ClingingSpawnablePositionCalculator)
SpawnablePositionCalculator.register(SeafloorSpawnablePositionCalculator)
SpawnablePositionCalculator.register(LavafloorSpawnablePositionCalculator)
SpawnablePositionCalculator.register(SubmergedSpawnablePositionCalculator)
SpawnablePositionCalculator.register(SurfaceSpawnablePositionCalculator)
SpawnablePosition.register(name = "grounded", clazz = GroundedSpawnablePosition::class.java, defaultCondition = GroundedSpawningCondition.NAME)
SpawnablePosition.register(name = "hanging", clazz = HangingSpawnablePosition::class.java, defaultCondition = AreaSpawningCondition.NAME)
SpawnablePosition.register(name = "clinging", clazz = ClingingSpawnablePosition::class.java, defaultCondition = ClingingSpawningCondition.NAME)
SpawnablePosition.register(name = "seafloor", clazz = SeafloorSpawnablePosition::class.java, defaultCondition = SeafloorSpawningCondition.NAME)
SpawnablePosition.register(name = "lavafloor", clazz = LavafloorSpawnablePosition::class.java, defaultCondition = GroundedSpawningCondition.NAME)
SpawnablePosition.register(name = "submerged", clazz = SubmergedSpawnablePosition::class.java, defaultCondition = SubmergedSpawningCondition.NAME)
@@ -143,4 +153,4 @@ object BestSpawner {
CobblemonSpawnPools.onServerLoad(server)
fishingSpawner = FishingSpawnerFactory.createSharedSpawner()
}
}
}
@@ -65,4 +65,4 @@ class AreaSpawningCondition : AreaTypeSpawningCondition<AreaSpawnablePosition>()
companion object {
const val NAME = "area"
}
}
}
@@ -0,0 +1,64 @@
/*
* 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.spawning.condition
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.spawning.position.ClingingSpawnablePosition
import com.cobblemon.mod.common.util.Merger
import net.minecraft.core.Direction
import net.minecraft.world.level.block.Block
/**
* Base type for a spawning condition that applies to some kind of [ClingingSpawnablePosition].
*
* The [attachedTo] list restricts which blocks the Pokemon may attach to, and [faces] restricts
* which faces of those blocks are usable: "floor", "sides", or "ceiling".
*/
abstract class ClingingTypeSpawningCondition<T : ClingingSpawnablePosition> : AreaTypeSpawningCondition<T>() {
var attachedTo: MutableList<RegistryLikeCondition<Block>>? = null
var faces: MutableList<String>? = null
override fun fits(spawnablePosition: T): Boolean {
if (!super.fits(spawnablePosition)) return false
return spawnablePosition.attachments.keys.any { allowsAttachment(spawnablePosition, it) }
}
fun allowsAttachment(spawnablePosition: ClingingSpawnablePosition, direction: Direction): Boolean {
if (faces != null && faces!!.none { faceMatches(it, direction) }) return false
if (attachedTo != null && attachedTo!!.none { it.fits(spawnablePosition.attachmentHolder(direction)) }) return false
return true
}
private fun faceMatches(face: String, direction: Direction): Boolean = when (face.lowercase()) {
"sides" -> direction.axis.isHorizontal
"floor", "top" -> direction == Direction.DOWN
"ceiling", "bottom" -> direction == Direction.UP
else -> false
}
override fun copyFrom(other: SpawningCondition<*>, merger: Merger) {
super.copyFrom(other, merger)
if (other is ClingingTypeSpawningCondition) {
attachedTo = merger.merge(attachedTo, other.attachedTo)?.toMutableList()
faces = merger.merge(faces, other.faces)?.toMutableList()
}
}
override fun isValid(): Boolean {
val containsNullValues = attachedTo != null && attachedTo!!.any { it == null }
return super.isValid() && !containsNullValues
}
}
class ClingingSpawningCondition : ClingingTypeSpawningCondition<ClingingSpawnablePosition>() {
override fun spawnablePositionClass() = ClingingSpawnablePosition::class.java
companion object {
const val NAME = "clinging"
}
}
@@ -85,4 +85,4 @@ open class AreaSpawnablePosition(
return true
}
}
}
@@ -8,13 +8,22 @@
package com.cobblemon.mod.common.api.spawning.position
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.spawning.SpawningZone
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
import com.cobblemon.mod.common.api.spawning.condition.ClingingTypeSpawningCondition
import com.cobblemon.mod.common.api.spawning.influence.SpawningInfluence
import com.cobblemon.mod.common.block.SilkThreadBlock
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.blockRegistry
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.Holder
import net.minecraft.world.entity.Entity
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.level.EmptyBlockGetter
import net.minecraft.tags.FluidTags
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
@@ -61,6 +70,179 @@ open class GroundedSpawnablePosition(
zone: SpawningZone
) : FlooredSpawnablePosition(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, zone)
/**
* A spawnable position for Pokemon that hang beneath leaves from a column of [SilkThreadBlock]s.
*/
open class HangingSpawnablePosition(
cause: SpawnCause,
world: ServerLevel,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
nearbyBlocks: List<BlockState>,
zone: SpawningZone
) : AreaSpawnablePosition(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, zone) {
override fun postFilter(detail: SpawnDetail): Boolean {
val sizeX = detail.width.takeIf { it > 0 } ?: 1
val sizeY = detail.height.takeIf { it > 0 } ?: 1
if (sizeX <= 1 && sizeY <= 1) return true
val monPos = position.above()
val anchorOffset = (1..SilkThreadBlock.MAX_LENGTH).firstOrNull { offset ->
SilkThreadBlock.isValidAnchor(zone.getBlockState(monPos.above(offset)))
} ?: return false
val anchorY = monPos.y + anchorOffset
val radius = sizeX / 2 + 1
val mutable = BlockPos.MutableBlockPos()
for (x in (position.x - radius)..(position.x + radius)) {
for (z in (position.z - radius)..(position.z + radius)) {
if (!SilkThreadBlock.isValidAnchor(zone.getBlockState(mutable.set(x, anchorY, z)))) {
return false
}
for (y in (anchorY - sizeY) until anchorY) {
if (zone.getBlockState(mutable.set(x, y, z)).isSolid) {
return false
}
}
}
}
return true
}
override fun afterSpawn(action: SpawnAction<*>, entity: Entity) {
super.afterSpawn(action, entity)
if (entity !is PokemonEntity || !entity.pokemon.isWild()) return
if (entity.behaviour.hanging.usesThread) {
if (placeThreadColumn(entity.blockPosition())) {
entity.startHangingFromThread()
}
} else {
snapToAnchor(entity)
}
}
private fun snapToAnchor(entity: PokemonEntity) {
val monPos = entity.blockPosition()
val anchorOffset = (1..SilkThreadBlock.MAX_LENGTH).firstOrNull { offset ->
SilkThreadBlock.isValidAnchor(world.getBlockState(monPos.above(offset)))
} ?: return
val anchor = monPos.above(anchorOffset)
entity.setPos(monPos.x + 0.5, anchor.y - entity.bbHeight + entity.behaviour.hanging.yOffset, monPos.z + 0.5)
entity.startHangingFromThread()
}
// we need to place the super special thread block for our hanging boys for **immersion**
private fun placeThreadColumn(monPos: BlockPos): Boolean {
val anchorOffset = (1..SilkThreadBlock.MAX_LENGTH).firstOrNull { offset ->
SilkThreadBlock.isValidAnchor(world.getBlockState(monPos.above(offset)))
} ?: return false
for (offset in (anchorOffset - 1) downTo 0) {
val pos = monPos.above(offset)
if (world.getBlockState(pos).isAir) {
world.setBlockAndUpdate(pos, CobblemonBlocks.SILK_THREAD.defaultBlockState())
}
}
return world.getBlockState(monPos).`is`(CobblemonBlocks.SILK_THREAD)
}
}
/**
* A spawnable position for Pokemon that cling to a face of an adjacent block without gravity.
* The [attachments] map holds every neighbouring block, keyed by the direction from the
* Pokemon towards that block. This can be used for us making it so cocoon mons spawn clung
* to surfaces and maybe allow for some mons like monkeys or spiders / worms to spawn on the
* sides of logs or caves
*/
open class ClingingSpawnablePosition(
cause: SpawnCause,
world: ServerLevel,
position: BlockPos,
light: Int,
skyLight: Int,
canSeeSky: Boolean,
influences: MutableList<SpawningInfluence>,
height: Int,
nearbyBlocks: List<BlockState>,
zone: SpawningZone,
val attachments: Map<Direction, BlockState>
) : AreaSpawnablePosition(cause, world, position, light, skyLight, canSeeSky, influences, height, nearbyBlocks, zone) {
fun attachmentHolder(direction: Direction): Holder<Block> =
world.blockRegistry.wrapAsHolder(attachments.getValue(direction).block)
override fun postFilter(detail: SpawnDetail): Boolean {
val sizeX = detail.width.takeIf { it > 0 } ?: 1
val sizeY = detail.height.takeIf { it > 0 } ?: 1
if (sizeX <= 1 && sizeY <= 1) return true
return attachments.keys.any { hasFootprintSpace(it, sizeX, sizeY) }
}
// attempt at trying to make sure it has space for the mon
private fun hasFootprintSpace(face: Direction, sizeX: Int, sizeY: Int): Boolean {
val monPos = position.above()
val mutable = BlockPos.MutableBlockPos()
if (face == Direction.UP) {
val radius = sizeX / 2 + 1
val ceilingY = monPos.y + 1
for (x in (monPos.x - radius)..(monPos.x + radius)) {
for (z in (monPos.z - radius)..(monPos.z + radius)) {
val ceilingState = zone.getBlockState(mutable.set(x, ceilingY, z))
if (!ceilingState.isFaceSturdy(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, Direction.DOWN)) {
return false
}
for (y in (ceilingY - sizeY) until ceilingY) {
if (zone.getBlockState(mutable.set(x, y, z)).isSolid) {
return false
}
}
}
}
return true
}
if (!face.axis.isHorizontal) return false
val along = face.clockWise
val radius = sizeX / 2
for (a in -radius..radius) {
for (up in 0 until sizeX) {
val wallPos = monPos.relative(face).relative(along, a).above(up)
if (!zone.getBlockState(mutable.set(wallPos)).isFaceSturdy(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, face.opposite)) {
return false
}
for (depth in 0 until sizeY) {
val bodyPos = wallPos.relative(face.opposite, depth + 1)
if (zone.getBlockState(mutable.set(bodyPos)).isSolid) {
return false
}
}
}
}
return true
}
override fun afterSpawn(action: SpawnAction<*>, entity: Entity) {
super.afterSpawn(action, entity)
if (entity !is PokemonEntity || !entity.pokemon.isWild()) return
val condition = action.detail.conditions.filterIsInstance<ClingingTypeSpawningCondition<*>>().firstOrNull()
val face = attachments.keys
.filter { condition == null || condition.allowsAttachment(this, it) }
.filter { direction ->
val supportPos = entity.blockPosition().relative(direction)
val state = world.getBlockState(supportPos)
state.isFaceSturdy(world, supportPos, direction.opposite) && entity.canClingTo(direction, state)
}
.randomOrNull()
if (face == null) {
entity.discard()
return
}
entity.startClinging(face)
}
}
/**
* A spawnable position that occurs at the bottom of a body of water.
*
@@ -14,6 +14,10 @@ import com.cobblemon.mod.common.api.spawning.position.calculators.SpawnablePosit
import com.cobblemon.mod.common.api.spawning.position.calculators.SpawnablePositionCalculator.Companion.isLavaCondition
import com.cobblemon.mod.common.api.spawning.position.calculators.SpawnablePositionCalculator.Companion.isSolidCondition
import com.cobblemon.mod.common.api.spawning.position.calculators.SpawnablePositionCalculator.Companion.isWaterCondition
import com.cobblemon.mod.common.block.SilkThreadBlock
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.world.level.EmptyBlockGetter
import net.minecraft.world.level.block.state.BlockState
/**
@@ -65,6 +69,84 @@ object GroundedSpawnablePositionCalculator : FlooredSpawnablePositionCalculator<
}
}
/**
* The spawnable position calculator used for [HangingSpawnablePosition]s. Requires an air pocket
* beneath leaves, with at most [SilkThreadBlock.MAX_LENGTH] air blocks of thread gap between them.
* SilkThreadBlock currently only accepts leaves.... but maybe if we find other mons that hang from
* string we can expand it to a tag json (might maybe it should be anyways....) or expand it to a
* system where things can hang without string and use this same method (like bats maybe)
*/
object HangingSpawnablePositionCalculator : AreaSpawnablePositionCalculator<HangingSpawnablePosition> {
override val name = "hanging"
override fun fits(input: AreaSpawningInput): Boolean {
if (!isAirCondition(input.zone.getBlockState(input.position))) return false
if (!isAirCondition(input.zone.getBlockState(input.position.above()))) return false
for (offset in 2..SilkThreadBlock.MAX_LENGTH + 1) {
val state = input.zone.getBlockState(input.position.above(offset))
when {
SilkThreadBlock.isValidAnchor(state) -> return true
!isAirCondition(state) -> return false
}
}
return false
}
override fun calculate(input: AreaSpawningInput): HangingSpawnablePosition {
return HangingSpawnablePosition(
cause = input.cause,
world = input.world,
position = input.position.immutable(),
light = getLight(input),
skyLight = getSkyLight(input),
canSeeSky = getCanSeeSky(input),
influences = input.spawner.copyInfluences(),
height = 1,
zone = input.zone,
nearbyBlocks = getNearbyBlocks(input)
)
}
}
/**
* The spawnable position calculator used for [ClingingSpawnablePosition]s. Requires an air block
* for the Pokemon with at least one solid neighbouring block the mon is allowed to attach to
*/
object ClingingSpawnablePositionCalculator : AreaSpawnablePositionCalculator<ClingingSpawnablePosition> {
override val name = "clinging"
override fun fits(input: AreaSpawningInput): Boolean {
if (!isAirCondition(input.zone.getBlockState(input.position.above()))) return false
return findAttachments(input).isNotEmpty()
}
override fun calculate(input: AreaSpawningInput): ClingingSpawnablePosition {
return ClingingSpawnablePosition(
cause = input.cause,
world = input.world,
position = input.position.immutable(),
light = getLight(input),
skyLight = getSkyLight(input),
canSeeSky = getCanSeeSky(input),
influences = input.spawner.copyInfluences(),
height = 1,
zone = input.zone,
nearbyBlocks = getNearbyBlocks(input),
attachments = findAttachments(input)
)
}
private fun findAttachments(input: AreaSpawningInput): Map<Direction, BlockState> {
val monPos = input.position.above()
return Direction.entries
.map { it to input.zone.getBlockState(monPos.relative(it)) }
.filter { (direction, state) ->
isSolidCondition(state) && state.isFaceSturdy(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, direction.opposite)
}
.toMap()
}
}
/**
* The spawnable position calculator used for [SeafloorSpawnablePosition]s. Requires a solid block below it and
* water blocks in its surroundings.
@@ -0,0 +1,90 @@
/*
* 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 com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.block.entity.SilkThreadBlockEntity
import com.mojang.serialization.MapCodec
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerLevel
import net.minecraft.tags.BlockTags
import net.minecraft.tags.TagKey
import net.minecraft.util.RandomSource
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.projectile.Projectile
import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.Level
import net.minecraft.world.level.LevelAccessor
import net.minecraft.world.level.LevelReader
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.RenderShape
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.shapes.CollisionContext
import net.minecraft.world.phys.shapes.VoxelShape
/**
* A thin strand of silk anchored to leaves, placed when a Pokemon spawns hanging from a tree.
* Each strand survives only while the block above it is another strand or a valid anchor,
* so breaking any part of the column pops everything below it.
*/
@Suppress("OVERRIDE_DEPRECATION", "DEPRECATION")
class SilkThreadBlock(settings: Properties) : Block(settings), EntityBlock {
override fun newBlockEntity(pos: BlockPos, state: BlockState) = SilkThreadBlockEntity(pos, state)
override fun getRenderShape(state: BlockState): RenderShape = RenderShape.INVISIBLE
override fun getShape(state: BlockState, world: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape = SHAPE
override fun canSurvive(state: BlockState, world: LevelReader, pos: BlockPos) = isSupport(world.getBlockState(pos.above()))
override fun updateShape(
state: BlockState,
direction: Direction,
neighborState: BlockState,
world: LevelAccessor,
pos: BlockPos,
neighborPos: BlockPos
): BlockState {
if (direction == Direction.UP && !isSupport(neighborState)) {
world.scheduleTick(pos, this, 1)
}
return super.updateShape(state, direction, neighborState, world, pos, neighborPos)
}
override fun tick(state: BlockState, world: ServerLevel, pos: BlockPos, random: RandomSource) {
if (!state.canSurvive(world, pos)) {
world.destroyBlock(pos, true)
}
}
override fun entityInside(state: BlockState, world: Level, pos: BlockPos, entity: Entity) {
if (entity is Projectile && !world.isClientSide) {
world.destroyBlock(pos, true, entity)
}
}
override fun codec(): MapCodec<out Block> = CODEC
companion object {
val CODEC = simpleCodec(::SilkThreadBlock)
const val MAX_LENGTH = 2
private val COMMON_LEAVES = TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath("c", "leaves"))
private val SHAPE = box(7.0, 0.0, 7.0, 9.0, 16.0, 9.0)
fun isValidAnchor(state: BlockState) = state.`is`(BlockTags.LEAVES) || state.`is`(COMMON_LEAVES)
fun isSupport(state: BlockState) = state.`is`(CobblemonBlocks.SILK_THREAD) || isValidAnchor(state)
}
}
@@ -0,0 +1,16 @@
/*
* 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.entity
import com.cobblemon.mod.common.CobblemonBlockEntities
import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
class SilkThreadBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(CobblemonBlockEntities.SILK_THREAD, pos, state)
@@ -437,6 +437,7 @@ object CobblemonClient {
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.CAMPFIRE, ::CampfireBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.POKE_SNACK, ::PokeSnackBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISC_SHELF, ::DiscShelfBlockEntityRenderer)
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.SILK_THREAD, ::SilkThreadRenderer)
}
private fun registerEntityRenderers() {
@@ -0,0 +1,56 @@
/*
* 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
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexConsumer
import com.mojang.math.Axis
import kotlin.math.min
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.resources.ResourceLocation
import org.joml.Matrix4f
object SilkLineRenderer {
private val TEXTURE = ResourceLocation.withDefaultNamespace("textures/block/tripwire.png")
private const val WIDTH = 0.5F / 16F
private const val V0 = 2F / 16F
private const val V1 = 4F / 16F
private const val SEGMENT_LENGTH = 4F / 16F
fun renderStrip(poseStack: PoseStack, buffer: MultiBufferSource, bottom: Float, top: Float, light: Int) {
poseStack.pushPose()
poseStack.mulPose(Axis.YP.rotationDegrees(-Minecraft.getInstance().gameRenderer.mainCamera.yRot))
val consumer = buffer.getBuffer(RenderType.entityCutoutNoCull(TEXTURE))
val matrix = poseStack.last().pose()
val half = WIDTH / 2
var segmentStart = bottom
while (segmentStart < top) {
val segmentEnd = min(segmentStart + SEGMENT_LENGTH, top)
val u = (segmentEnd - segmentStart) / SEGMENT_LENGTH
vertex(consumer, matrix, -half, segmentStart, 0F, V0, light)
vertex(consumer, matrix, -half, segmentEnd, u, V0, light)
vertex(consumer, matrix, half, segmentEnd, u, V1, light)
vertex(consumer, matrix, half, segmentStart, 0F, V1, light)
segmentStart = segmentEnd
}
poseStack.popPose()
}
private fun vertex(consumer: VertexConsumer, matrix: Matrix4f, x: Float, y: Float, u: Float, v: Float, light: Int) {
consumer.addVertex(matrix, x, y, 0F)
.setColor(255, 255, 255, 255)
.setUv(u, v)
.setOverlay(OverlayTexture.NO_OVERLAY)
.setLight(light)
.setNormal(0F, 1F, 0F)
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.block
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.block.entity.SilkThreadBlockEntity
import com.cobblemon.mod.common.client.render.SilkLineRenderer
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.mojang.blaze3d.vertex.PoseStack
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
import net.minecraft.core.BlockPos
import net.minecraft.world.level.Level
import net.minecraft.world.phys.AABB
class SilkThreadRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<SilkThreadBlockEntity> {
override fun render(
entity: SilkThreadBlockEntity,
partialTicks: Float,
poseStack: PoseStack,
buffer: MultiBufferSource,
light: Int,
overlay: Int
) {
val world = entity.level ?: return
val pos = entity.blockPos
val bottom = if (world.getBlockState(pos.below()).`is`(CobblemonBlocks.SILK_THREAD)) 0F else findHangingMonCentre(world, pos)
poseStack.pushPose()
poseStack.translate(0.5, 0.0, 0.5)
SilkLineRenderer.renderStrip(poseStack, buffer, bottom, 1F, light)
poseStack.popPose()
}
private fun findHangingMonCentre(world: Level, pos: BlockPos): Float {
val mon = world.getEntitiesOfClass(PokemonEntity::class.java, AABB(pos).expandTowards(0.0, -1.0, 0.0))
.firstOrNull { it.getCurrentPoseType() == PoseType.HANG }
?: return 0F
return (mon.y + mon.bbHeight / 2.0 - pos.y).toFloat()
}
}
@@ -569,7 +569,19 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
* If none exists, return the first pose. Only possible with bad configuration, though.
*/
fun getFirstSuitablePose(state: PosableState, poseType: PoseType?): Pose {
return poses.values.firstOrNull { (poseType == null || poseType in it.poseTypes) && it.isSuitable(state) } ?: poses.values.first()
val exact = poses.values.firstOrNull { (poseType == null || poseType in it.poseTypes) && it.isSuitable(state) }
if (exact != null) {
return exact
}
// Clinging mons without a dedicated pose use their ground idle, which the renderer
// rotates against the surface, rather than whatever pose happens to be first.
if (poseType == PoseType.CLING || poseType == PoseType.CLING_CEILING) {
val standing = poses.values.firstOrNull { PoseType.STAND in it.poseTypes && it.isSuitable(state) }
if (standing != null) {
return standing
}
}
return poses.values.first()
}
/**
@@ -46,6 +46,7 @@ import net.minecraft.client.Minecraft
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.commands.arguments.item.ItemParser
import net.minecraft.core.Direction
import net.minecraft.sounds.SoundEvent
import net.minecraft.world.entity.Entity
import net.minecraft.world.item.ItemStack
@@ -274,6 +275,12 @@ abstract class PosableState : Schedulable {
.addFunction("current_aspects") { ArrayStruct(currentAspects.mapIndexed { index, s -> "$index" to StringValue(s)}.toMap())}
.addFunction("has_aspect") { params -> DoubleValue(params.get<MoValue>(0).asString() in currentAspects) }
.addFunction("has_entity") { DoubleValue(getEntity() != null) }
.addFunction("entity_id") { DoubleValue(getEntity()?.id?.toDouble() ?: 0.0) }
.addFunction("cling_face") {
val pokemon = getEntity() as? PokemonEntity ?: return@addFunction StringValue("none")
val face = pokemon.entityData.get(PokemonEntity.CLINGING_FACE)
StringValue(if (face == Direction.DOWN) "none" else face.getName())
}
.addFunction("pose") { StringValue(currentPose ?: "") }
.addFunction("sound") { params ->
if (params.get<MoValue>(0) !is StringValue) {
@@ -37,10 +37,25 @@ class MetapodModel(root: ModelPart) : PokemonPosableModel(root) {
animations = arrayOf(bedrock("metapod", "sleep"))
)
registerPose(
poseType = PoseType.HANG,
animations = arrayOf(bedrock("metapod", "hang"))
)
registerPose(
poseType = PoseType.CLING,
animations = arrayOf(bedrock("metapod", "cling_side"))
)
registerPose(
poseType = PoseType.CLING_CEILING,
animations = arrayOf(bedrock("metapod", "cling_ceiling"))
)
standing = registerPose(
poseName = "standing",
quirks = arrayOf(blink),
poseTypes = ALL_POSES - PoseType.SLEEP,
poseTypes = ALL_POSES - PoseType.SLEEP - PoseType.HANG - PoseType.CLING - PoseType.CLING_CEILING,
animations = arrayOf(bedrock("metapod", "ground_idle"))
)
}
@@ -31,6 +31,7 @@ import com.cobblemon.mod.common.client.render.renderBeaconBeam
import com.cobblemon.mod.common.client.settings.ServerSettings
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PosableEntity
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -54,6 +55,7 @@ import net.minecraft.client.renderer.entity.EntityRendererProvider
import net.minecraft.client.renderer.entity.ItemRenderer
import net.minecraft.client.renderer.entity.MobRenderer
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.core.Direction
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.Style
@@ -303,6 +305,30 @@ class PokemonRenderer(
pPoseStack.scale(scale, scale, scale)
}
override fun setupRotations(entity: PokemonEntity, poseStack: PoseStack, bob: Float, yBodyRot: Float, partialTick: Float, scale: Float) {
super.setupRotations(entity, poseStack, bob, yBodyRot, partialTick, scale)
applyDefaultClingRotation(entity, poseStack, yBodyRot)
}
private fun applyDefaultClingRotation(entity: PokemonEntity, poseStack: PoseStack, yBodyRot: Float) {
val poseType = entity.getCurrentPoseType()
if (poseType != PoseType.CLING && poseType != PoseType.CLING_CEILING) return
val matched = model.posableModel.getPose(poseType)
if (matched != null && PoseType.STAND !in matched.poseTypes) return
val pivot = entity.bbHeight / 2.0
if (poseType == PoseType.CLING) {
val face = entity.entityData.get(PokemonEntity.CLINGING_FACE)
if (face.axis.isHorizontal) {
poseStack.mulPose(Axis.YP.rotationDegrees(yBodyRot - face.toYRot()))
}
val wallDistance = 0.5 - entity.behaviour.clinging.xOffset
poseStack.translate(0.0, 0.0, -(wallDistance - pivot))
}
poseStack.translate(0.0, pivot, 0.0)
poseStack.mulPose(Axis.XP.rotationDegrees(if (poseType == PoseType.CLING) 90F else 180F))
poseStack.translate(0.0, -pivot, 0.0)
}
/**
* Renders a beam between the Cobblemon and the target.
*
@@ -529,4 +555,4 @@ class PokemonRenderer(
matrixStack.popPose()
}
}
}
@@ -27,6 +27,12 @@ enum class PoseType {
FLOAT,
SWIM,
GLIDE,
/** A pose for hanging beneath a block surface.... probably only ever with our string block entity idk */
HANG,
/** A pose for clinging to the face of an adjacent block. Maybe we want monke to cling to trees or from leaves */
CLING,
/** A pose for clinging to the underside of a block above, different from thread hanging. */
CLING_CEILING,
/** A pose for rendering on the left shoulder. Pose animations are given the player head yaw, pitch, and ageInTicks. */
SHOULDER_LEFT,
/** A pose for rendering on the right shoulder. Pose animations are given the player head yaw, pitch, and ageInTicks. */
@@ -49,7 +55,7 @@ enum class PoseType {
val UI_POSES = EnumSet.of(PROFILE, PORTRAIT)
val MOVING_POSES = EnumSet.of(WALK, SWIM, FLY)
val STATIONARY_POSES = EnumSet.of(STAND, FLOAT, HOVER)
val NO_GRAV_POSES = EnumSet.of(FLY, HOVER, SWIM)
val NO_GRAV_POSES = EnumSet.of(FLY, HOVER, SWIM, HANG, CLING, CLING_CEILING)
fun identified() : List<ResourceLocation> {
return ALL_POSES.stream()
@@ -13,8 +13,6 @@ import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
import com.cobblemon.mod.common.util.getMemorySafely
import com.cobblemon.mod.common.util.toBlockPos
import com.google.common.collect.ImmutableMap
@@ -57,6 +55,15 @@ class FollowHerdLeaderTask : Behavior<PokemonEntity>(
override fun tick(level: ServerLevel, entity: PokemonEntity, gameTime: Long) {
val leader = leader ?: return
if (entity.isSleepClinging || entity.isSettlingToSleep) {
return // Settled or settling sleepers stay put until they wake on their own
}
// Drowsy followers break off to find a sleeping place
if (entity.brain.getMemorySafely(CobblemonMemories.POKEMON_DROWSY).orElse(false)) {
return
}
if (entity.brain.hasMemoryValue(MemoryModuleType.WALK_TARGET)) {
return // We're busy goin' n' shit
}
@@ -135,16 +142,12 @@ class FollowHerdLeaderTask : Behavior<PokemonEntity>(
)
)
} else if (leader.getCurrentPoseType() == PoseType.SLEEP) {
// Leader is sleeping, if I'm drowsy and can sleep here then I will sleep too.
if (entity.canSleepAt(entity.blockPosition().offset(0, -1, 0)) && entity.brain.getMemorySafely(CobblemonMemories.POKEMON_DROWSY).orElse(false)) {
if (entity.random.nextFloat() < 1 / 40F) {
applySleep(entity)
}
}
} else if (entity.brain.getMemorySafely(CobblemonMemories.POKEMON_SLEEPING).orElse(false)) {
// Leader is awake, so we should be awake too.
if (entity.random.nextFloat() < 1 / 15F) {
removeSleep(entity)
// Leader is sleeping, so followers get drowsy faster and settle via the usual sleep tasks.
if (entity.behaviour.resting.canSleep &&
!entity.brain.getMemorySafely(CobblemonMemories.POKEMON_DROWSY).orElse(false) &&
entity.random.nextFloat() < 1 / 40F
) {
entity.brain.setMemory(CobblemonMemories.POKEMON_DROWSY, true)
}
}
}
@@ -168,11 +171,6 @@ class FollowHerdLeaderTask : Behavior<PokemonEntity>(
return offset
}
fun applySleep(entity: PokemonEntity) {
entity.brain.setMemory(CobblemonMemories.POKEMON_SLEEPING, true)
entity.pokemon.status = PersistentStatusContainer(Statuses.SLEEP)
}
fun removeSleep(entity: PokemonEntity) {
if (entity.brain.hasMemoryValue(CobblemonMemories.POKEMON_SLEEPING)) {
entity.brain.eraseMemory(CobblemonMemories.POKEMON_SLEEPING)
@@ -180,6 +178,9 @@ class FollowHerdLeaderTask : Behavior<PokemonEntity>(
if (status != null && status.status == Statuses.SLEEP) {
entity.pokemon.status = null
}
// Without this the woken follower stays in the sleeping activity, where neither the
// wake task (blocked while drowsy) nor the settle task (not registered there) can run.
entity.brain.useDefaultActivity()
}
}
}
@@ -43,6 +43,7 @@ import com.cobblemon.mod.common.api.pokemon.feature.ChoiceSpeciesFeatureProvider
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeature
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
import com.cobblemon.mod.common.api.pokemon.feature.StringSpeciesFeature
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.riding.Rideable
@@ -62,12 +63,14 @@ import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
import com.cobblemon.mod.common.api.scheduling.afterOnServer
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.SpawnCause
import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.BagItems
import com.cobblemon.mod.common.battles.BattleBuilder
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.battles.SuccessfulBattleStart
import com.cobblemon.mod.common.block.SilkThreadBlock
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
import com.cobblemon.mod.common.client.MountedCameraTypeHandler
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
@@ -78,6 +81,7 @@ import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.entity.pokeball.EmptyPokeBallEntity
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
import com.cobblemon.mod.common.entity.pokemon.ai.SleepDebug
import com.cobblemon.mod.common.entity.pokemon.ai.sensors.PokemonItemSensor
import com.cobblemon.mod.common.entity.pokemon.effects.EffectTracker
import com.cobblemon.mod.common.entity.pokemon.effects.IllusionEffect
@@ -212,6 +216,7 @@ open class PokemonEntity(
@JvmStatic val FREEZE_FRAME = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.FLOAT)
@JvmStatic val CAUGHT_BALL = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.STRING)
@JvmStatic val EVOLUTION_STARTED = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.BOOLEAN)
@JvmStatic val CLINGING_FACE = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.DIRECTION)
@JvmStatic var SHOWN_HELD_ITEM = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.ITEM_STACK)
@JvmStatic var RIDE_BOOSTS = SynchedEntityData.defineId(PokemonEntity::class.java, RideBoostsDataSerializer)
@JvmStatic var RIDE_STAMINA = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.FLOAT)
@@ -221,6 +226,7 @@ open class PokemonEntity(
const val BATTLE_LOCK = "battle"
const val EVOLUTION_LOCK = "evolving"
const val CLING_SPACE_BLOCKS = 2
const val FALL_DAMAGE_MULT_FLYINGTYPE = 0.5f
const val FALL_DAMAGE_MULT_MOVEMENT_FLY = 0.2f
@@ -423,6 +429,14 @@ open class PokemonEntity(
var tickSpawned = 0
var isHangingFromThread = false
var clingingFace: Direction? = null
var isSleepClinging = false
var isSettlingToSleep = false
var occupiedSeats = mutableMapOf<Seat, Entity>()
init {
@@ -462,6 +476,7 @@ open class PokemonEntity(
builder.define(FREEZE_FRAME, -1F)
builder.define(CAUGHT_BALL, "")
builder.define(EVOLUTION_STARTED, false)
builder.define(CLINGING_FACE, Direction.DOWN)
builder.define(SHOWN_HELD_ITEM, ItemStack.EMPTY)
builder.define(RIDE_BOOSTS, emptyMap())
builder.define(RIDE_STAMINA, 1F)
@@ -701,6 +716,13 @@ open class PokemonEntity(
evolutionEntity!!.setPos(pokemon.entity!!.x, pokemon.entity!!.y, pokemon.entity!!.z)
pokemon.entity!!.navigation.stop()
}
if (!level().isClientSide) {
tickThreadHanging()
tickClinging()
if (tickCount % 20 == 0) {
SleepDebug.status(this)
}
}
delegate.tick(this)
ticksLived++
@@ -943,6 +965,13 @@ open class PokemonEntity(
if (!enablePoseTypeRecalculation) {
nbt.putBoolean(DataKeys.POKEMON_RECALCULATE_POSE, enablePoseTypeRecalculation)
}
if (isHangingFromThread) {
nbt.putBoolean(DataKeys.POKEMON_HANGING_FROM_THREAD, true)
}
clingingFace?.let { nbt.putByte(DataKeys.POKEMON_CLINGING_FACE, it.get3DDataValue().toByte()) }
if (isSleepClinging) {
nbt.putBoolean(DataKeys.POKEMON_SLEEP_CLINGING, true)
}
val dataResult = this.brain.serializeStart(NbtOps.INSTANCE)
dataResult.resultOrPartial(::error).ifPresent { brain ->
nbt.put("Brain", brain)
@@ -1036,6 +1065,20 @@ open class PokemonEntity(
if (nbt.contains(DataKeys.POKEMON_COUNTS_TOWARDS_SPAWN_CAP)) {
countsTowardsSpawnCap = nbt.getBoolean(DataKeys.POKEMON_COUNTS_TOWARDS_SPAWN_CAP)
}
isHangingFromThread = nbt.getBoolean(DataKeys.POKEMON_HANGING_FROM_THREAD)
clingingFace = if (nbt.contains(DataKeys.POKEMON_CLINGING_FACE)) {
Direction.from3DDataValue(nbt.getByte(DataKeys.POKEMON_CLINGING_FACE).toInt())
} else {
null
}
entityData.set(CLINGING_FACE, clingingFace ?: Direction.DOWN)
isSleepClinging = nbt.getBoolean(DataKeys.POKEMON_SLEEP_CLINGING)
// The saved pose can be stale for attached mons so try to it from the attachment
when {
isHangingFromThread -> entityData.set(POSE_TYPE, PoseType.HANG)
clingingFace == Direction.UP -> entityData.set(POSE_TYPE, PoseType.CLING_CEILING)
clingingFace?.axis?.isHorizontal == true -> entityData.set(POSE_TYPE, PoseType.CLING)
}
if (nbt.contains(DataKeys.POKEMON_RECALCULATE_POSE)) {
enablePoseTypeRecalculation = nbt.getBoolean(DataKeys.POKEMON_RECALCULATE_POSE)
}
@@ -1341,6 +1384,12 @@ open class PokemonEntity(
override fun hurt(source: DamageSource, amount: Float): Boolean {
return if (super.hurt(source, amount)) {
if (clingingFace != null || isHangingFromThread) {
SleepDebug.log(this, "hurt by ${source.msgId} while attached")
}
releaseFromThread()
releaseFromClinging()
effects.mockEffect?.takeIf { it is IllusionEffect && this.battleId == null }?.end(this)
if (this.health == 0F) {
@@ -1353,6 +1402,172 @@ open class PokemonEntity(
} else false
}
fun startHangingFromThread() {
isHangingFromThread = true
isNoGravity = true
setDeltaMovement(Vec3.ZERO)
navigation.stop()
}
fun releaseFromThread() {
if (!isHangingFromThread) return
isHangingFromThread = false
breakThreadColumn()
isNoGravity = false
}
private fun tickThreadHanging() {
if (!isHangingFromThread) return
val isSupported = if (behaviour.hanging.usesThread) {
level().getBlockState(blockPosition()).`is`(CobblemonBlocks.SILK_THREAD)
} else {
hasHangAnchorAbove()
}
if (isEvolving || !isSupported) {
releaseFromThread()
return
}
setDeltaMovement(Vec3.ZERO)
navigation.stop()
brain.eraseMemory(MemoryModuleType.WALK_TARGET)
}
private fun hasHangAnchorAbove(): Boolean {
var pos = blockPosition().above()
repeat(CLING_SPACE_BLOCKS) {
val state = level().getBlockState(pos)
if (!state.isAir) {
return SilkThreadBlock.isValidAnchor(state)
}
pos = pos.above()
}
return false
}
private fun breakThreadColumn() {
val world = level() as? ServerLevel ?: return
var pos = blockPosition()
repeat(SilkThreadBlock.MAX_LENGTH) {
if (world.getBlockState(pos).`is`(CobblemonBlocks.SILK_THREAD)) {
world.destroyBlock(pos, true)
}
pos = pos.above()
}
}
fun startClinging(face: Direction) {
clingingFace = face
entityData.set(CLINGING_FACE, face)
isNoGravity = true
setDeltaMovement(Vec3.ZERO)
navigation.stop()
val column = blockPosition()
val cling = behaviour.clinging
val faceY = findCeilingFaceY()
// Things get a bit weird with mons of different sizes so we try to get the size ratio to make the adjustment right on the clingg
val sizeRatio = bbHeight / (exposedForm.hitbox.height * exposedForm.baseScale)
val newY = if (face == Direction.UP) (faceY ?: column.above().y.toDouble()) - bbHeight + cling.yOffset * sizeRatio else y
SleepDebug.log(this, "startClinging face=$face faceY=$faceY bbHeight=$bbHeight yOffset=${cling.yOffset} sizeRatio=$sizeRatio newY=$newY fromY=$y")
setPos(
column.x + 0.5 + face.stepX * cling.xOffset,
newY,
column.z + 0.5 + face.stepZ * cling.xOffset
)
faceClingedBlock(face)
}
/** The block above the feet is not the ceiling for mons taller than a block, so the snap
* scans up from the head for the first collision block available */
private fun findCeilingFaceY(): Double? {
var pos = BlockPos.containing(x, y + bbHeight, z)
repeat(CLING_SPACE_BLOCKS + 1) {
if (!level().getBlockState(pos).getCollisionShape(level(), pos).isEmpty) {
return pos.y.toDouble()
}
pos = pos.above()
}
return null
}
fun releaseFromClinging() {
if (clingingFace == null) return
clingingFace = null
isSleepClinging = false
entityData.set(CLINGING_FACE, Direction.DOWN)
if (behaviour.moving.fly.canFly) {
setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
} else {
isNoGravity = false
}
}
fun canClingTo(face: Direction, state: BlockState): Boolean {
val cling = behaviour.clinging
val isFaceAllowed = when {
face == Direction.UP -> cling.canClingToCeilings
face.axis.isHorizontal -> cling.canClingToWalls
else -> false
}
if (!isFaceAllowed) return false
return cling.blocks.isEmpty() || cling.blocks.any { it.fits(state.block, level().blockRegistry) }
}
private fun tickClinging() {
val face = clingingFace ?: return
val isSupported = if (face == Direction.UP) {
hasClingCeilingAbove()
} else {
val supportPos = blockPosition().relative(face)
val state = level().getBlockState(supportPos)
state.isFaceSturdy(level(), supportPos, face.opposite) && (isSleepClinging || canClingTo(face, state))
}
val isRoused = !brain.getMemorySafely(CobblemonMemories.POKEMON_DROWSY).orElse(false) &&
pokemon.storeCoordinates.get()?.store !is PartyStore
val isSleepOver = isSleepClinging && (pokemon.status?.status != Statuses.SLEEP || isRoused)
if (isEvolving || !isSupported || isSleepOver) {
SleepDebug.log(this, "released from clinging: supported=$isSupported sleepOver=$isSleepOver roused=$isRoused evolving=$isEvolving")
if (isSleepOver) {
// we want to make sure we clear the sleep from the mon (might happen already somewhere else so this might not be needed)
if (pokemon.status?.status == Statuses.SLEEP) {
pokemon.status = null
}
brain.eraseMemory(CobblemonMemories.POKEMON_SLEEPING)
brain.useDefaultActivity()
}
releaseFromClinging()
return
}
if (isSleepClinging && !brain.getMemorySafely(CobblemonMemories.POKEMON_SLEEPING).orElse(false)) {
brain.setMemory(CobblemonMemories.POKEMON_SLEEPING, true)
brain.setActiveActivityToFirstValid(listOf(CobblemonActivities.POKEMON_SLEEPING_ACTIVITY))
}
setDeltaMovement(Vec3.ZERO)
navigation.stop()
brain.eraseMemory(MemoryModuleType.WALK_TARGET)
faceClingedBlock(face)
}
private fun hasClingCeilingAbove(): Boolean {
var pos = BlockPos.containing(x, y + bbHeight, z)
repeat(CLING_SPACE_BLOCKS) {
val state = level().getBlockState(pos)
if (!state.getCollisionShape(level(), pos).isEmpty) {
if (isSleepClinging) return true
return state.isFaceSturdy(level(), pos, Direction.DOWN) && canClingTo(Direction.UP, state)
}
pos = pos.above()
}
return false
}
private fun faceClingedBlock(face: Direction) {
if (!face.axis.isHorizontal) return
val yaw = face.toYRot()
yRot = yaw
yBodyRot = yaw
yHeadRot = yaw
}
override fun shouldBeSaved(): Boolean {
if (ownerUUID == null && !pokemon.isNPCOwned() && (Cobblemon.config.savePokemonToWorld || isPersistenceRequired)) {
CobblemonEvents.POKEMON_ENTITY_SAVE_TO_WORLD.postThen(PokemonEntitySaveToWorldEvent(this)) {
@@ -1785,6 +2000,10 @@ open class PokemonEntity(
removalObservable.emit(reason)
this.brain.clearMemories()
if (reason.shouldDestroy()) {
releaseFromThread()
}
if (reason.shouldDestroy() && pokemon.tetheringId != null) {
pokemon.tetheringId = null
}
@@ -1975,6 +2194,7 @@ open class PokemonEntity(
}
override fun isPushable(): Boolean {
if (isSettlingToSleep || isHangingFromThread || clingingFace != null) return false
return beamMode != 3 && super.isPushable()
}
@@ -31,6 +31,7 @@ import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
import com.cobblemon.mod.common.util.*
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
import net.minecraft.core.Direction
import net.minecraft.network.chat.Component
import net.minecraft.network.syncher.EntityDataAccessor
import net.minecraft.server.level.ServerLevel
@@ -390,6 +391,9 @@ class PokemonServerDelegate : PokemonSideDelegate {
val poseType = when {
isPassenger -> PoseType.STAND
entity.isHangingFromThread -> PoseType.HANG
entity.clingingFace == Direction.UP -> PoseType.CLING_CEILING
entity.clingingFace?.axis?.isHorizontal == true -> PoseType.CLING
isSleeping -> PoseType.SLEEP
isMoving && isUnderwater -> PoseType.SWIM
isUnderwater -> PoseType.FLOAT
@@ -492,4 +496,4 @@ class PokemonServerDelegate : PokemonSideDelegate {
entity.z + offset.z
)
}
}
}
@@ -8,42 +8,415 @@
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
import com.cobblemon.mod.common.CobblemonActivities
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
import com.cobblemon.mod.common.entity.pokemon.ai.SleepDebug
import com.cobblemon.mod.common.pokemon.ai.SleepPlace
import com.cobblemon.mod.common.pokemon.status.PersistentStatusContainer
import com.cobblemon.mod.common.util.PositionType
import com.cobblemon.mod.common.util.blockRegistry
import com.cobblemon.mod.common.util.canEntityStayAt
import com.cobblemon.mod.common.util.getBlockPositions
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 com.cobblemon.mod.common.util.getMemorySafely
import com.google.common.collect.ImmutableMap
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.server.level.ServerLevel
import net.minecraft.util.Mth
import net.minecraft.world.entity.ai.behavior.Behavior
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.level.EmptyBlockGetter
import net.minecraft.world.level.LightLayer
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
object FindRestingPlaceTask {
fun create(horizontalSearchDistance: Int, verticalSearchDistance: Int): OneShot<PokemonEntity> {
return BehaviorBuilder.create {
it.group(
it.absent(MemoryModuleType.WALK_TARGET),
it.present(CobblemonMemories.POKEMON_DROWSY),
it.absent(CobblemonMemories.PATH_COOLDOWN)
).apply(it) { walkTarget, pokemonDrowsy, restPathCooldown ->
Trigger { world, entity, _ ->
return@Trigger if (it.get(pokemonDrowsy) && entity.pokemon.status?.status != Statuses.SLEEP) {
entity.brain.setMemoryWithExpiry(CobblemonMemories.PATH_COOLDOWN, true, 80)
val position = entity.level()
.getBlockPositions(AABB.ofSize(entity.position(), horizontalSearchDistance.toDouble(), verticalSearchDistance.toDouble(), horizontalSearchDistance.toDouble()))
.filter(entity::canSleepAt)
// .randomOrNull()
.minByOrNull { it.distToCenterSqr(entity.position()) }
if (position != null) {
walkTarget.set(WalkTarget(position.below(), 0.3F, 1))
}
true
} else {
false
class FindRestingPlaceTask(
private val horizontalSearchDistance: Int,
private val verticalSearchDistance: Int
) : Behavior<PokemonEntity>(
ImmutableMap.of(
MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT,
CobblemonMemories.POKEMON_DROWSY, MemoryStatus.VALUE_PRESENT,
CobblemonMemories.PATH_COOLDOWN, MemoryStatus.VALUE_ABSENT
),
600
) {
private var targetPos = BlockPos.ZERO
private var targetFace: Direction? = null
private var targetPlace: SleepPlace? = null
private var stallTicks = 0
private var lastApproachPos = Vec3.ZERO
private var failedSpot: BlockPos? = null
private var failedSpotExpiry = 0L
override fun checkExtraStartConditions(world: ServerLevel, entity: PokemonEntity): Boolean {
if (entity.isBattling || entity.clingingFace != null || entity.isHangingFromThread) return false
if (entity.pokemon.status?.status == Statuses.SLEEP) {
if (world.gameTime % 40 == 0L) SleepDebug.log(entity, "task blocked: already asleep")
return false
}
// Navigation refuses to compute paths for airborne mons that arent flagged as flying so
// the search waits for a pathable moment and looks for valid spots
if (!entity.onGround() && !entity.isInWater && !entity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) return false
if ((world.gameTime + entity.id) % SEARCH_INTERVAL != 0L) return false
val target = findTarget(world, entity)
if (target == null) {
SleepDebug.log(entity, "no resting spot found")
return false
}
SleepDebug.log(entity, "chose spot=${target.first.toShortString()} face=${target.second ?: "ground"}")
targetPos = target.first
targetFace = target.second
return true
}
override fun start(world: ServerLevel, entity: PokemonEntity, time: Long) {
SleepDebug.log(entity, "task start target=${targetPos.toShortString()} face=${targetFace ?: "ground"}")
entity.isSettlingToSleep = true
stallTicks = 0
lastApproachPos = entity.position()
entity.brain.setMemoryWithExpiry(CobblemonMemories.PATH_COOLDOWN, true, 80)
}
override fun canStillUse(world: ServerLevel, entity: PokemonEntity, time: Long): Boolean {
return entity.isSettlingToSleep &&
entity.pokemon.status?.status != Statuses.SLEEP &&
entity.brain.getMemorySafely(CobblemonMemories.POKEMON_DROWSY).orElse(false)
}
override fun tick(world: ServerLevel, entity: PokemonEntity, time: Long) {
if (targetFace == null) {
tickGroundApproach(entity)
return
}
if (targetFace == Direction.UP) {
tickCeilingApproach(world, entity)
return
}
if (!hasArrived(entity)) {
walkTowardsTarget(entity, completionRange = 1)
return
}
entity.brain.eraseMemory(MemoryModuleType.WALK_TARGET)
settleAgainstWall(world, entity)
}
/** Mons will try to get to the air block below the ceiling and if they are large they might need a little shift into it to get the task running */
private fun tickCeilingApproach(world: ServerLevel, entity: PokemonEntity) {
if (!isValidCeiling(world, targetPos.above(), targetPlace) || isSpotClaimed(world, entity, targetPos)) {
SleepDebug.log(entity, "ceiling approach aborted at ${targetPos.toShortString()}: ceiling gone or spot claimed")
entity.isSettlingToSleep = false
return
}
// A mon who can not progress should ideely wait for a bit to check for any new spots
stallTicks = if (entity.position().distanceToSqr(lastApproachPos) < 0.001) stallTicks + 1 else 0
lastApproachPos = entity.position()
if (stallTicks > STALL_GIVE_UP_TICKS) {
SleepDebug.log(entity, "approach stalled, shunning ${targetPos.toShortString()}")
failedSpot = targetPos
failedSpotExpiry = world.gameTime + FAILED_SPOT_MEMORY_TICKS
entity.isSettlingToSleep = false
return
}
val dx = targetPos.x + 0.5 - entity.x
val dz = targetPos.z + 0.5 - entity.z
val horizontalSqr = dx * dx + dz * dz
val isAtColumn = horizontalSqr <= COLUMN_RADIUS_SQR
if (world.gameTime % 10 == 0L) {
SleepDebug.log(entity, "ceiling approach target=${targetPos.toShortString()}" +
" dx=%.2f dz=%.2f headGap=%.2f".format(dx, dz, targetPos.y + 1.0 - (entity.y + entity.bbHeight)) +
" atColumn=$isAtColumn ceilingAboveHead=${isUnderTargetCeiling(world, entity)} navDone=${entity.navigation.isDone}" +
" spotBlock=${world.getBlockState(targetPos).block.name.string}" +
" ceilingBlock=${world.getBlockState(targetPos.above()).block.name.string}" +
" feetPosBlock=${world.getBlockState(hangPos(entity)).block.name.string}")
}
if (isAtColumn && entity.y + entity.bbHeight >= targetPos.y && isUnderTargetCeiling(world, entity)) {
SleepDebug.log(entity, "grabbing ceiling at ${targetPos.toShortString()}")
entity.setDeltaMovement(Vec3.ZERO)
settle(entity, Direction.UP)
return
}
// try to nudge to the air space below the ceiling here, but rather than nudge them we might need to check a radius from the tardet area instead and snap to that location?
// Currently this looks smoother.... but we might need to do more testing.
if (horizontalSqr <= DRIFT_RADIUS_SQR && entity.navigation.isDone) {
if (world.gameTime % 10 == 0L) SleepDebug.log(entity, "nav stalled near column, drifting in")
entity.brain.eraseMemory(MemoryModuleType.WALK_TARGET)
haltSteering(entity)
if (entity.behaviour.moving.fly.canFly) {
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
}
val remaining = targetPos.y + 1.0 - (entity.y + entity.bbHeight)
entity.setDeltaMovement(dx * 0.1, min(0.15, remaining), dz * 0.1)
return
}
walkTowardsTarget(entity, completionRange = 0, pos = hangPos(entity))
}
/** Block position of where our mons feets will be when hanging from and wanting to go towards */
private fun hangPos(entity: PokemonEntity, spot: BlockPos = targetPos): BlockPos =
BlockPos.containing(spot.x + 0.5, spot.y + 1.0 - entity.bbHeight, spot.z + 0.5)
/** Try to get a read on where the head of the mon is based on the target ceiling spot for knowing when to stop */
private fun isUnderTargetCeiling(world: ServerLevel, entity: PokemonEntity): Boolean {
val headPos = BlockPos.containing(entity.x, entity.y + entity.bbHeight, entity.z)
return findCeilingAbove(world, headPos.below(), targetPlace) == targetPos.above()
}
private fun tickGroundApproach(entity: PokemonEntity) {
if (entity.canSleepAt(entity.blockPosition().below()) || entity.blockPosition() == targetPos) {
SleepDebug.log(entity, "ground approach done at ${entity.blockPosition().toShortString()}")
entity.brain.eraseMemory(MemoryModuleType.WALK_TARGET)
entity.isSettlingToSleep = false
return
}
walkTowardsTarget(entity, completionRange = 0)
}
private fun walkTowardsTarget(entity: PokemonEntity, completionRange: Int, pos: BlockPos = targetPos) {
if (!entity.brain.hasMemoryValue(MemoryModuleType.WALK_TARGET)) {
SleepDebug.log(entity, "setting walk target ${pos.toShortString()} range=$completionRange")
entity.brain.setMemory(MemoryModuleType.WALK_TARGET, WalkTarget(pos, WALK_SPEED, completionRange))
}
}
override fun stop(world: ServerLevel, entity: PokemonEntity, time: Long) {
entity.isSettlingToSleep = false
}
private fun hasArrived(entity: PokemonEntity): Boolean {
val dx = targetPos.x + 0.5 - entity.x
val dz = targetPos.z + 0.5 - entity.z
val dy = targetPos.y + 0.5 - entity.y
return dx * dx + dz * dz + dy * dy <= ARRIVAL_DISTANCE_SQR
}
/** The move control keeps steering towards its last wanted position even after the navigation
* stops and it ticks after the brain so we have to stop it otehrwise it overwrites the nudging into placement */
private fun haltSteering(entity: PokemonEntity) {
entity.navigation.stop()
(entity.moveControl as? PokemonMoveControl)?.stop()
}
private fun settleAgainstWall(world: ServerLevel, entity: PokemonEntity) {
val face = targetFace ?: return
val place = targetPlace
if (place == null || !wallFits(world, entity, place, targetPos, face) || isSpotClaimed(world, entity, targetPos, claimSpacing(face))) {
SleepDebug.log(entity, "wall settle aborted at ${targetPos.toShortString()}: wall gone or spot claimed")
entity.isSettlingToSleep = false
return
}
entity.setPos(targetPos.x + 0.5, targetPos.y.toDouble(), targetPos.z + 0.5)
settle(entity, face)
}
private fun settle(entity: PokemonEntity, face: Direction) {
SleepDebug.log(entity, "settled on face=$face at ${targetPos.toShortString()}")
entity.startClinging(face)
entity.isSleepClinging = true
entity.isSettlingToSleep = false
if (entity.pokemon.status?.status != Statuses.SLEEP) {
entity.pokemon.status = PersistentStatusContainer(Statuses.SLEEP)
entity.brain.setMemory(CobblemonMemories.POKEMON_SLEEPING, true)
entity.brain.setActiveActivityToFirstValid(listOf(CobblemonActivities.POKEMON_SLEEPING_ACTIVITY))
}
}
private fun findTarget(world: ServerLevel, entity: PokemonEntity): Pair<BlockPos, Direction?>? {
val searchBox = AABB.ofSize(entity.position(), horizontalSearchDistance.toDouble(), verticalSearchDistance.toDouble(), horizontalSearchDistance.toDouble())
for (place in entity.behaviour.resting.places) {
val found = searchPlace(world, entity, place, searchBox)
if (found != null) {
targetPlace = place
return found
}
}
targetPlace = null
entity.brain.setMemoryWithExpiry(CobblemonMemories.POKEMON_SLEEP_SEARCH_FAILED, true, PLACE_SEARCH_FAILURE_TICKS)
val ground = world.getBlockPositions(searchBox)
.filter(entity::canSleepAt)
.minByOrNull { it.distToCenterSqr(entity.position()) }
return ground?.let { it.above() to null }
}
private fun searchPlace(world: ServerLevel, entity: PokemonEntity, place: SleepPlace, searchBox: AABB): Pair<BlockPos, Direction?>? {
val spots = mutableListOf<Pair<BlockPos, Direction>>()
if (place.allowsCeiling()) spots += ceilingSpots(world, entity, place, searchBox)
if (place.allowsSides()) spots += wallSpots(world, entity, place, searchBox)
if (place.allowsFloor()) spots += floorSpots(world, entity, place, searchBox)
SleepDebug.log(entity, "place faces=${place.faces} spots=${spots.size}")
// try to do some lazy checks on valid spots
var pathChecks = 0
val match = spots
.sortedBy { (spot, _) -> spot.distToCenterSqr(entity.position()) }
.asSequence()
.filter { (spot, face) ->
if (spot == failedSpot && world.gameTime < failedSpotExpiry) return@filter false
val hasBodyRoom = face != Direction.UP || bodyFits(
world, entity, spot.x + 0.5,
spot.y + 1.0 - entity.bbHeight + entity.behaviour.clinging.yOffset, spot.z + 0.5
)
hasBodyRoom && fitsPlaceSpace(world, entity, place, spot) &&
!isSpotClaimed(world, entity, spot, claimSpacing(face))
}
.takeWhile { pathChecks < REACHABILITY_CHECKS }
.firstOrNull { (spot, face) ->
pathChecks++
val navPos = if (face == Direction.UP) hangPos(entity, spot) else spot
val path = entity.navigation.createPath(navPos, 0)
val endPos = path?.endNode?.asBlockPos()
SleepDebug.log(entity, "candidate ${spot.toShortString()} face=$face navPos=${navPos.toShortString()}" +
" path=${path?.let { p -> "${if (p.canReach()) "reaches" else "partial"} end=${endPos?.toShortString()} endDistSqr=${endPos?.distSqr(navPos)}" } ?: "null"}")
path != null
}
return match?.let { (spot, face) -> spot to face.takeUnless { it == Direction.DOWN } }
}
/** Upwawrd scans from each area scan around the mon looking for open air spots with solid
* blocks above them, but ignoring ones below floors stood on to make it have an easier time*/
private fun ceilingSpots(world: ServerLevel, entity: PokemonEntity, place: SleepPlace, searchBox: AABB): List<Pair<BlockPos, Direction>> {
val spots = mutableListOf<Pair<BlockPos, Direction>>()
val feetY = entity.blockPosition().y
val boxTop = Mth.floor(searchBox.maxY)
val pos = BlockPos.MutableBlockPos()
for (x in Mth.floor(searchBox.minX)..Mth.floor(searchBox.maxX)) {
for (z in Mth.floor(searchBox.minZ)..Mth.floor(searchBox.maxZ)) {
var seenAirInBox = false
for (y in Mth.floor(searchBox.minY)..(boxTop + MAX_ASCENT)) {
pos.set(x, y, z)
val state = world.getBlockState(pos)
if (state.getCollisionShape(world, pos).isEmpty) {
if (y <= boxTop && state.isAir) seenAirInBox = true
continue
}
if (seenAirInBox && y >= feetY && isValidCeiling(world, pos, place)) {
spots += BlockPos(x, y - 1, z) to Direction.UP
}
seenAirInBox = false
}
}
}
SleepDebug.log(entity, "ceilings=${spots.size}")
return spots
}
private fun bodyFits(world: ServerLevel, entity: PokemonEntity, centerX: Double, minY: Double, centerZ: Double): Boolean {
val half = entity.bbWidth / 2.0
val box = AABB(centerX - half, minY, centerZ - half, centerX + half, minY + entity.bbHeight, centerZ + half)
return world.noCollision(entity, box)
}
/** Fliers may cling anywhere along a wall but want open air below so they perch above the
* ground so we dont see them clipping, but walkers only cling where they can stand beside the wall.
* Might need tweaked so that we add a check for an air block above too? we will see */
private fun wallSpots(world: ServerLevel, entity: PokemonEntity, place: SleepPlace, searchBox: AABB): List<Pair<BlockPos, Direction>> {
val spots = if (entity.behaviour.moving.fly.canFly) {
world.getBlockPositions(searchBox).filter { pos ->
val below = pos.below()
world.getBlockState(pos).isAir && world.getBlockState(below).getCollisionShape(world, below).isEmpty
}
} else {
val width = ceil(entity.bbWidth).toInt()
val height = ceil(entity.bbHeight).toInt()
world.getBlockPositions(searchBox)
.filter { world.canEntityStayAt(it, width, height, PositionType.LAND) }
.map { it.above() }
}
val xOffset = entity.behaviour.clinging.xOffset
return spots.mapNotNull { spot ->
Direction.Plane.HORIZONTAL.firstOrNull { direction ->
wallFits(world, entity, place, spot, direction) &&
bodyFits(world, entity, spot.x + 0.5 + direction.stepX * xOffset, spot.y.toDouble(), spot.z + 0.5 + direction.stepZ * xOffset)
}?.let { spot to it }
}
}
/** We need to try to make sure the mon will fit on the wall it is attached to and that it is sturdy block */
private fun wallFits(world: ServerLevel, entity: PokemonEntity, place: SleepPlace, spot: BlockPos, direction: Direction): Boolean {
val verticalSpan = ceil(max(entity.bbWidth, entity.bbHeight)).toInt().coerceAtLeast(1)
val horizontalSpan = ceil(entity.bbWidth - 0.2).toInt().coerceAtLeast(1)
val sideways = direction.clockWise
for (up in 0 until verticalSpan) {
for (side in 0 until horizontalSpan) {
val wallPos = spot.above(up).relative(direction).relative(sideways, side - (horizontalSpan - 1) / 2)
val state = world.getBlockState(wallPos)
if (!state.isFaceSturdy(world, wallPos, direction.opposite) || !placeBlockMatches(world, place, state)) {
return false
}
}
}
return true
}
private fun floorSpots(world: ServerLevel, entity: PokemonEntity, place: SleepPlace, searchBox: AABB): List<Pair<BlockPos, Direction>> =
world.getBlockPositions(searchBox)
.filter { entity.canSleepAt(it) && placeBlockMatches(world, place, world.getBlockState(it)) }
.map { it.above() to Direction.DOWN }
private fun fitsPlaceSpace(world: ServerLevel, entity: PokemonEntity, place: SleepPlace, spot: BlockPos): Boolean {
val state = world.getBlockState(spot)
if (place.onlyAir && !state.isAir) return false
val rest = entity.behaviour.resting
val light = place.light ?: rest.light
if (world.getMaxLocalRawBrightness(spot) !in light) return false
val canSeeSky = place.canSeeSky ?: rest.canSeeSky
if (canSeeSky != null && world.canSeeSky(spot.above()) != canSeeSky) return false
val skyLight = place.skyLight ?: rest.skyLight
return skyLight == null || world.lightEngine.getLayerListener(LightLayer.SKY).getLightValue(spot) in skyLight
}
private fun findCeilingAbove(world: ServerLevel, from: BlockPos, place: SleepPlace?): BlockPos? {
for (offset in 1..MAX_ASCENT) {
val pos = from.above(offset)
if (world.getBlockState(pos).getCollisionShape(world, pos).isEmpty) continue
return pos.takeIf { isValidCeiling(world, pos, place) }
}
return null
}
/** A place that whitelists blocks may attach to not sturdy undersides like leaves;
* without a whitelist only sturdy undersides count */
private fun isValidCeiling(world: ServerLevel, pos: BlockPos, place: SleepPlace?): Boolean {
val state = world.getBlockState(pos)
if (state.getCollisionShape(world, pos).isEmpty) return false
if (place != null && place.blocks.isNotEmpty()) return placeBlockMatches(world, place, state)
return state.isFaceSturdy(EmptyBlockGetter.INSTANCE, BlockPos.ZERO, Direction.DOWN)
}
private fun placeBlockMatches(world: ServerLevel, place: SleepPlace, state: BlockState): Boolean =
place.blocks.isEmpty() || place.blocks.any { it.fits(state.block, world.blockRegistry) }
/** Wall clingers keep an air block of spacing so they don't overlap along the same surface;
* ceiling sleepers may pack together. */
private fun claimSpacing(face: Direction) = if (face.axis.isHorizontal) 1.0 else 0.0
private fun isSpotClaimed(world: ServerLevel, entity: PokemonEntity, pos: BlockPos, spacing: Double = 0.0): Boolean {
return world.getEntitiesOfClass(PokemonEntity::class.java, AABB(pos).inflate(spacing)) {
it !== entity && (it.clingingFace != null || it.isSettlingToSleep)
}.isNotEmpty()
}
companion object {
fun create(horizontalSearchDistance: Int, verticalSearchDistance: Int) = FindRestingPlaceTask(horizontalSearchDistance, verticalSearchDistance)
private const val MAX_ASCENT = 20
private const val ARRIVAL_DISTANCE_SQR = 4.0
private const val COLUMN_RADIUS_SQR = 0.25
private const val DRIFT_RADIUS_SQR = 4.0
private const val REACHABILITY_CHECKS = 4
private const val SEARCH_INTERVAL = 20L
private const val STALL_GIVE_UP_TICKS = 60
private const val FAILED_SPOT_MEMORY_TICKS = 1200L
private const val PLACE_SEARCH_FAILURE_TICKS = 100L
private const val WALK_SPEED = 0.35F
}
}
@@ -29,7 +29,11 @@ object GoToSleepTask {
it.registered(CobblemonMemories.POKEMON_DROWSY)
).apply(it) { _, pokemonDrowsy ->
Trigger { _, entity, _ ->
if (entity.isSettlingToSleep || entity.clingingFace != null) return@Trigger false
val hasSleepStatus = entity.pokemon.status?.status === Statuses.SLEEP
val wantsPlace = entity.behaviour.resting.places.isNotEmpty() &&
!entity.brain.hasMemoryValue(CobblemonMemories.POKEMON_SLEEP_SEARCH_FAILED)
if (!hasSleepStatus && wantsPlace) return@Trigger false
if (entity.behaviour.resting.canSleep && ((it.tryGet(pokemonDrowsy).orElse(false) && entity.canSleepAt(entity.blockPosition().below())) || hasSleepStatus)) {
if (!hasSleepStatus) {
if (onlyFromStatus) {
@@ -0,0 +1,30 @@
/*
* 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.pokemon.ai
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import com.cobblemon.mod.common.api.molang.ObjectValue
import net.minecraft.world.level.block.Block
class ClingBehaviour {
val canClingToWalls = false
val canClingToCeilings = false
val blocks = mutableListOf<RegistryLikeCondition<Block>>()
val xOffset = 0.0
val yOffset = 0.0
@Transient
val struct = ObjectValue<ClingBehaviour>(this).also {
it.addFunction("can_cling_to_walls") { DoubleValue(canClingToWalls) }
it.addFunction("can_cling_to_ceilings") { DoubleValue(canClingToCeilings) }
it.addFunction("x_offset") { DoubleValue(xOffset) }
it.addFunction("y_offset") { DoubleValue(yOffset) }
}
}
@@ -26,6 +26,12 @@ class FormPokemonBehaviour {
@SerializedName("resting")
private val _resting: RestBehaviour? = null
@SerializedName("clinging")
private val _clinging: ClingBehaviour? = null
@SerializedName("hanging")
private val _hanging: HangBehaviour? = null
@SerializedName("moving")
private val _moving: MoveBehaviour? = null
@@ -66,6 +72,12 @@ class FormPokemonBehaviour {
val resting: RestBehaviour
get() = _resting ?: parent.resting
val clinging: ClingBehaviour
get() = _clinging ?: parent.clinging
val hanging: HangBehaviour
get() = _hanging ?: parent.hanging
val moving: MoveBehaviour
get() = _moving ?: parent.moving
@@ -105,6 +117,8 @@ class FormPokemonBehaviour {
@Transient
val struct = ObjectValue(this).also {
it.addFunction("resting") { resting.struct }
it.addFunction("clinging") { clinging.struct }
it.addFunction("hanging") { hanging.struct }
it.addFunction("moving") { moving.struct }
it.addFunction("idle") { idle.struct }
it.addFunction("entity_interact") { entityInteract.struct }
@@ -0,0 +1,22 @@
/*
* 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.pokemon.ai
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.api.molang.ObjectValue
class HangBehaviour {
val usesThread = true
val yOffset = 0.0
@Transient
val struct = ObjectValue<HangBehaviour>(this).also {
it.addFunction("uses_thread") { DoubleValue(usesThread) }
}
}
@@ -20,6 +20,8 @@ import net.minecraft.network.RegistryFriendlyByteBuf
*/
open class PokemonBehaviour(
val resting: RestBehaviour = RestBehaviour(),
val clinging: ClingBehaviour = ClingBehaviour(),
val hanging: HangBehaviour = HangBehaviour(),
var moving: MoveBehaviour = MoveBehaviour(),
val idle: IdleBehaviour = IdleBehaviour(),
val fireImmune: Boolean = false,
@@ -36,6 +38,8 @@ open class PokemonBehaviour(
@Transient
val struct = ObjectValue<PokemonBehaviour>(this).also {
it.addFunction("resting") { resting.struct }
it.addFunction("clinging") { clinging.struct }
it.addFunction("hanging") { hanging.struct }
it.addFunction("moving") { moving.struct }
it.addFunction("idle") { idle.struct }
it.addFunction("entity_interact") { entityInteract.struct }
@@ -33,6 +33,7 @@ class RestBehaviour {
val depth = SleepDepth.normal
val canSeeSky: Boolean? = null
val skyLight: IntRange? = null
val places = mutableListOf<SleepPlace>()
val drowsyChance: Float = 1 / 30F // Once per 30 seconds on average. Drowsy sensor runs once per second.
val rouseChance: Float = 1 / 240F // Once every 4 minutes on average. Drowsy sensor runs once per second.
@@ -0,0 +1,25 @@
/*
* 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.pokemon.ai
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
import net.minecraft.world.level.block.Block
class SleepPlace {
val faces = mutableListOf<String>()
val blocks = mutableListOf<RegistryLikeCondition<Block>>()
val onlyAir = false
val light: IntRange? = null
val canSeeSky: Boolean? = null
val skyLight: IntRange? = null
fun allowsFloor() = faces.any { it.equals("floor", true) || it.equals("top", true) }
fun allowsSides() = faces.any { it.equals("sides", true) }
fun allowsCeiling() = faces.any { it.equals("ceiling", true) || it.equals("bottom", true) }
}
@@ -80,6 +80,9 @@ object DataKeys {
const val POKEMON_COUNTS_TOWARDS_SPAWN_CAP = "CountsTowardsSpawnCap"
const val POKEMON_FREEZE_FRAME = "FreezeFrame"
const val POKEMON_RECALCULATE_POSE = "RecalculatePose"
const val POKEMON_HANGING_FROM_THREAD = "HangingFromThread"
const val POKEMON_CLINGING_FACE = "ClingingFace"
const val POKEMON_SLEEP_CLINGING = "SleepClinging"
const val POKEMON_PLATFORM_TYPE = "PlatformType"
const val POKEMON_ORIGINAL_TRAINER = "PokemonOriginalTrainer"
@@ -1,252 +1,634 @@
{
"format_version": "1.8.0",
"animations": {
"animation.metapod.ground_idle": {
"loop": true,
"bones": {
"body": {
"rotation": [
"math.sin(q.anim_time*90*2)*0.5",
0,
"math.clamp(math.sin(q.anim_time*90*4)*0.1,-0.8,0)+math.clamp(math.sin(q.anim_time*90*4)*0.5,0,0.8)+math.sin(q.anim_time*90*2)*0.1"
],
"position": [
0,
"(-math.clamp(math.sin(q.anim_time*90*2)*0.2,-0.1,0)-math.clamp(math.sin(q.anim_time*90*2)*0.2,0,0.1)-math.sin(q.anim_time*90*2)*0.2)*0.1",
0
]
},
"body_segment": {
"rotation": ["-math.clamp(math.sin(q.anim_time*90*2)*0.5,-0.8,0)-math.clamp(math.sin(q.anim_time*90*2)*0.5,0,0.8)-math.sin(q.anim_time*90*2)*0.1", 0, 0]
}
}
},
"animation.metapod.sleep": {
"loop": true,
"bones": {
"body": {
"rotation": [
"5+math.sin(q.anim_time*90*1)*0.25",
0,
"math.clamp(math.sin(q.anim_time*90*2)*0.1,-0.8,0)+math.clamp(math.sin(q.anim_time*90*2)*0.5,0,0.8)+math.sin(q.anim_time*90*1)*0.1"
],
"position": [
0,
"(-math.clamp(math.sin(q.anim_time*90*1)*0.2,-0.1,0)-math.clamp(math.sin(q.anim_time*90*1)*0.2,0,0.1)-math.sin(q.anim_time*90*1)*0.2)*0.1",
-0.5
]
},
"body_segment": {
"rotation": ["-math.clamp(math.sin(q.anim_time*90*1)*0.5,-0.8,0)-math.clamp(math.sin(q.anim_time*90*1)*0.5,0,0.8)-math.sin(q.anim_time*90*1)*0.1", 0, 0]
},
"eyelid_right": {
"position": [-0.1, 0, 0]
},
"eyelid_left": {
"position": [0.1, 0, 0]
}
}
},
"animation.metapod.faint": {
"animation_length": 3,
"bones": {
"body": {
"rotation": {
"0.0": [0, 0, 0],
"0.2917": [4.29, 0, 0],
"0.4583": [10, 0, 0],
"0.625": [32.5, 0, 0],
"0.6667": [30, 0, 0],
"0.7083": [32.5, 0, 0],
"1.5": [32.5, 0, 0],
"1.8333": [30, 0, -26.25],
"2.0": [30, 0, -60],
"2.0833": [30, 0, -97.5],
"2.125": [30, 0, -85],
"2.1667": [30, 0, -90]
},
"position": {
"0.0": [0, 0, 0],
"0.2917": [0, 0.04, -0.43],
"0.4583": [0, 0.1, -1],
"0.625": [0, 0.1, -3.3],
"0.6667": [0, 0.1, -3.1],
"0.7083": [0, 0.1, -3.3],
"1.5": [0, 0.1, -3.3],
"1.8333": [-2.63, 1.03, -3.1],
"1.9583": [-4.65, 0.84, -3.1],
"2.0": [-6, 0.22, -3.1],
"2.0833": [-9, -2.2, -3.1]
}
},
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.5833": [0, 0, 0],
"0.625": [-0.1, 0, 0],
"0.9583": [-0.1, 0, 0],
"1.0": [0, 0, 0],
"1.0833": [0, 0, 0],
"1.125": [-0.1, 0, 0],
"1.2083": [-0.1, 0, 0],
"1.25": [0, 0, 0],
"2.0417": [0, 0, 0],
"2.0833": [-0.1, 0, 0]
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.5833": [0, 0, 0],
"0.625": [0.1, 0, 0],
"0.9583": [0.1, 0, 0],
"1.0": [0, 0, 0],
"1.0833": [0, 0, 0],
"1.125": [0.1, 0, 0],
"1.2083": [0.1, 0, 0],
"1.25": [0, 0, 0],
"2.0417": [0, 0, 0],
"2.0833": [0.1, 0, 0]
}
}
}
},
"animation.metapod.blink": {
"animation_length": 0.16667,
"bones": {
"eyelid_right": {
"position": {
"0.0": [-0.1, 0, 0],
"0.125": [-0.1, 0, 0],
"0.1667": [0, 0, 0]
}
},
"eyelid_left": {
"position": {
"0.0": [0.1, 0, 0],
"0.125": [0.1, 0, 0],
"0.1667": [0, 0, 0]
}
}
}
},
"animation.metapod.cry": {
"animation_length": 1.41667,
"bones": {
"body": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.125": {
"post": [0.24495, 2.5286, -6.33169],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [5.05167, -1.52982, 3.02713],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [0, 2.5, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [0, -2.5, 0],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [0, 2.5, 0],
"lerp_mode": "catmullrom"
},
"0.875": {
"post": [0, -2.5, 0],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
},
"position": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"body_segment": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.125": {
"post": [0.2074, -2.5008, 4.95993],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [-4.81906, 2.96226, -5.45921],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [-0.09209, -0.00633, -0.26004],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [-0.69275, 2.49348, -0.29026],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [0.27379, -2.50469, -0.15728],
"lerp_mode": "catmullrom"
},
"0.875": {
"post": [-0.38046, 2.49075, -0.36995],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
},
"position": [0, 0, 0]
},
"eyelid_right": {
"position": {
"0.0": [0, 0, 0],
"0.0833": [-0.12441, 0.01024, -0.00643],
"0.625": [-0.12441, 0.01024, -0.00643],
"0.75": [0, 0, 0]
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, 0],
"0.0833": [0.09953, -0.00819, 0.00514],
"0.625": [0.09953, -0.00819, 0.00514],
"0.75": [0, 0, 0]
}
}
},
"sound_effects": {
"0.0417": {
"effect": "pokemon.metapod.cry"
}
}
},
"animation.metapod.render": {
"loop": true,
"bones": {
"body": {
"rotation": [-10, 0, 0],
"position": [0, 1, 0]
}
}
}
}
}
"format_version": "1.8.0",
"animations": {
"animation.metapod.ground_idle": {
"loop": true,
"bones": {
"body": {
"rotation": [
"math.sin(q.anim_time*90*2)*0.5",
0,
"math.clamp(math.sin(q.anim_time*90*4)*0.1,-0.8,0)+math.clamp(math.sin(q.anim_time*90*4)*0.5,0,0.8)+math.sin(q.anim_time*90*2)*0.1"
],
"position": [
0,
"(-math.clamp(math.sin(q.anim_time*90*2)*0.2,-0.1,0)-math.clamp(math.sin(q.anim_time*90*2)*0.2,0,0.1)-math.sin(q.anim_time*90*2)*0.2)*0.1",
0
]
},
"body_segment": {
"rotation": [
"-math.clamp(math.sin(q.anim_time*90*2)*0.5,-0.8,0)-math.clamp(math.sin(q.anim_time*90*2)*0.5,0,0.8)-math.sin(q.anim_time*90*2)*0.1",
0,
0
]
}
}
},
"animation.metapod.sleep": {
"loop": true,
"bones": {
"body": {
"rotation": [
"5+math.sin(q.anim_time*90*1)*0.25",
0,
"math.clamp(math.sin(q.anim_time*90*2)*0.1,-0.8,0)+math.clamp(math.sin(q.anim_time*90*2)*0.5,0,0.8)+math.sin(q.anim_time*90*1)*0.1"
],
"position": [
0,
"(-math.clamp(math.sin(q.anim_time*90*1)*0.2,-0.1,0)-math.clamp(math.sin(q.anim_time*90*1)*0.2,0,0.1)-math.sin(q.anim_time*90*1)*0.2)*0.1",
-0.5
]
},
"body_segment": {
"rotation": [
"-math.clamp(math.sin(q.anim_time*90*1)*0.5,-0.8,0)-math.clamp(math.sin(q.anim_time*90*1)*0.5,0,0.8)-math.sin(q.anim_time*90*1)*0.1",
0,
0
]
},
"eyelid_right": {
"position": [
-0.1,
0,
0
]
},
"eyelid_left": {
"position": [
0.1,
0,
0
]
}
}
},
"animation.metapod.faint": {
"animation_length": 3,
"bones": {
"body": {
"rotation": {
"0.0": [
0,
0,
0
],
"0.2917": [
4.29,
0,
0
],
"0.4583": [
10,
0,
0
],
"0.625": [
32.5,
0,
0
],
"0.6667": [
30,
0,
0
],
"0.7083": [
32.5,
0,
0
],
"1.5": [
32.5,
0,
0
],
"1.8333": [
30,
0,
-26.25
],
"2.0": [
30,
0,
-60
],
"2.0833": [
30,
0,
-97.5
],
"2.125": [
30,
0,
-85
],
"2.1667": [
30,
0,
-90
]
},
"position": {
"0.0": [
0,
0,
0
],
"0.2917": [
0,
0.04,
-0.43
],
"0.4583": [
0,
0.1,
-1
],
"0.625": [
0,
0.1,
-3.3
],
"0.6667": [
0,
0.1,
-3.1
],
"0.7083": [
0,
0.1,
-3.3
],
"1.5": [
0,
0.1,
-3.3
],
"1.8333": [
-2.63,
1.03,
-3.1
],
"1.9583": [
-4.65,
0.84,
-3.1
],
"2.0": [
-6,
0.22,
-3.1
],
"2.0833": [
-9,
-2.2,
-3.1
]
}
},
"eyelid_right": {
"position": {
"0.0": [
0,
0,
0
],
"0.5833": [
0,
0,
0
],
"0.625": [
-0.1,
0,
0
],
"0.9583": [
-0.1,
0,
0
],
"1.0": [
0,
0,
0
],
"1.0833": [
0,
0,
0
],
"1.125": [
-0.1,
0,
0
],
"1.2083": [
-0.1,
0,
0
],
"1.25": [
0,
0,
0
],
"2.0417": [
0,
0,
0
],
"2.0833": [
-0.1,
0,
0
]
}
},
"eyelid_left": {
"position": {
"0.0": [
0,
0,
0
],
"0.5833": [
0,
0,
0
],
"0.625": [
0.1,
0,
0
],
"0.9583": [
0.1,
0,
0
],
"1.0": [
0,
0,
0
],
"1.0833": [
0,
0,
0
],
"1.125": [
0.1,
0,
0
],
"1.2083": [
0.1,
0,
0
],
"1.25": [
0,
0,
0
],
"2.0417": [
0,
0,
0
],
"2.0833": [
0.1,
0,
0
]
}
}
}
},
"animation.metapod.blink": {
"animation_length": 0.1667,
"bones": {
"eyelid_right": {
"position": {
"0.0": [
-0.1,
0,
0
],
"0.125": [
-0.1,
0,
0
],
"0.1667": [
0,
0,
0
]
}
},
"eyelid_left": {
"position": {
"0.0": [
0.1,
0,
0
],
"0.125": [
0.1,
0,
0
],
"0.1667": [
0,
0,
0
]
}
}
}
},
"animation.metapod.cry": {
"animation_length": 1.4167,
"bones": {
"body": {
"rotation": {
"0.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.125": {
"post": [
0.24495,
2.5286,
-6.33169
],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [
5.05167,
-1.52982,
3.02713
],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [
0,
2.5,
0
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
0,
-2.5,
0
],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [
0,
2.5,
0
],
"lerp_mode": "catmullrom"
},
"0.875": {
"post": [
0,
-2.5,
0
],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
}
},
"position": {
"0.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
}
}
},
"body_segment": {
"rotation": {
"0.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.125": {
"post": [
0.2074,
-2.5008,
4.95993
],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [
-4.81906,
2.96226,
-5.45921
],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [
-0.09209,
-0.00633,
-0.26004
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
-0.69275,
2.49348,
-0.29026
],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [
0.27379,
-2.50469,
-0.15728
],
"lerp_mode": "catmullrom"
},
"0.875": {
"post": [
-0.38046,
2.49075,
-0.36995
],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
}
},
"position": [
0,
0,
0
]
},
"eyelid_right": {
"position": {
"0.0": [
0,
0,
0
],
"0.0833": [
-0.12441,
0.01024,
-0.00643
],
"0.625": [
-0.12441,
0.01024,
-0.00643
],
"0.75": [
0,
0,
0
]
}
},
"eyelid_left": {
"position": {
"0.0": [
0,
0,
0
],
"0.0833": [
0.09953,
-0.00819,
0.00514
],
"0.625": [
0.09953,
-0.00819,
0.00514
],
"0.75": [
0,
0,
0
]
}
}
},
"sound_effects": {
"0.0417": {
"effect": "pokemon.metapod.cry"
}
}
},
"animation.metapod.render": {
"loop": true,
"bones": {
"body": {
"rotation": [
-10,
0,
0
],
"position": [
0,
1,
0
]
}
}
},
"animation.metapod.cling_side": {
"loop": true,
"bones": {
"body": {
"rotation": [
-77.5,
0,
0
]
}
}
},
"animation.metapod.cling_ceiling": {
"loop": true,
"bones": {
"body": {
"rotation": [
"-35-math.sin(q.anim_time*90*1)*2",
0,
"math.sin(q.anim_time*90*1/2)*2"
],
"position": [
"-math.sin(q.anim_time*90*1/2)*0.5",
"+math.sin(q.anim_time*90*1)*-0.1",
"math.sin(q.anim_time*90*1)*-0.4"
]
}
}
},
"animation.metapod.hang": {
"loop": true,
"bones": {
"body": {
"rotation": [
"-65-math.sin(q.anim_time*90*1)*2",
0,
"math.sin(q.anim_time*90*1/2)*2"
],
"position": [
"-math.sin(q.anim_time*90*1/2)*0.3",
"+math.sin(q.anim_time*90*1)*-0.2",
"1.75+math.sin(q.anim_time*90*1)*-0.3"
]
}
}
}
}
}
@@ -1,312 +1,651 @@
{
"format_version": "1.8.0",
"animations": {
"animation.kakuna.ground_idle": {
"loop": true,
"bones": {
"body": {
"rotation": ["-math.sin(q.anim_time*90*2)*1", 0, "math.sin(q.anim_time*90*2-90)*0.5"],
"position": ["-math.sin(q.anim_time*90*2-90)*-0.1", 0.5, "math.sin(q.anim_time*90*2)*0.2"]
}
}
},
"animation.kakuna.sleep": {
"loop": true,
"bones": {
"body": {
"rotation": ["-math.sin(q.anim_time*90*1-90)*1", 0, "math.sin(q.anim_time*90*1)*0.5"],
"position": ["-math.sin(q.anim_time*90*1)*-0.1", 0.5, "math.sin(q.anim_time*90*1-90)*0.2"]
}
}
},
"animation.kakuna.physical": {
"animation_length": 3,
"bones": {
"body": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": ["-math.sin(q.anim_time*90*3)*-20", 0, "math.cos(q.anim_time*90*3)*-20"],
"lerp_mode": "catmullrom"
},
"0.7917": {
"post": ["-math.sin(q.anim_time*90*3)*-20", 0, "math.cos(q.anim_time*90*3)*-20"],
"lerp_mode": "catmullrom"
},
"1.0417": {
"post": [-16.62939, 7, -11.1114],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [0, 30, -32.5],
"lerp_mode": "catmullrom"
},
"1.2083": {
"post": [43.5061, 41.7947, 7.1679],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [43.47759, 0, 7.65367],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [36.1795, -24.8022, 10.1779],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [8.1692, -24.4369, 32.0742],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": ["-math.cos(q.anim_time*90*2)*20", 0, "math.sin(q.anim_time*90*2)*-20"],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
},
"position": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": ["-math.cos(q.anim_time*90*3)*2.6", "math.sin(q.anim_time*90*3)*0.2", "math.sin(q.anim_time*90*3)*-2.6"],
"lerp_mode": "catmullrom"
},
"0.7917": {
"post": ["-math.cos(q.anim_time*90*3)*2.6", "math.sin(q.anim_time*90*3)*0.2", "math.sin(q.anim_time*90*3)*-2.6"],
"lerp_mode": "catmullrom"
},
"1.0417": {
"post": [-1.44448, -0.16629, 2.16182],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [-3.6, 0, 0],
"lerp_mode": "catmullrom"
},
"1.2083": {
"post": [-2.31, 0.1, -3.81],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [0.99498, 0.18478, -5.40209],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [2.22, 0.2, -4.24],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [3.11, -0.5, -0.9],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": ["-math.sin(q.anim_time*90*2)*2.6", "math.cos(q.anim_time*90*2)*-0.2", "math.cos(q.anim_time*90*2)*2.6"],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
},
"scale": {
"1.125": [1, 1, 1],
"1.2083": [1.2, 1.1, 0.8],
"1.25": [1, 1, 1]
}
}
}
},
"animation.kakuna.faint": {
"animation_length": 3,
"bones": {
"body": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": ["-math.sin(q.anim_time*90*2)*-20", 0, "math.cos(q.anim_time*90*2)*-20"],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": ["-math.sin(q.anim_time*90*2)*-20", 0, "math.cos(q.anim_time*90*2)*-20"],
"lerp_mode": "catmullrom"
},
"1.375": {
"post": ["-19.94-math.sin(q.anim_time*90*32)*1", -0.9, 2.28],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": ["-24.1146-math.sin(q.anim_time*90*32)*1", -5.1806, -9.6237],
"lerp_mode": "catmullrom"
},
"1.75": {
"post": [-48.12, -9.9, -10.88],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [-82.4083, -26.1002, -17.2368],
"lerp_mode": "catmullrom"
},
"2.0417": {
"post": [-102.1119, -24.854, -31.5905],
"lerp_mode": "catmullrom"
},
"2.3333": {
"post": [-99.1014, -23.4505, -14.6775],
"lerp_mode": "catmullrom"
},
"2.6667": {
"post": [-66.3538, -24.159, 6.6861],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [-85.0639, -23.1834, -2.9264],
"lerp_mode": "catmullrom"
}
},
"position": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": ["-math.cos(q.anim_time*90*2)*2.6", "math.sin(q.anim_time*90*2)*0.2", "math.sin(q.anim_time*90*2)*-2.6"],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": ["-math.cos(q.anim_time*90*2)*2.6", "math.sin(q.anim_time*90*2)*0.2", "math.sin(q.anim_time*90*2)*-2.6"],
"lerp_mode": "catmullrom"
},
"1.375": {
"post": [0.3, -0.73, 2.28],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [-1.64, -1.13, 2.77],
"lerp_mode": "catmullrom"
},
"1.625": {
"post": [-1.96, -1.39, 4.06],
"lerp_mode": "catmullrom"
},
"1.7083": {
"post": [-2.19, -2.77, 4.5],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [-3.71, -4.79, 5.06],
"lerp_mode": "catmullrom"
},
"1.9167": {
"post": [-4.94977, -3.02238, 5.61398],
"lerp_mode": "catmullrom"
},
"2.2083": {
"post": [-5.87185, -2.2078, 6.20958],
"lerp_mode": "catmullrom"
},
"2.5": {
"post": [-4.3217, -4.5458, 4.90724],
"lerp_mode": "catmullrom"
},
"2.6667": {
"post": [-3.91, -4.91, 5.01],
"lerp_mode": "catmullrom"
},
"2.75": {
"post": [-3.92405, -4.96563, 5.12418],
"lerp_mode": "catmullrom"
},
"2.9167": {
"post": [-4.24661, -5.20065, 5.11229],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [-4.29542, -5.18509, 5.3042],
"lerp_mode": "catmullrom"
}
}
}
}
},
"animation.kakuna.cry": {
"animation_length": 1,
"bones": {
"body": {
"rotation": {
"0.0": [0, 0, 0],
"0.125": {
"pre": [4.5, 0, 0],
"post": [4.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.3333": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.4167": {
"post": [-0.1296, 2.4461, -3.0023],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [-0.0867, -2.4636, 2.0016],
"lerp_mode": "catmullrom"
},
"0.5833": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.6667": [0, 0, 0]
},
"position": {
"0.0": [0, 0, 0],
"0.125": {
"pre": [0, -0.05, -0.5],
"post": [0, -0.05, -0.5],
"lerp_mode": "catmullrom"
},
"0.3333": {
"post": [0, -0.1, 0.1],
"lerp_mode": "catmullrom"
},
"0.4167": {
"post": [-0.25, -0.08, 0.12],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [0.08, -0.05, 0.08],
"lerp_mode": "catmullrom"
},
"0.5833": {
"post": [0.015, -0.01, 0.02],
"lerp_mode": "catmullrom"
},
"0.6667": [0, 0, 0]
}
}
},
"sound_effects": {
"0.0417": {
"effect": "pokemon.kakuna.cry"
}
}
},
"animation.kakuna.render": {
"loop": true,
"bones": {
"kakuna": {
"rotation": [0, -15, 0]
}
}
}
}
"format_version": "1.8.0",
"animations": {
"animation.kakuna.ground_idle": {
"loop": true,
"bones": {
"body": {
"rotation": [
"-math.sin(q.anim_time*90*2)*1",
0,
"math.sin(q.anim_time*90*2-90)*0.5"
],
"position": [
"-math.sin(q.anim_time*90*2-90)*-0.1",
0.5,
"math.sin(q.anim_time*90*2)*0.2"
]
}
}
},
"animation.kakuna.sleep": {
"loop": true,
"bones": {
"body": {
"rotation": [
"-math.sin(q.anim_time*90*1-90)*1",
0,
"math.sin(q.anim_time*90*1)*0.5"
],
"position": [
"-math.sin(q.anim_time*90*1)*-0.1",
0.5,
"math.sin(q.anim_time*90*1-90)*0.2"
]
}
}
},
"animation.kakuna.physical": {
"animation_length": 3,
"bones": {
"body": {
"rotation": {
"0.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
"-math.sin(q.anim_time*90*3)*-20",
0,
"math.cos(q.anim_time*90*3)*-20"
],
"lerp_mode": "catmullrom"
},
"0.7917": {
"post": [
"-math.sin(q.anim_time*90*3)*-20",
0,
"math.cos(q.anim_time*90*3)*-20"
],
"lerp_mode": "catmullrom"
},
"1.0417": {
"post": [
-16.62939,
7,
-11.1114
],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [
0,
30,
-32.5
],
"lerp_mode": "catmullrom"
},
"1.2083": {
"post": [
43.5061,
41.7947,
7.1679
],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [
43.47759,
0,
7.65367
],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [
36.1795,
-24.8022,
10.1779
],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [
8.1692,
-24.4369,
32.0742
],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": [
"-math.cos(q.anim_time*90*2)*20",
0,
"math.sin(q.anim_time*90*2)*-20"
],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
}
},
"position": {
"0.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
"-math.cos(q.anim_time*90*3)*2.6",
"math.sin(q.anim_time*90*3)*0.2",
"math.sin(q.anim_time*90*3)*-2.6"
],
"lerp_mode": "catmullrom"
},
"0.7917": {
"post": [
"-math.cos(q.anim_time*90*3)*2.6",
"math.sin(q.anim_time*90*3)*0.2",
"math.sin(q.anim_time*90*3)*-2.6"
],
"lerp_mode": "catmullrom"
},
"1.0417": {
"post": [
-1.44448,
-0.16629,
2.16182
],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [
-3.6,
0,
0
],
"lerp_mode": "catmullrom"
},
"1.2083": {
"post": [
-2.31,
0.1,
-3.81
],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [
0.99498,
0.18478,
-5.40209
],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [
2.22,
0.2,
-4.24
],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [
3.11,
-0.5,
-0.9
],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": [
"-math.sin(q.anim_time*90*2)*2.6",
"math.cos(q.anim_time*90*2)*-0.2",
"math.cos(q.anim_time*90*2)*2.6"
],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
}
},
"scale": {
"1.125": [
1,
1,
1
],
"1.2083": [
1.2,
1.1,
0.8
],
"1.25": [
1,
1,
1
]
}
}
}
},
"animation.kakuna.faint": {
"animation_length": 3,
"bones": {
"body": {
"rotation": {
"0.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
"-math.sin(q.anim_time*90*2)*-20",
0,
"math.cos(q.anim_time*90*2)*-20"
],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [
"-math.sin(q.anim_time*90*2)*-20",
0,
"math.cos(q.anim_time*90*2)*-20"
],
"lerp_mode": "catmullrom"
},
"1.375": {
"post": [
"-19.94-math.sin(q.anim_time*90*32)*1",
-0.9,
2.28
],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [
"-24.1146-math.sin(q.anim_time*90*32)*1",
-5.1806,
-9.6237
],
"lerp_mode": "catmullrom"
},
"1.75": {
"post": [
-48.12,
-9.9,
-10.88
],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [
-82.4083,
-26.1002,
-17.2368
],
"lerp_mode": "catmullrom"
},
"2.0417": {
"post": [
-102.1119,
-24.854,
-31.5905
],
"lerp_mode": "catmullrom"
},
"2.3333": {
"post": [
-99.1014,
-23.4505,
-14.6775
],
"lerp_mode": "catmullrom"
},
"2.6667": {
"post": [
-66.3538,
-24.159,
6.6861
],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [
-85.0639,
-23.1834,
-2.9264
],
"lerp_mode": "catmullrom"
}
},
"position": {
"0.0": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
"-math.cos(q.anim_time*90*2)*2.6",
"math.sin(q.anim_time*90*2)*0.2",
"math.sin(q.anim_time*90*2)*-2.6"
],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [
"-math.cos(q.anim_time*90*2)*2.6",
"math.sin(q.anim_time*90*2)*0.2",
"math.sin(q.anim_time*90*2)*-2.6"
],
"lerp_mode": "catmullrom"
},
"1.375": {
"post": [
0.3,
-0.73,
2.28
],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [
-1.64,
-1.13,
2.77
],
"lerp_mode": "catmullrom"
},
"1.625": {
"post": [
-1.96,
-1.39,
4.06
],
"lerp_mode": "catmullrom"
},
"1.7083": {
"post": [
-2.19,
-2.77,
4.5
],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [
-3.71,
-4.79,
5.06
],
"lerp_mode": "catmullrom"
},
"1.9167": {
"post": [
-4.94977,
-3.02238,
5.61398
],
"lerp_mode": "catmullrom"
},
"2.2083": {
"post": [
-5.87185,
-2.2078,
6.20958
],
"lerp_mode": "catmullrom"
},
"2.5": {
"post": [
-4.3217,
-4.5458,
4.90724
],
"lerp_mode": "catmullrom"
},
"2.6667": {
"post": [
-3.91,
-4.91,
5.01
],
"lerp_mode": "catmullrom"
},
"2.75": {
"post": [
-3.92405,
-4.96563,
5.12418
],
"lerp_mode": "catmullrom"
},
"2.9167": {
"post": [
-4.24661,
-5.20065,
5.11229
],
"lerp_mode": "catmullrom"
},
"3.0": {
"post": [
-4.29542,
-5.18509,
5.3042
],
"lerp_mode": "catmullrom"
}
}
}
}
},
"animation.kakuna.cry": {
"animation_length": 1,
"bones": {
"body": {
"rotation": {
"0.0": [
0,
0,
0
],
"0.125": {
"pre": [
4.5,
0,
0
],
"post": [
4.5,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.3333": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.4167": {
"post": [
-0.1296,
2.4461,
-3.0023
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
-0.0867,
-2.4636,
2.0016
],
"lerp_mode": "catmullrom"
},
"0.5833": {
"post": [
0,
0,
0
],
"lerp_mode": "catmullrom"
},
"0.6667": [
0,
0,
0
]
},
"position": {
"0.0": [
0,
0,
0
],
"0.125": {
"pre": [
0,
-0.05,
-0.5
],
"post": [
0,
-0.05,
-0.5
],
"lerp_mode": "catmullrom"
},
"0.3333": {
"post": [
0,
-0.1,
0.1
],
"lerp_mode": "catmullrom"
},
"0.4167": {
"post": [
-0.25,
-0.08,
0.12
],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [
0.08,
-0.05,
0.08
],
"lerp_mode": "catmullrom"
},
"0.5833": {
"post": [
0.015,
-0.01,
0.02
],
"lerp_mode": "catmullrom"
},
"0.6667": [
0,
0,
0
]
}
}
},
"sound_effects": {
"0.0417": {
"effect": "pokemon.kakuna.cry"
}
}
},
"animation.kakuna.render": {
"loop": true,
"bones": {
"kakuna": {
"rotation": [
0,
-15,
0
]
}
}
},
"animation.kakuna.cling_side": {
"loop": true,
"bones": {
"body": {
"rotation": [
0,
0,
0
],
"position": [
0,
0,
0.75
]
}
}
},
"animation.kakuna.cling_side2": {
"loop": true,
"bones": {
"body": {
"rotation": [
185,
0,
-179.9998
],
"position": [
0,
0,
-1
]
}
}
},
"animation.kakuna.hang": {
"loop": true,
"bones": {
"body": {
"rotation": [
"-math.sin(q.anim_time*90*1)*2",
0,
"math.sin(q.anim_time*90*1/2)*2"
],
"position": [
"-math.sin(q.anim_time*90*1/2)*0.3",
0,
"1+math.sin(q.anim_time*90*1)*-0.3"
]
}
}
}
}
}
@@ -149,7 +149,7 @@
},
"body": {
"rotation": [15, 0, 0],
"position": [0, 0.67, 0.74]
"position": [0, 0.57, -0.26]
},
"fang_left": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "-27.5-math.cos(q.anim_time*90*3+30)*6", 0]
@@ -1274,165 +1274,6 @@
}
}
},
"animation.spinarak.shoulder_left": {
"loop": true,
"bones": {
"head": {
"rotation": ["30.77-math.cos(q.anim_time*90*3-30)*2", 0.87, 0],
"position": [0, 0, 0]
},
"horn": {
"rotation": [20, 0, 0]
},
"legfront_left": {
"rotation": [37.03, 30.64, "103.77+math.cos(q.anim_time*90*3)*1"],
"position": ["0.25+math.cos(q.anim_time*90*3)*0.025", "0+math.cos(q.anim_time*90*3)*0.022", "0-math.cos(q.anim_time*90*3)*0.035"]
},
"legfront_left2": {
"rotation": [10.39, "6.94-math.cos(q.anim_time*90*3)*1", "51.29-math.cos(q.anim_time*90*3)*0.85"],
"position": [0, 0, 0]
},
"legmiddle_left2": {
"rotation": [0, 0, "77-math.cos(q.anim_time*90*3)*0.75"],
"position": [0, "0+math.cos(q.anim_time*90*3)*0.075", 0]
},
"legmiddle_left": {
"rotation": [1.50701, -4.76804, "59.4373+math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legback_left": {
"rotation": ["-39.86-math.cos(q.anim_time*90*3)*2", -32.37, "68.5+math.cos(q.anim_time*90*3)*1.5"],
"position": [0, 0, 0]
},
"legback_left2": {
"rotation": [0, 0, "62-math.cos(q.anim_time*90*3)*1"],
"position": [0, "math.cos(q.anim_time*90*3)*0.05", 0]
},
"legfront_right": {
"rotation": [43.86, -48.64, "-55.06+math.cos(q.anim_time*90*3)*1.25"]
},
"legfront_right2": {
"rotation": ["0-math.cos(q.anim_time*90*3)*0.5", "0-math.cos(q.anim_time*90*3)*1.25", "-72.5-math.cos(q.anim_time*90*3)*0.5"],
"position": ["0-math.cos(q.anim_time*90*3)*0.025", "0-math.cos(q.anim_time*90*3)*0.04", 0]
},
"legmiddle_right": {
"rotation": [6.75653, 11.06411, 17.23876],
"position": [0, 0, 0]
},
"legmiddle_right2": {
"rotation": [0, 0, -115],
"position": [-0.3559, -0.74021, 0]
},
"legback_right": {
"rotation": [-20.75, 36.97, "-33.8-math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legback_right2": {
"rotation": [-7.5, "0-math.cos(q.anim_time*90*3)*0.75", "-79.5+math.cos(q.anim_time*90*3)*0.75"],
"position": ["0+math.cos(q.anim_time*90*3)*0.01", "0+math.cos(q.anim_time*90*3)*0.05", "0-math.cos(q.anim_time*90*3)*0.01"]
},
"torso_pattern_top": {
"rotation": [0, 0, 0]
},
"torso": {
"rotation": ["3.26+math.cos(q.anim_time*90*3)*1", 6.75, 11.24],
"position": [-0.17, "-0.37-math.sin(q.anim_time*90*3)*0.05", 0.15]
},
"torso_pattern_bottom": {
"position": [0, 0, 0.5]
},
"body": {
"rotation": [-9.51, -2.14, 22.97],
"position": [0, 0, 0]
},
"fang_left": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "-27.5-math.cos(q.anim_time*90*3+30)*6", 0]
},
"fang_right": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "27.5+math.cos(q.anim_time*90*3+30)*6", 0]
}
}
},
"animation.spinarak.shoulder_right": {
"loop": true,
"bones": {
"head": {
"rotation": ["30.77+math.cos(q.anim_time*90*3-30)*2", -0.87, 0],
"position": [0, 0, 0]
},
"horn": {
"rotation": [20, 0, 0]
},
"legfront_left": {
"rotation": [43.86, 48.64, "55.06-math.cos(q.anim_time*90*3)*1.25"],
"position": ["0.25+math.cos(q.anim_time*90*3)*0.025", "0-math.cos(q.anim_time*90*3)*0.022", "0-math.cos(q.anim_time*90*3)*0.035"]
},
"legfront_left2": {
"rotation": ["0-math.cos(q.anim_time*90*3)*0.5", "0+math.cos(q.anim_time*90*3)*1.25", "72.5+math.cos(q.anim_time*90*3)*0.5"],
"position": ["0-math.cos(q.anim_time*90*3)*0.025", "0-math.cos(q.anim_time*90*3)*0.04", 0]
},
"legmiddle_left2": {
"rotation": [0, 0, 115],
"position": [0.3559, -0.74021, 0]
},
"legmiddle_left": {
"rotation": [6.75653, -11.06411, -17.23876],
"position": [0, 0, 0]
},
"legback_left": {
"rotation": [-20.75, -36.97, "33.8+math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legback_left2": {
"rotation": [-7.5, "0+math.cos(q.anim_time*90*3)*0.75", "79.5-math.cos(q.anim_time*90*3)*0.75"],
"position": ["0-math.cos(q.anim_time*90*3)*0.01", "0+math.cos(q.anim_time*90*3)*0.05", "0+math.cos(q.anim_time*90*3)*0.01"]
},
"legfront_right": {
"rotation": [37.03, -30.64, "-103.77-math.cos(q.anim_time*90*3)*1"],
"position": ["-0.25-math.cos(q.anim_time*90*3)*0.025", "0+math.cos(q.anim_time*90*3)*0.022", "0-math.cos(q.anim_time*90*3)*0.035"]
},
"legfront_right2": {
"rotation": [10.39, "-6.94+math.cos(q.anim_time*90*3)*1", "-51.29+math.cos(q.anim_time*90*3)*0.85"],
"position": [0, 0, 0]
},
"legmiddle_right": {
"rotation": [1.50701, 4.76804, "-59.4373-math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legmiddle_right2": {
"rotation": [0, 0, "-77+math.cos(q.anim_time*90*3)*0.75"],
"position": [0, "0+math.cos(q.anim_time*90*3)*0.075", 0]
},
"legback_right": {
"rotation": ["-39.86-math.cos(q.anim_time*90*3)*2", 32.37, "-68.5-math.cos(q.anim_time*90*3)*1.5"],
"position": [0, 0, 0]
},
"legback_right2": {
"rotation": [0, 0, "-62+math.cos(q.anim_time*90*3)*1"],
"position": [0, "0+math.cos(q.anim_time*90*3)*0.05", 0]
},
"torso_pattern_top": {
"rotation": [0, 0, 0]
},
"torso": {
"rotation": ["3.26-math.cos(q.anim_time*90*3)*1", -6.75, -11.24],
"position": [0.17, "-0.37+math.sin(q.anim_time*90*3)*0.05", 0.15]
},
"torso_pattern_bottom": {
"position": [0, 0, 0.5]
},
"body": {
"rotation": [-9.51, 2.14, -22.97],
"position": [0, 0, 0]
},
"fang_left": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "-27.5-math.cos(q.anim_time*90*3+30)*6", 0]
},
"fang_right": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "27.5+math.cos(q.anim_time*90*3+30)*6", 0]
}
}
},
"animation.spinarak.dance": {
"loop": true,
"animation_length": 0.3333,
@@ -1850,6 +1691,165 @@
}
}
},
"animation.spinarak.shoulder_left": {
"loop": true,
"bones": {
"head": {
"rotation": ["30.77-math.cos(q.anim_time*90*3-30)*2", 0.87, 0],
"position": [0, 0, 0]
},
"horn": {
"rotation": [20, 0, 0]
},
"legfront_left": {
"rotation": [37.03, 30.64, "103.77+math.cos(q.anim_time*90*3)*1"],
"position": ["0.25+math.cos(q.anim_time*90*3)*0.025", "0+math.cos(q.anim_time*90*3)*0.022", "0-math.cos(q.anim_time*90*3)*0.035"]
},
"legfront_left2": {
"rotation": [10.39, "6.94-math.cos(q.anim_time*90*3)*1", "51.29-math.cos(q.anim_time*90*3)*0.85"],
"position": [0, 0, 0]
},
"legmiddle_left2": {
"rotation": [0, 0, "77-math.cos(q.anim_time*90*3)*0.75"],
"position": [0, "0+math.cos(q.anim_time*90*3)*0.075", 0]
},
"legmiddle_left": {
"rotation": [1.50701, -4.76804, "59.4373+math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legback_left": {
"rotation": ["-39.86-math.cos(q.anim_time*90*3)*2", -32.37, "68.5+math.cos(q.anim_time*90*3)*1.5"],
"position": [0, 0, 0]
},
"legback_left2": {
"rotation": [0, 0, "62-math.cos(q.anim_time*90*3)*1"],
"position": [0, "math.cos(q.anim_time*90*3)*0.05", 0]
},
"legfront_right": {
"rotation": [43.86, -48.64, "-55.06+math.cos(q.anim_time*90*3)*1.25"]
},
"legfront_right2": {
"rotation": ["0-math.cos(q.anim_time*90*3)*0.5", "0-math.cos(q.anim_time*90*3)*1.25", "-72.5-math.cos(q.anim_time*90*3)*0.5"],
"position": ["0-math.cos(q.anim_time*90*3)*0.025", "0-math.cos(q.anim_time*90*3)*0.04", 0]
},
"legmiddle_right": {
"rotation": [6.75653, 11.06411, 17.23876],
"position": [0, 0, 0]
},
"legmiddle_right2": {
"rotation": [0, 0, -115],
"position": [-0.3559, -0.74021, 0]
},
"legback_right": {
"rotation": [-20.75, 36.97, "-33.8-math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legback_right2": {
"rotation": [-7.5, "0-math.cos(q.anim_time*90*3)*0.75", "-79.5+math.cos(q.anim_time*90*3)*0.75"],
"position": ["0+math.cos(q.anim_time*90*3)*0.01", "0+math.cos(q.anim_time*90*3)*0.05", "0-math.cos(q.anim_time*90*3)*0.01"]
},
"torso_pattern_top": {
"rotation": [0, 0, 0]
},
"torso": {
"rotation": ["3.26+math.cos(q.anim_time*90*3)*1", 6.75, 11.24],
"position": [-0.17, "-0.37-math.sin(q.anim_time*90*3)*0.05", 0.15]
},
"torso_pattern_bottom": {
"position": [0, 0, 0.5]
},
"body": {
"rotation": [-9.51, -2.14, 22.97],
"position": [0, 0, 0]
},
"fang_left": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "-27.5-math.cos(q.anim_time*90*3+30)*6", 0]
},
"fang_right": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "27.5+math.cos(q.anim_time*90*3+30)*6", 0]
}
}
},
"animation.spinarak.shoulder_right": {
"loop": true,
"bones": {
"head": {
"rotation": ["30.77+math.cos(q.anim_time*90*3-30)*2", -0.87, 0],
"position": [0, 0, 0]
},
"horn": {
"rotation": [20, 0, 0]
},
"legfront_left": {
"rotation": [43.86, 48.64, "55.06-math.cos(q.anim_time*90*3)*1.25"],
"position": ["0.25+math.cos(q.anim_time*90*3)*0.025", "0-math.cos(q.anim_time*90*3)*0.022", "0-math.cos(q.anim_time*90*3)*0.035"]
},
"legfront_left2": {
"rotation": ["0-math.cos(q.anim_time*90*3)*0.5", "0+math.cos(q.anim_time*90*3)*1.25", "72.5+math.cos(q.anim_time*90*3)*0.5"],
"position": ["0-math.cos(q.anim_time*90*3)*0.025", "0-math.cos(q.anim_time*90*3)*0.04", 0]
},
"legmiddle_left2": {
"rotation": [0, 0, 115],
"position": [0.3559, -0.74021, 0]
},
"legmiddle_left": {
"rotation": [6.75653, -11.06411, -17.23876],
"position": [0, 0, 0]
},
"legback_left": {
"rotation": [-20.75, -36.97, "33.8+math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legback_left2": {
"rotation": [-7.5, "0+math.cos(q.anim_time*90*3)*0.75", "79.5-math.cos(q.anim_time*90*3)*0.75"],
"position": ["0-math.cos(q.anim_time*90*3)*0.01", "0+math.cos(q.anim_time*90*3)*0.05", "0+math.cos(q.anim_time*90*3)*0.01"]
},
"legfront_right": {
"rotation": [37.03, -30.64, "-103.77-math.cos(q.anim_time*90*3)*1"],
"position": ["-0.25-math.cos(q.anim_time*90*3)*0.025", "0+math.cos(q.anim_time*90*3)*0.022", "0-math.cos(q.anim_time*90*3)*0.035"]
},
"legfront_right2": {
"rotation": [10.39, "-6.94+math.cos(q.anim_time*90*3)*1", "-51.29+math.cos(q.anim_time*90*3)*0.85"],
"position": [0, 0, 0]
},
"legmiddle_right": {
"rotation": [1.50701, 4.76804, "-59.4373-math.cos(q.anim_time*90*3)*1"],
"position": [0, 0, 0]
},
"legmiddle_right2": {
"rotation": [0, 0, "-77+math.cos(q.anim_time*90*3)*0.75"],
"position": [0, "0+math.cos(q.anim_time*90*3)*0.075", 0]
},
"legback_right": {
"rotation": ["-39.86-math.cos(q.anim_time*90*3)*2", 32.37, "-68.5-math.cos(q.anim_time*90*3)*1.5"],
"position": [0, 0, 0]
},
"legback_right2": {
"rotation": [0, 0, "-62+math.cos(q.anim_time*90*3)*1"],
"position": [0, "0+math.cos(q.anim_time*90*3)*0.05", 0]
},
"torso_pattern_top": {
"rotation": [0, 0, 0]
},
"torso": {
"rotation": ["3.26-math.cos(q.anim_time*90*3)*1", -6.75, -11.24],
"position": [0.17, "-0.37+math.sin(q.anim_time*90*3)*0.05", 0.15]
},
"torso_pattern_bottom": {
"position": [0, 0, 0.5]
},
"body": {
"rotation": [-9.51, 2.14, -22.97],
"position": [0, 0, 0]
},
"fang_left": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "-27.5-math.cos(q.anim_time*90*3+30)*6", 0]
},
"fang_right": {
"rotation": ["0-math.cos(q.anim_time*90*3-60)*4", "27.5+math.cos(q.anim_time*90*3+30)*6", 0]
}
}
},
"animation.spinarak.cry": {
"animation_length": 1,
"bones": {
@@ -3182,6 +3182,125 @@
}
}
}
},
"animation.spinarak.hang": {
"loop": true,
"bones": {
"body": {
"rotation": ["90-math.sin(q.anim_time*90*1)*1", 0, "math.sin(q.anim_time*90*1/2-30)*-2"],
"position": ["-math.sin(q.anim_time*90*1/2-30)*-0.2", "math.sin(q.anim_time*90*1)*0.2", "math.sin(q.anim_time*90*1)*-0.15"]
},
"head": {
"rotation": ["-27.5-math.sin(q.anim_time*90*1+30)*-2", "-math.sin(q.anim_time*90*1/2)*-3", 0]
},
"fang_left": {
"rotation": [0, "-20-math.cos(q.anim_time*90*1+30)*6", 0]
},
"fang_right": {
"rotation": [0, "20+math.cos(q.anim_time*90*1+30)*6", 0]
},
"legfront_left": {
"rotation": [12.2127, "2.6852+math.sin(q.anim_time*90*1+40)*2", 77.7873]
},
"legfront_left2": {
"rotation": [0, 0, "75-math.sin(q.anim_time*90*1)*2"]
},
"legfront_right": {
"rotation": [12.2127, "-2.6852-math.sin(q.anim_time*90*1+40)*2", -77.7873]
},
"legfront_right2": {
"rotation": [0, 0, "-75+math.sin(q.anim_time*90*1)*2"]
},
"legmiddle_left": {
"rotation": [10.0629, "-15.9665+math.sin(q.anim_time*90*1+60)*2", 69.2151],
"position": [0, 0, 0.75]
},
"legmiddle_left2": {
"rotation": [0, 0, "80-math.sin(q.anim_time*90*1+20)*2"]
},
"legmiddle_right": {
"rotation": [10.0629, "15.9665-math.sin(q.anim_time*90*1+60)*2", -69.2151],
"position": [0, 0, 0.75]
},
"legmiddle_right2": {
"rotation": [0, 0, "-80+math.sin(q.anim_time*90*1+20)*2"]
},
"legback_left": {
"rotation": [89.6171, "-68.5328+math.sin(q.anim_time*90*1-30)*2", 17.6831],
"position": [0, 0, 0.75]
},
"legback_left2": {
"rotation": [0, 0, "67.5-math.sin(q.anim_time*90*1-30)*-5"]
},
"legback_right": {
"rotation": [89.6171, "68.5328-math.sin(q.anim_time*90*1-30)*2", -17.6831],
"position": [0, 0, 0.75]
},
"legback_right2": {
"rotation": [0, 0, "-67.5+math.sin(q.anim_time*90*1-30)*-5"]
}
}
},
"animation.spinarak.hang2": {
"loop": true,
"bones": {
"body": {
"rotation": ["90-math.sin(q.anim_time*90*1)*1", 0, "math.sin(q.anim_time*90*1/2-30)*-2"],
"position": ["-math.sin(q.anim_time*90*1/2-30)*-0.2", "math.sin(q.anim_time*90*1)*0.2", "math.sin(q.anim_time*90*1)*-0.15"]
},
"head": {
"rotation": ["-27.5-math.sin(q.anim_time*90*1+30)*-2", "-math.sin(q.anim_time*90*1/2)*-3", 0]
},
"fang_left": {
"rotation": [0, "-20-math.cos(q.anim_time*90*1+30)*6", 0]
},
"fang_right": {
"rotation": [0, "20+math.cos(q.anim_time*90*1+30)*6", 0]
},
"legfront_left": {
"rotation": [-2.7873, "20.1852+math.sin(q.anim_time*90*1+40)*5", 15.2873]
},
"legfront_left2": {
"rotation": [0, 0, "37.5-math.sin(q.anim_time*90*1)*2"]
},
"legfront_right": {
"rotation": [-2.7873, "-20.1852-math.sin(q.anim_time*90*1+40)*5", -15.2873]
},
"legfront_right2": {
"rotation": [0, 0, "-37.5+math.sin(q.anim_time*90*1)*2"]
},
"legmiddle_left": {
"rotation": [8.244, "-20.0319+math.sin(q.anim_time*90*1+60)*4", 14.8239],
"position": [0, 0, 0.75]
},
"legmiddle_left2": {
"rotation": [0, 0, "22.5-math.sin(q.anim_time*90*1+20)*2"]
},
"legmiddle_right": {
"rotation": [8.244, "20.0319-math.sin(q.anim_time*90*1+60)*4", -14.8239],
"position": [0, 0, 0.75]
},
"legmiddle_right2": {
"rotation": [0, 0, "-22.5+math.sin(q.anim_time*90*1+20)*2"]
},
"legback_left": {
"rotation": [89.6171, "-68.5328+math.sin(q.anim_time*90*1-30)*2", 17.6831],
"position": [0, 0, 0.75]
},
"legback_left2": {
"rotation": [0, 0, "67.5-math.sin(q.anim_time*90*1-30)*-5"]
},
"legback_right": {
"rotation": [89.6171, "68.5328-math.sin(q.anim_time*90*1-30)*2", -17.6831],
"position": [0, 0, 0.75]
},
"legback_right2": {
"rotation": [0, 0, "-67.5+math.sin(q.anim_time*90*1-30)*-5"]
}
}
},
"animation.spinarak.new": {
"loop": true
}
}
}
@@ -1537,7 +1537,7 @@
}
}
},
"animation.ariados.ride_ground_walk": {
"animation.ariados.ride_ground_walk_turn": {
"loop": true,
"bones": {
"body": {
@@ -1560,7 +1560,7 @@
}
}
},
"animation.ariados.ride_ground_run": {
"animation.ariados.ride_ground_run_turn": {
"loop": true,
"bones": {
"body": {
@@ -2624,6 +2624,100 @@
}
}
},
"animation.ariados.hang": {
"loop": true,
"bones": {
"body": {
"rotation": ["90-math.sin(q.anim_time*90*3/4)*2", 0, "math.sin(q.anim_time*90*1)*2"],
"position": ["-math.sin(q.anim_time*90*1)*0.6", "math.sin(q.anim_time*90*1/3)*-0.2", "0.5+math.sin(q.anim_time*90*3/4)*-0.6"]
},
"leg_top_left": {
"rotation": ["-54-math.sin(q.anim_time*90*3/4-50)*3", "12-math.sin(q.anim_time*90*1-40)*-4", "9+math.sin(q.anim_time*90*1-40)*1"]
},
"leg_top_right": {
"rotation": ["-54-math.sin(q.anim_time*90*3/4-50)*3", "-12-math.sin(q.anim_time*90*1-40)*-4", "-9+math.sin(q.anim_time*90*1-40)*1"]
},
"neck": {
"rotation": ["-15-math.sin(q.anim_time*90*3/4-50)*3", "-math.sin(q.anim_time*90*1-30)*2", 0]
},
"head": {
"rotation": ["-10-math.sin(q.anim_time*90*3/4-110)*3", "-math.sin(q.anim_time*90*1-80)*-4", 0]
},
"leg_front_left": {
"rotation": [5.6965, -7.0155, "57.1864-math.sin(q.anim_time*90*1-60)*-4"]
},
"leg_front2_left": {
"rotation": [0, 5, "67.5-math.sin(q.anim_time*90*1-150)*-2"]
},
"leg_front_right": {
"rotation": [13.1965, 9.5155, "-57.1864+math.sin(q.anim_time*90*1-30)*-4"]
},
"leg_front2_right": {
"rotation": [0, 0, "-67.5+math.sin(q.anim_time*90*1-160)*-2"]
},
"leg_back_left": {
"rotation": [2.9325, -22.4097, "60.4096-math.sin(q.anim_time*90*1-20)*-4"],
"position": [0, -1, 0]
},
"leg_back2_left": {
"rotation": [0, -7.5, "72.5-math.sin(q.anim_time*90*1-100)*-2"]
},
"leg_back_right": {
"rotation": [-2.0675, 22.4097, "-60.4096+math.sin(q.anim_time*90*1-40)*-4"],
"position": [0, -1, 0]
},
"leg_back2_right": {
"rotation": [0, 2.5, "-72.5+math.sin(q.anim_time*90*1-110)*-2"]
}
}
},
"animation.ariados.hang2": {
"loop": true,
"bones": {
"body": {
"rotation": ["90-math.sin(q.anim_time*90*3/4)*2", 0, "math.sin(q.anim_time*90*1)*2"],
"position": ["-math.sin(q.anim_time*90*1)*0.6", "math.sin(q.anim_time*90*1/3)*-0.2", "0.5+math.sin(q.anim_time*90*3/4)*-0.6"]
},
"leg_top_left": {
"rotation": ["-54-math.sin(q.anim_time*90*3/4-50)*3", "12-math.sin(q.anim_time*90*1-40)*-4", "9+math.sin(q.anim_time*90*1-40)*1"]
},
"leg_top_right": {
"rotation": ["-54-math.sin(q.anim_time*90*3/4-50)*3", "-12-math.sin(q.anim_time*90*1-40)*-4", "-9+math.sin(q.anim_time*90*1-40)*1"]
},
"neck": {
"rotation": ["-15-math.sin(q.anim_time*90*3/4-50)*3", "-math.sin(q.anim_time*90*1-30)*2", 0]
},
"head": {
"rotation": ["-10-math.sin(q.anim_time*90*3/4-110)*3", "-math.sin(q.anim_time*90*1-80)*-4", 0]
},
"leg_front_left": {
"rotation": [-16, 18, "27-math.sin(q.anim_time*90*1-60)*-4"]
},
"leg_front2_left": {
"rotation": [0, 5, "math.sin(q.anim_time*90*1-150)*2"]
},
"leg_front_right": {
"rotation": [-16, -18, "-27+math.sin(q.anim_time*90*1-30)*4"]
},
"leg_front2_right": {
"rotation": [0, 0, "math.sin(q.anim_time*90*1-160)*2"]
},
"leg_back_left": {
"rotation": [0, -30, "23-math.sin(q.anim_time*90*1-20)*-4"],
"position": [0, -1, 0]
},
"leg_back2_left": {
"rotation": [0, -2.5, "17.5-math.sin(q.anim_time*90*1-100)*-2"]
},
"leg_back_right": {
"rotation": [0, 30, "-23+math.sin(q.anim_time*90*1-40)*4"],
"position": [0, -1, 0]
},
"leg_back2_right": {
"rotation": [0, 2.5, "-17.5+math.sin(q.anim_time*90*1-110)*2"]
}
}
},
"animation.ariados.look_quirk_WIP": {
"loop": "hold_on_last_frame",
"animation_length": 3.5,
@@ -2805,6 +2899,55 @@
}
}
}
},
"animation.ariados.ride_ground_walk": {
"loop": true,
"bones": {
"body": {
"rotation": [0, "0+q.r.yaw_change(0)*10", 0]
},
"leg_top_left": {
"rotation": [0, 0, "0+q.r.yaw_change(2)*12"]
},
"leg_top_right": {
"rotation": [0, 0, "0+q.r.yaw_change(2)*12"]
},
"neck": {
"rotation": [0, "0-q.r.yaw_change(0)*5", 0]
},
"head": {
"rotation": [0, "0+q.r.yaw_change(0)*15", 0]
},
"front_legs": {
"rotation": [0, "0+q.r.yaw_change(0)*12", 0]
}
}
},
"animation.ariados.ride_ground_run": {
"loop": true,
"bones": {
"body": {
"rotation": [0, "0+q.r.yaw_change(0)*10", 0]
},
"leg_top_left": {
"rotation": [0, 0, "0+q.r.yaw_change(2)*12"]
},
"leg_top_right": {
"rotation": [0, 0, "0+q.r.yaw_change(2)*12"]
},
"neck": {
"rotation": [0, "0-q.r.yaw_change(0)*5", 0]
},
"head": {
"rotation": [0, "0+q.r.yaw_change(0)*15", 0]
},
"front_legs": {
"rotation": [0, "0+q.r.yaw_change(0)*12", 0]
},
"back_legs": {
"rotation": [0, "0+q.r.yaw_change(1)*6", 0]
}
}
}
}
}
}
@@ -1874,7 +1874,6 @@
},
"animation.noivern.air_idle": {
"loop": true,
"animation_length": 1,
"bones": {
"body": {
"rotation": ["25+Math.cos((query.anim_time)*90*4-90)*-2", 0, 0],
@@ -2057,14 +2056,476 @@
"wing_tip_right": {
"rotation": [0, "-20+Math.cos((query.anim_time)*90*4-160)*-30", "5+Math.cos((query.anim_time)*90*4-60)*-5"]
}
},
"timeline": {
"0.4167": "q.has_entity ? { q.sound('animation.leather.wing_flap.medium'); };"
}
},
"animation.noivern.sleep": {
"loop": true,
"animation_length": 0.1667,
"bones": {
"body": {
"rotation": [87.5, 0, 0],
"position": [0, -25, 0]
},
"torso": {
"rotation": [17.5, 0, 0]
},
"torso2": {
"rotation": [-12.5, 0, 0]
},
"torso3": {
"rotation": [-17.5, 0, 0]
},
"neck": {
"rotation": [30, -5, 2.5]
},
"neck2": {
"rotation": [-20, 0, 7.5]
},
"head": {
"rotation": [-55, 0, 0]
},
"tail": {
"rotation": [-42.5, 0, 15],
"position": [-0.4, -6.75, -1.65]
},
"tail2": {
"rotation": [-17.5, -10, -2.5]
},
"tail3": {
"rotation": [7.5, -30, -5]
},
"tail4": {
"rotation": [17.5, -30, -5]
},
"tail5": {
"rotation": [-5, -40, 0]
},
"tail6": {
"rotation": [0, -32.5, 0]
},
"tail7": {
"rotation": [-5, -50, 0]
},
"tail8": {
"rotation": [0, 15, 0]
},
"ftorso2": {
"rotation": [-12.5, 0, 0]
},
"ftorso3": {
"rotation": [-12.5, 0, 0]
},
"arms": {
"position": [0, 0, -3]
},
"shoulder_left": {
"rotation": [-5, 30, -40]
},
"shoulder_membrane_left": {
"rotation": [0, 0, 32.5]
},
"arm_left": {
"rotation": [7.5, 2.5, 0]
},
"arm_membrane_left": {
"rotation": [-5, 0, 25]
},
"arm_membrane_hidden_left": {
"rotation": [7.5, -10, -22.5],
"position": [-0.2, 0.75, 0.6]
},
"elbow_left": {
"rotation": [12.5, 12.5, -30]
},
"wing_trim_inner_left2": {
"rotation": [7.5, 0, 10]
},
"elbow_membrane_left": {
"rotation": [5, -5, 0]
},
"elbow_membrane_hidden_left": {
"rotation": [0, -20, 0],
"position": [0, 1.2, 0]
},
"hand_left": {
"rotation": [5, -10, 7.5]
},
"fingers_left": {
"rotation": [-2.5, 4, 4.25]
},
"finger_outer_left": {
"rotation": [-10, 0, 0]
},
"finger_outer_left2": {
"rotation": [15, 0, 0]
},
"finger_inner_left": {
"rotation": [0, 0, -5]
},
"finger_inner_left2": {
"rotation": [15, 0, 0]
},
"finger_middle_left2": {
"rotation": [15, 0, 0]
},
"wing_end_left": {
"rotation": [0, -5, 2.5]
},
"shoulder_right": {
"rotation": [-5, -30, 42.5]
},
"shoulder_membrane_right": {
"rotation": [0, 0, -32.5]
},
"arm_right": {
"rotation": [7.5, -2.5, 0]
},
"arm_membrane_right": {
"rotation": [-5, 0, -25]
},
"arm_membrane_hidden_right": {
"rotation": [7.5, 10, 22.5],
"position": [0.2, 0.75, 0.6]
},
"elbow_right": {
"rotation": [10, -12.5, 27.5]
},
"wing_trim_inner_right2": {
"rotation": [7.5, 0, -10]
},
"elbow_membrane_right": {
"rotation": [5, 5, 0]
},
"elbow_membrane_hidden_right": {
"rotation": [0, 20, 0],
"position": [0, 1.2, 0]
},
"hand_right": {
"rotation": [5, 10, -7.5]
},
"fingers_right": {
"rotation": [-15, -4, -4.25]
},
"finger_outer_right": {
"rotation": [-2.5, 0, 0]
},
"finger_outer_right2": {
"rotation": [15, 0, 0]
},
"finger_inner_right2": {
"rotation": [15, 0, 0]
},
"finger_middle_right": {
"rotation": [-5, 0, 0]
},
"finger_middle_right2": {
"rotation": [15, 0, 0]
},
"wing_end_right": {
"rotation": [0, 5, -2.5]
},
"leg_left": {
"rotation": [2.5, 7.5, 15]
},
"knee_left": {
"rotation": [-22.5, 0, 0]
},
"foot_left": {
"rotation": [0, 10, 0]
},
"foot_left3": {
"rotation": [50, 0, 0]
},
"toe_inner_left": {
"rotation": [60, 0, 0]
},
"toe_outer_left": {
"rotation": [55, 0, 0]
},
"leg_right": {
"rotation": [-85, 25, -15],
"position": [0, -0.75, 1.75]
},
"knee_right": {
"rotation": [62.5, 0, 0],
"position": [0, -3, 0]
},
"foot_right": {
"rotation": [2.5, -25, 7.5]
},
"foot_right3": {
"rotation": [50, 0, 0]
},
"toe_inner_right": {
"rotation": [60, 0, 0]
},
"toe_outer_right": {
"rotation": [55, 0, 0]
},
"eyelid_left": {
"position": {
"0.0": [0.1, 0.1, 0],
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
}
},
"eyelid_right": {
"position": {
"0.0": [-0.1, 0.1, 0],
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
}
}
}
},
"animation.noivern.cling_ceiling": {
"loop": true,
"bones": {
"body": {
"rotation": ["-math.sin(q.anim_time*90*1+30)*1", 0, -180],
"position": [0, "math.sin(q.anim_time*90*1+30)*-0.3", "4.25+math.sin(q.anim_time*90*1+30)*0.3"]
},
"neck": {
"rotation": ["20-math.sin(q.anim_time*90*1-120)*1", 0, 0]
},
"neck2": {
"rotation": [12.5, 0, 0]
},
"head": {
"rotation": ["12.5-math.sin(q.anim_time*90*1-160)*3", 0, 0]
},
"leg_left": {
"rotation": ["-math.sin(q.anim_time*90*1+30)*-1", -12.5, 27.5]
},
"knee_left": {
"rotation": ["-17.5-math.sin(q.anim_time*90*1+30)*2", 0, 0]
},
"foot_left3": {
"rotation": ["-25+math.sin(q.anim_time*90*1+30)*1", 0, -5]
},
"toe_inner_left": {
"rotation": [-12.5, 0, 0]
},
"toe_inner_left2": {
"rotation": [27.5, 0, 0]
},
"toe_outer_left": {
"rotation": [-12.5, 0, 0]
},
"toe_outer_left2": {
"rotation": [27.5, 0, 0]
},
"leg_right": {
"rotation": ["-math.sin(q.anim_time*90*1+30)*-1", 12.5, -27.5]
},
"knee_right": {
"rotation": ["-17.5-math.sin(q.anim_time*90*1+30)*2", 0, 0]
},
"foot_right3": {
"rotation": ["-25+math.sin(q.anim_time*90*1+30)*1", 0, 5]
},
"toe_inner_right": {
"rotation": [-12.5, 0, 0]
},
"toe_inner_right2": {
"rotation": [27.5, 0, 0]
},
"toe_outer_right": {
"rotation": [-12.5, 0, 0]
},
"toe_outer_right2": {
"rotation": [27.5, 0, 0]
},
"hips": {
"rotation": ["-math.sin(q.anim_time*90*1)*1", 0, 0]
},
"torso2": {
"rotation": ["-math.sin(q.anim_time*90*1-60)*1", 0, 0]
},
"torso3": {
"rotation": ["-7.5-math.sin(q.anim_time*90*1-90)*1", 0, 0]
},
"fluff_back": {
"rotation": ["-math.sin(q.anim_time*90*1-120)*3", 0, 0]
},
"tail": {
"rotation": ["-10-math.sin(q.anim_time*90*1)*-2-math.sin(q.anim_time*90*1+30)*-1", 0, 0]
},
"tail2": {
"rotation": ["10-math.sin(q.anim_time*90*1)*1", -15, -2.5]
},
"tail3": {
"rotation": [-15, "-32.5-math.sin(q.anim_time*90*1)*-2", 0]
},
"tail4": {
"rotation": [-42.5, "-47.5-math.sin(q.anim_time*90*1)*1", 15]
},
"tail5": {
"rotation": [-52.5, "-math.sin(q.anim_time*90*1-60)*3", "15+math.sin(q.anim_time*90*1-60)*3"]
},
"tail6": {
"rotation": [-57.5, "-math.sin(q.anim_time*90*1-120)*5", "math.sin(q.anim_time*90*1-120)*5"]
},
"tail7": {
"rotation": [-27.5, "-7.5-math.sin(q.anim_time*90*1-160)*9", 0]
},
"tail8": {
"rotation": ["-30-math.sin(q.anim_time*90*1-130)*-15", "-10-math.sin(q.anim_time*90*1-190)*12", 0]
},
"ftorso2": {
"rotation": ["-math.sin(q.anim_time*90*1-60)*1", 0, 0]
},
"ftorso3": {
"rotation": [-7.5, 0, 0]
},
"shoulder_left": {
"rotation": [0, 35, 22.5]
},
"arm_left": {
"rotation": [0, 2.5, 0]
},
"arm_membrane_hidden_left": {
"scale": 0
},
"elbow_left": {
"rotation": [155.5356, 68.7337, 156.8466]
},
"wing_trim_inner_left2": {
"rotation": [7.5, 0, 10]
},
"elbow_membrane_hidden_left": {
"rotation": [0, -102.5, 0]
},
"elbow_membrane_hidden_left2": {
"rotation": [0, 15, 0],
"scale": 0
},
"hand_left": {
"rotation": [0, 22.5, 0]
},
"hand_membrane_hidden_left": {
"rotation": [0, 27.5, 0],
"scale": 0
},
"fingers_left": {
"rotation": ["50-math.sin(q.anim_time*90*1-110)*-4", 0, 0]
},
"finger_outer_left": {
"rotation": [-15, 0, 0]
},
"finger_outer_left2": {
"rotation": [40, 0, 0]
},
"finger_inner_left": {
"rotation": [-12.5, 0, 0]
},
"finger_inner_left2": {
"rotation": [40, 0, 0]
},
"finger_middle_left": {
"rotation": [-20, 0, 0]
},
"finger_middle_left2": {
"rotation": [40, 0, 0]
},
"wing_end_left": {
"rotation": [0, 30, "-math.sin(q.anim_time*90*1-120)*1/2"]
},
"wing_trim_outer_left2": {
"rotation": [2.5, 0, 10]
},
"wing_end_membrane_left": {
"rotation": [7.2594, 11.6373, 10.6933],
"position": [0.8, 0.5, 1.1],
"scale": 1
},
"wing_end_membrane_hidden_left": {
"rotation": [6.1722, 31.4593, 13.096],
"scale": 0
},
"wing_tip_left": {
"rotation": [10.9281, 53.7754, 22.0884]
},
"shoulder_right": {
"rotation": [-5, -40, -15]
},
"shoulder_membrane_right": {
"rotation": [0, 0, 7.5]
},
"arm_right": {
"rotation": [7.5, -7.5, 7.5]
},
"arm_membrane_right": {
"rotation": [5, 0, 0]
},
"arm_membrane_hidden_right": {
"scale": 0
},
"elbow_right": {
"rotation": [-177.5, -90, -180]
},
"wing_trim_inner_right2": {
"rotation": [-2.5, 0, -5]
},
"elbow_membrane_hidden_right": {
"rotation": [0, 92.5, 0]
},
"elbow_membrane_hidden_right2": {
"rotation": [0, -15, 0],
"scale": 0
},
"hand_right": {
"rotation": [-0.4905, -20.2178, -4.9952]
},
"hand_membrane_hidden_right": {
"rotation": [0, -27.5, 0],
"scale": 0
},
"fingers_right": {
"rotation": ["50-math.sin(q.anim_time*90*1-130)*-4", 0, 0]
},
"finger_outer_right": {
"rotation": [-15, 0, 0]
},
"finger_outer_right2": {
"rotation": [40, 0, 0]
},
"finger_inner_right": {
"rotation": [-10, 0, 0]
},
"finger_inner_right2": {
"rotation": [40, 0, 0]
},
"finger_middle_right": {
"rotation": [-20, 0, 0]
},
"finger_middle_right2": {
"rotation": [40, 0, 0]
},
"wing_end_right": {
"rotation": [0, -30, "math.sin(q.anim_time*90*1-120)*1/2"]
},
"wing_end_membrane_hidden_right": {
"rotation": [0, -55, 0],
"scale": 0
},
"wing_tip_right": {
"rotation": [5.2761, -19.2416, -7.6109]
},
"foot_left": {
"rotation": ["-math.sin(q.anim_time*90*1+30)*-3", 0, 0]
},
"foot_right": {
"rotation": ["-math.sin(q.anim_time*90*1+30)*-3", 0, 0]
},
"eyelid_left": {
"position": [0.1, 0.1, 0]
},
"eyelid_right": {
"position": [-0.1, 0.1, 0]
}
}
},
"animation.noivern.air_fly": {
"loop": true,
"animation_length": 1,
"bones": {
"body": {
"rotation": ["47.5+Math.cos((query.anim_time)*90*4-90)*-2", 0, 0],
@@ -2247,9 +2708,6 @@
"wing_tip_right": {
"rotation": [0, "-20+Math.cos((query.anim_time)*90*4-160)*-30", "5+Math.cos((query.anim_time)*90*4-60)*-5"]
}
},
"timeline": {
"0.4167": "q.has_entity ? { q.sound('animation.leather.wing_flap.medium'); };"
}
},
"animation.noivern.air_glide": {
@@ -3098,124 +3556,6 @@
}
}
},
"animation.noivern.wing": {
"loop": true,
"bones": {
"shoulder_left": {
"rotation": [-10, -15, 12.5],
"position": [0, 0, 2]
},
"shoulder_membrane_left": {
"rotation": [-7.5, 0, -15]
},
"arm_left": {
"rotation": [-7.5, -7.5, -15]
},
"elbow_left": {
"rotation": [10, 12.5, 15]
},
"wing_trim_inner_left": {
"rotation": [0, 0, -5]
},
"hand_left": {
"rotation": [1, 20, -12.5]
},
"wing_end_left": {
"rotation": [0, 17.5, -11.5]
},
"wing_trim_outer_left": {
"rotation": [-1, 0, 2.5]
},
"wing_tip_left": {
"rotation": [0, 25, -10]
}
}
},
"animation.noivern.wing2": {
"loop": true,
"bones": {
"shoulder_left": {
"rotation": [-10, -2.5, 12.5],
"position": [0, 0, 2]
},
"shoulder_membrane_left": {
"rotation": [-7.5, 0, -15]
},
"arm_left": {
"rotation": [-7.5, -5, -15]
},
"elbow_left": {
"rotation": [0, 2.5, 5]
},
"wing_trim_inner_left": {
"rotation": [0, 0, -5]
},
"hand_left": {
"rotation": [1, 7.5, -12.5]
},
"wing_end_left": {
"rotation": [0, 0, -11.5]
},
"wing_trim_outer_left": {
"rotation": [-1, 0, 2.5]
},
"wing_tip_left": {
"rotation": [0, 5, -10]
}
}
},
"animation.noivern.wing3": {
"loop": true,
"bones": {
"elbow_left": {
"rotation": [0, 0, -22]
},
"wing_trim_inner_left": {
"rotation": [0, 0, 3]
},
"hand_left": {
"rotation": [0, 0, 7.5]
},
"wing_end_left": {
"rotation": [0, 0, 7.5]
},
"wing_trim_outer_left": {
"rotation": [0, 0, -4]
},
"wing_tip_left": {
"rotation": [0, 0, 5]
},
"elbow_membrane_left": {
"rotation": [0, 0, 2.5]
},
"hand_membrane_left": {
"rotation": [0, 0, 4]
}
}
},
"animation.noivern.blink": {
"animation_length": 0.1667,
"bones": {
"pupil_left": {
"rotation": {
"0.0": [0, 0, -90],
"0.1667": {
"pre": [0, 0, -90],
"post": [0, 0, 0]
}
}
},
"pupil_right": {
"rotation": {
"0.0": [0, 0, 90],
"0.1667": {
"pre": [0, 0, 90],
"post": [0, 0, 0]
}
}
}
}
},
"animation.noivern.ground_pose": {
"loop": true,
"bones": {
@@ -3435,6 +3775,124 @@
"position": [0, 0, "-q.anim_time*16*15"]
}
}
},
"animation.noivern.blink": {
"animation_length": 0.1667,
"bones": {
"pupil_left": {
"rotation": {
"0.0": [0, 0, -90],
"0.1667": {
"pre": [0, 0, -90],
"post": [0, 0, 0]
}
}
},
"pupil_right": {
"rotation": {
"0.0": [0, 0, 90],
"0.1667": {
"pre": [0, 0, 90],
"post": [0, 0, 0]
}
}
}
}
},
"animation.noivern.wing": {
"loop": true,
"bones": {
"shoulder_left": {
"rotation": [-10, -15, 12.5],
"position": [0, 0, 2]
},
"shoulder_membrane_left": {
"rotation": [-7.5, 0, -15]
},
"arm_left": {
"rotation": [-7.5, -7.5, -15]
},
"elbow_left": {
"rotation": [10, 12.5, 15]
},
"wing_trim_inner_left": {
"rotation": [0, 0, -5]
},
"hand_left": {
"rotation": [1, 20, -12.5]
},
"wing_end_left": {
"rotation": [0, 17.5, -11.5]
},
"wing_trim_outer_left": {
"rotation": [-1, 0, 2.5]
},
"wing_tip_left": {
"rotation": [0, 25, -10]
}
}
},
"animation.noivern.wing2": {
"loop": true,
"bones": {
"shoulder_left": {
"rotation": [-10, -2.5, 12.5],
"position": [0, 0, 2]
},
"shoulder_membrane_left": {
"rotation": [-7.5, 0, -15]
},
"arm_left": {
"rotation": [-7.5, -5, -15]
},
"elbow_left": {
"rotation": [0, 2.5, 5]
},
"wing_trim_inner_left": {
"rotation": [0, 0, -5]
},
"hand_left": {
"rotation": [1, 7.5, -12.5]
},
"wing_end_left": {
"rotation": [0, 0, -11.5]
},
"wing_trim_outer_left": {
"rotation": [-1, 0, 2.5]
},
"wing_tip_left": {
"rotation": [0, 5, -10]
}
}
},
"animation.noivern.wing3": {
"loop": true,
"bones": {
"elbow_left": {
"rotation": [0, 0, -22]
},
"wing_trim_inner_left": {
"rotation": [0, 0, 3]
},
"hand_left": {
"rotation": [0, 0, 7.5]
},
"wing_end_left": {
"rotation": [0, 0, 7.5]
},
"wing_trim_outer_left": {
"rotation": [0, 0, -4]
},
"wing_tip_left": {
"rotation": [0, 0, 5]
},
"elbow_membrane_left": {
"rotation": [0, 0, 2.5]
},
"hand_membrane_left": {
"rotation": [0, 0, 4]
}
}
}
}
}
}
@@ -1,27 +1,71 @@
{
"portraitScale": 1.7,
"portraitTranslation": [-0.1, -0.4, 0],
"profileScale": 0.96,
"profileTranslation": [0, 0.35, 0],
"rootBone": "kakuna",
"animations": {
"faint": "q.bedrock_primary('kakuna', 'faint', q.curve('one'))",
"cry": "q.bedrock_stateful('kakuna', 'cry')",
"physical": "q.bedrock_primary('kakuna', 'physical', q.curve('symmetrical'))"
{
"portraitScale": 1.7,
"portraitTranslation": [
-0.1,
-0.4,
0
],
"profileScale": 0.96,
"profileTranslation": [
0,
0.35,
0
],
"rootBone": "kakuna",
"animations": {
"faint": "q.bedrock_primary('kakuna', 'faint', q.curve('one'))",
"cry": "q.bedrock_stateful('kakuna', 'cry')",
"physical": "q.bedrock_primary('kakuna', 'physical', q.curve('symmetrical'))"
},
"poses": {
"standing": {
"poseTypes": [
"STAND",
"FLOAT",
"HOVER",
"NONE",
"PORTRAIT",
"PROFILE"
],
"animations": [
"q.bedrock('kakuna', 'ground_idle')"
]
},
"poses": {
"standing": {
"poseTypes": ["STAND", "FLOAT", "HOVER", "NONE", "PORTRAIT", "PROFILE"],
"animations": [
"q.bedrock('kakuna', 'ground_idle')"
]
},
"sleeping": {
"poseTypes": ["SLEEP"],
"poseTypes": [
"SLEEP"
],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('kakuna', 'sleep')"]
}
"animations": [
"q.bedrock('kakuna', 'sleep')"
]
},
"hang": {
"poseTypes": [
"HANG"
],
"animations": [
"q.bedrock('kakuna', 'hang')"
]
},
"cling_side2": {
"poseTypes": [
"CLING"
],
"animations": [
"q.bedrock('kakuna', 'cling_side2')"
],
"condition": "math.mod(q.entity_id, 2) == 1"
},
"cling": {
"poseTypes": [
"CLING"
],
"animations": [
"q.bedrock('kakuna', 'cling_side')"
]
}
}
}
}
@@ -1,8 +1,16 @@
{
"portraitScale": 2.18,
"portraitTranslation": [-0.07,0.08,0],
"portraitTranslation": [
-0.07,
0.08,
0
],
"profileScale": 0.7,
"profileTranslation": [0,0.7,0],
"profileTranslation": [
0,
0.7,
0
],
"rootBone": "zubat",
"animations": {
"cry": "q.bedrock_stateful('zubat', 'cry')",
@@ -104,7 +112,9 @@
]
},
"sleep": {
"poseTypes": ["SLEEP"],
"poseTypes": [
"SLEEP"
],
"animations": [
"q.bedrock('zubat', 'sleep')"
],
@@ -122,13 +132,35 @@
}
]
},
"roost": {
"poseTypes": [
"CLING_CEILING"
],
"animations": [
"q.bedrock('zubat', 'roost')"
],
"transformedParts": [
{
"part": "wings_folded",
"isVisible": true
},
{
"part": "wings_open",
"isVisible": false
}
]
},
"shoulder_left": {
"poseTypes": ["SHOULDER_LEFT"],
"poseTypes": [
"SHOULDER_LEFT"
],
"animations": [
"q.look('body')",
"q.bedrock('zubat', 'shoulder_left')"
],
"quirks": ["q.bedrock_quirk('zubat', 'eartwitch')"],
"quirks": [
"q.bedrock_quirk('zubat', 'eartwitch')"
],
"transformedParts": [
{
"part": "wings_folded",
@@ -141,12 +173,16 @@
]
},
"shoulder_right": {
"poseTypes": ["SHOULDER_RIGHT"],
"poseTypes": [
"SHOULDER_RIGHT"
],
"animations": [
"q.look('body')",
"q.bedrock('zubat', 'shoulder_right')"
],
"quirks": ["q.bedrock_quirk('zubat', 'eartwitch')"],
"quirks": [
"q.bedrock_quirk('zubat', 'eartwitch')"
],
"transformedParts": [
{
"part": "wings_folded",
@@ -157,6 +193,6 @@
"isVisible": false
}
]
}
}
}
}
}
@@ -1,8 +1,16 @@
{
"portraitScale": 1.55,
"portraitTranslation": [-0.06,0.07,0],
"portraitTranslation": [
-0.06,
0.07,
0
],
"profileScale": 0.7,
"profileTranslation": [0,0.7,0],
"profileTranslation": [
0,
0.7,
0
],
"rootBone": "golbat",
"animations": {
"cry": "q.bedrock_stateful('golbat', 'cry')"
@@ -92,13 +100,26 @@
]
},
"sleep": {
"poseTypes": ["SLEEP"],
"poseTypes": [
"SLEEP"
],
"animations": [
"q.bedrock('golbat', 'sleep')"
],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
}
},
"roost": {
"poseTypes": [
"CLING_CEILING"
],
"animations": [
"q.bedrock('golbat', 'roost')"
],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
}
}
}
}
@@ -1,41 +1,76 @@
{
"portraitScale": 1.58,
"portraitTranslation": [-0.03, -0.53, 0],
"portraitTranslation": [
-0.03,
-0.53,
0
],
"profileScale": 0.94,
"profileTranslation": [0, 0.29, 0],
"profileTranslation": [
0,
0.29,
0
],
"animations": {
"cry": "q.bedrock_stateful('weepinbell', 'cry')"
},
"poses": {
"battle-standing": {
"poseTypes": ["STAND"],
"poseTypes": [
"STAND"
],
"isBattle": true,
"animations": [
"q.look('head_ai')",
"q.bedrock('weepinbell', 'battle_idle')"
],
"quirks": ["q.bedrock_quirk('weepinbell', 'blink')"]
"quirks": [
"q.bedrock_quirk('weepinbell', 'blink')"
]
},
"standing": {
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"poseTypes": [
"STAND",
"NONE",
"PORTRAIT",
"PROFILE"
],
"isBattle": false,
"animations": [
"q.look('head_ai')",
"q.bedrock('weepinbell', 'ground_idle')"
],
"quirks": ["q.bedrock_quirk('weepinbell', 'blink')"]
"quirks": [
"q.bedrock_quirk('weepinbell', 'blink')"
]
},
"walking": {
"poseTypes": ["WALK"],
"poseTypes": [
"WALK"
],
"animations": [
"q.look('head_ai')",
"q.bedrock('weepinbell', 'ground_walk')"
],
"quirks": ["q.bedrock_quirk('weepinbell', 'blink')"]
"quirks": [
"q.bedrock_quirk('weepinbell', 'blink')"
]
},
"sleep": {
"poseTypes": ["SLEEP"],
"animations": ["q.bedrock('weepinbell', 'sleep')"]
"poseTypes": [
"SLEEP"
],
"animations": [
"q.bedrock('weepinbell', 'sleep')"
]
},
"hang": {
"poseTypes": [
"HANG"
],
"animations": [
"q.bedrock('weepinbell', 'hang')"
]
}
}
}
}
@@ -1,35 +1,55 @@
{
"rootBone": "spinarak",
"portraitScale": 2.8,
"portraitTranslation": [-0.35, -2.65, 0],
"portraitTranslation": [
-0.35,
-2.65,
0
],
"profileScale": 1.1,
"profileTranslation": [-0.1, 0, 0],
"animations": {
"cry": "q.bedrock_stateful('spinarak', 'cry')",
"recoil": "q.bedrock_stateful('spinarak', 'recoil')"
},
"poses": {
"profileTranslation": [
-0.1,
0,
0
],
"animations": {
"cry": "q.bedrock_stateful('spinarak', 'cry')",
"recoil": "q.bedrock_stateful('spinarak', 'recoil')"
},
"poses": {
"battle-standing": {
"poseTypes": ["STAND"],
"poseTypes": [
"STAND"
],
"isBattle": true,
"animations": [
"q.look('head')",
"q.bedrock('spinarak', 'battle_idle')"
],
"quirks": ["q.bedrock_quirk('spinarak', 'blink')","q.bedrock_quirk('spinarak', 'fang_quirk')"],
"namedAnimations": {
"sleep": "q.bedrock_primary('spinarak', 'battle_sleep')"
}
},
"quirks": [
"q.bedrock_quirk('spinarak', 'blink')",
"q.bedrock_quirk('spinarak', 'fang_quirk')"
],
"namedAnimations": {
"sleep": "q.bedrock_primary('spinarak', 'battle_sleep')"
}
},
"standing": {
"poseTypes": [
"STAND","PORTRAIT","PROFILE","NONE"
"STAND",
"PORTRAIT",
"PROFILE",
"NONE"
],
"animations": [
"q.look('head')",
"q.bedrock('spinarak', 'ground_idle')"
],
"quirks": ["q.bedrock_quirk('spinarak', 'blink')","q.bedrock_quirk('spinarak', 'fang_quirk')","q.bedrock_quirk('spinarak', 'look_quirk')"],
"quirks": [
"q.bedrock_quirk('spinarak', 'blink')",
"q.bedrock_quirk('spinarak', 'fang_quirk')",
"q.bedrock_quirk('spinarak', 'look_quirk')"
],
"transformTicks": 10
},
"walk": {
@@ -40,34 +60,80 @@
"q.look('head')",
"q.bedrock('spinarak', 'ground_walk')"
],
"quirks": ["q.bedrock_quirk('spinarak', 'blink')"],
"quirks": [
"q.bedrock_quirk('spinarak', 'blink')"
],
"transformTicks": 5
},
"sleep": {
"poseTypes": ["SLEEP"],
"animations": ["q.bedrock('spinarak', 'sleep')"]
},
"shoulder_left": {
"poseTypes": ["SHOULDER_LEFT"],
"animations": ["q.look('head')", "q.bedrock('spinarak', 'shoulder_left')"],
"quirks": ["q.bedrock_quirk('spinarak', 'blink')"],
"transformedParts": [
{
"part": "body",
"position": [6, 0, 0]
}
]
"sleep": {
"poseTypes": [
"SLEEP"
],
"animations": [
"q.bedrock('spinarak', 'sleep')"
]
},
"shoulder_right": {
"poseTypes": ["SHOULDER_RIGHT"],
"animations": ["q.look('head')", "q.bedrock('spinarak', 'shoulder_right')"],
"quirks": ["q.bedrock_quirk('spinarak', 'blink')"],
"shoulder_left": {
"poseTypes": [
"SHOULDER_LEFT"
],
"animations": [
"q.look('head')",
"q.bedrock('spinarak', 'shoulder_left')"
],
"quirks": [
"q.bedrock_quirk('spinarak', 'blink')"
],
"transformedParts": [
{
"part": "body",
"position": [-6, 0, 0]
"position": [
6,
0,
0
]
}
]
},
"shoulder_right": {
"poseTypes": [
"SHOULDER_RIGHT"
],
"animations": [
"q.look('head')",
"q.bedrock('spinarak', 'shoulder_right')"
],
"quirks": [
"q.bedrock_quirk('spinarak', 'blink')"
],
"transformedParts": [
{
"part": "body",
"position": [
-6,
0,
0
]
}
]
},
"hang": {
"poseTypes": [
"HANG"
],
"condition": "math.mod(q.entity_id, 2) == 0",
"animations": [
"q.bedrock('spinarak', 'hang')"
]
},
"hang2": {
"poseTypes": [
"HANG"
],
"condition": "math.mod(q.entity_id, 2) == 1",
"animations": [
"q.bedrock('spinarak', 'hang2')"
]
}
}
}
@@ -90,6 +90,24 @@
"sleep": {
"poseTypes": ["SLEEP"],
"animations": ["q.bedrock('ariados', 'sleep')"]
}
},
"hang": {
"poseTypes": [
"HANG"
],
"condition": "math.mod(q.entity_id, 2) == 0",
"animations": [
"q.bedrock('ariados', 'hang')"
]
},
"hang2": {
"poseTypes": [
"HANG"
],
"condition": "math.mod(q.entity_id, 2) == 1",
"animations": [
"q.bedrock('ariados', 'hang2')"
]
}
}
}
@@ -1,55 +1,100 @@
{
"portraitScale": 1.2,
"portraitTranslation": [-0.1, 1.8, 0],
"portraitTranslation": [
-0.1,
1.8,
0
],
"profileScale": 0.5,
"profileTranslation": [0, 1.2, 0],
"profileTranslation": [
0,
1.2,
0
],
"rootBone": "crobat",
"firstPersonCameraOffset": {
"seat_1": [0, 0.45, 0]
"seat_1": [
0,
0.45,
0
]
},
"thirdPersonCameraOffset": {
"seat_1": [0, 0.35, 0],
"seat_1_reverse": [0, 0.35, 0]
"seat_1": [
0,
0.35,
0
],
"seat_1_reverse": [
0,
0.35,
0
]
},
"thirdPersonCameraOffsetNoViewBobbing": {
"seat_1": [0, 0.35, 0],
"seat_1_reverse": [0, 0.35, 0]
"seat_1": [
0,
0.35,
0
],
"seat_1_reverse": [
0,
0.35,
0
]
},
"animations": {
"cry": "q.bedrock_stateful('crobat', 'cry')"
},
"animations": {
"cry": "q.bedrock_stateful('crobat', 'cry')"
},
"poses": {
"battle-standing": {
"poseTypes": ["STAND"],
"poseTypes": [
"STAND"
],
"isBattle": true,
"animations": [
"q.look('body', 0.5, 0.5)",
"q.bedrock('crobat', 'battle_idle')"
],
"quirks": ["q.bedrock_quirk('crobat', 'blink')"]
"quirks": [
"q.bedrock_quirk('crobat', 'blink')"
]
},
"standing": {
"poseTypes": ["STAND","PORTRAIT","PROFILE","NONE"],
"poseTypes": [
"STAND",
"PORTRAIT",
"PROFILE",
"NONE"
],
"isBattle": false,
"condition": "q.has_entity ? !q.in_air : 1.0",
"animations": [
"q.look('body', 0.5, 0.5)",
"q.bedrock('crobat', 'ground_idle')"
],
"quirks": ["q.bedrock_quirk('crobat', 'blink')"],
"quirks": [
"q.bedrock_quirk('crobat', 'blink')"
],
"transformTicks": 10
},
"walk": {
"poseTypes": ["WALK"],
"poseTypes": [
"WALK"
],
"animations": [
"q.look('body', 0.5, 0.5)",
"q.bedrock('crobat', 'ground_walk')"
],
"quirks": ["q.bedrock_quirk('crobat', 'blink')"],
"quirks": [
"q.bedrock_quirk('crobat', 'blink')"
],
"transformTicks": 5
},
"hover": {
"poseTypes": ["HOVER"],
"poseTypes": [
"HOVER"
],
"isBattle": false,
"animations": [
"q.pitch_tilt('body', 1)",
@@ -64,9 +109,11 @@
"q.bedrock_quirk('crobat', 'blink')"
],
"transformTicks": 5
},
},
"fly": {
"poseTypes": ["FLY"],
"poseTypes": [
"FLY"
],
"condition": "!q.is_gliding",
"isBattle": false,
"animations": [
@@ -83,7 +130,9 @@
"transformTicks": 5
},
"glide": {
"poseTypes": ["FLY"],
"poseTypes": [
"FLY"
],
"condition": "q.is_gliding",
"animations": [
"q.look('head')",
@@ -95,11 +144,32 @@
}
]
},
"sleep": {
"poseTypes": ["SLEEP"],
"animations": ["q.bedrock('crobat', 'sleep')"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
"sleep": {
"poseTypes": [
"SLEEP"
],
"animations": [
"q.bedrock('crobat', 'sleep')"
],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
}
},
"roost": {
"poseTypes": [
"CLING_CEILING"
],
"transformedParts": [
{
"part": "body",
"position": [0, -16, 0]
}
],
"animations": [
"q.bedrock('crobat', 'roost')"
],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
}
}
}
@@ -1,11 +1,18 @@
{
"portraitScale": 1.07,
"portraitTranslation": [-0.41,0.55,0],
"portraitTranslation": [
-0.41,
0.55,
0
],
"profileScale": 0.39,
"profileTranslation": [-0.08,0.9,-6],
"profileTranslation": [
-0.08,
0.9,
-6
],
"rootBone": "ferrothorn",
"animations": {
},
"animations": {},
"poses": {
"battle-standing": {
"poseTypes": [
@@ -57,6 +64,14 @@
"animations": [
"q.bedrock('ferrothorn', 'sleep')"
]
},
"cling_ceiling": {
"poseTypes": [
"CLING_CEILING"
],
"animations": [
"q.bedrock('ferrothorn', 'cling_ceiling')"
]
}
}
}
@@ -62,6 +62,14 @@
"quirks": [
"q.bedrock_quirk('riolu', 'blink')"
]
},
"cling_ceiling": {
"poseTypes": [
"CLING_CEILING"
],
"animations": [
"q.bedrock('noibat', 'cling_ceiling')"
]
}
}
}
@@ -111,6 +111,14 @@
"quirks": [
"q.bedrock_quirk('noivern', 'blink')"
]
},
"cling_ceiling": {
"poseTypes": [
"CLING_CEILING"
],
"animations": [
"q.bedrock('noivern', 'cling_ceiling')"
]
}
}
}
@@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "cobblemon:block/silk_thread" }
}
}
@@ -9474,4 +9474,4 @@
"stat.cobblemon.riding_land": "Distance by Pokémon on Land",
"stat.cobblemon.riding_air": "Distance by Pokémon in Air",
"stat.cobblemon.riding_liquid": "Distance by Pokémon in Liquid"
}
}
@@ -0,0 +1,5 @@
{
"textures": {
"particle": "minecraft:block/tripwire"
}
}
@@ -10,7 +10,25 @@
"5": [
{
"type": "find_resting_place",
"condition": "!q.entity.is_in_party"
"condition": "!q.entity.is_in_party",
"verticalSearchDistance": "16"
},
{
"type": "go_to_sleep",
"onlyFromStatus": "q.entity.is_in_party"
}
]
}
},
{
"type": "add_tasks_to_activity",
"activity": "cobblemon:pokemon_herd",
"tasksByPriority": {
"5": [
{
"type": "find_resting_place",
"condition": "!q.entity.is_in_party",
"verticalSearchDistance": "16"
},
{
"type": "go_to_sleep",
@@ -0,0 +1,14 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:string"
}
]
}
]
}
@@ -1,77 +1,109 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "caterpie-1",
"pokemon": "caterpie",
"presets": [
"natural",
"foliage",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_plains",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing",
"#cobblemon:is_spooky"
]
}
},
{
"id": "caterpie-valencian-2",
"pokemon": "caterpie valencian",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_jungle",
"#cobblemon:is_tropical_island"
]
}
},
{
"id": "caterpie-valencian-3",
"pokemon": "caterpie valencian",
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 4.5,
"condition": {
"biomes": [
"the_bumblezone:floral_meadow"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "caterpie-1",
"pokemon": "caterpie",
"presets": [
"natural",
"foliage",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_plains",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing",
"#cobblemon:is_spooky"
]
}
},
{
"id": "caterpie-valencian-2",
"pokemon": "caterpie valencian",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_jungle",
"#cobblemon:is_tropical_island"
]
}
},
{
"id": "caterpie-valencian-3",
"pokemon": "caterpie valencian",
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 4.5,
"condition": {
"biomes": [
"the_bumblezone:floral_meadow"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
},
{
"id": "caterpie-cling-1",
"pokemon": "caterpie",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_plains",
"aether:skyroot_forest",
"aether:skyroot_woodland"
],
"attachedTo": [
"#minecraft:logs"
],
"faces": [
"sides",
"ceiling"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing",
"#cobblemon:is_spooky"
]
}
}
]
}
@@ -1,77 +1,98 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "metapod-1",
"pokemon": "metapod",
"presets": [
"natural",
"foliage",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_plains",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing",
"#cobblemon:is_spooky"
]
}
},
{
"id": "metapod-valencian-2",
"pokemon": "metapod valencian",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_jungle",
"#cobblemon:is_tropical_island"
]
}
},
{
"id": "metapod-valencian-3",
"pokemon": "metapod valencian",
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "7-21",
"weight": 1.0,
"condition": {
"biomes": [
"the_bumblezone:floral_meadow"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "metapod-1",
"pokemon": "metapod",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_plains",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing",
"#cobblemon:is_spooky"
]
}
},
{
"id": "metapod-cling-1",
"pokemon": "metapod",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"attachedTo": [
"#minecraft:logs"
],
"faces": [
"sides",
"ceiling"
],
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_plains"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing",
"#cobblemon:is_spooky"
]
}
},
{
"id": "metapod-valencian-2",
"pokemon": "metapod valencian",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_jungle",
"#cobblemon:is_tropical_island"
]
}
},
{
"id": "metapod-valencian-3",
"pokemon": "metapod valencian",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "7-21",
"weight": 1.0,
"condition": {
"biomes": [
"the_bumblezone:floral_meadow"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
}
]
}
@@ -1,54 +1,85 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "weedle-1",
"pokemon": "weedle",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "weedle-2",
"pokemon": "weedle",
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 3.0,
"condition": {
"biomes": [
"#the_bumblezone:the_bumblezone"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "weedle-1",
"pokemon": "weedle",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "weedle-2",
"pokemon": "weedle",
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-20",
"weight": 3.0,
"condition": {
"biomes": [
"#the_bumblezone:the_bumblezone"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
},
{
"id": "weedle-cling-1",
"pokemon": "weedle",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "1-20",
"weight": 7.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"aether:skyroot_forest",
"aether:skyroot_woodland"
],
"attachedTo": [
"#minecraft:logs"
],
"faces": [
"sides",
"ceiling"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
}
]
}
@@ -1,54 +1,78 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "kakuna-1",
"pokemon": "kakuna",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "kakuna-2",
"pokemon": "kakuna",
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"biomes": [
"#the_bumblezone:the_bumblezone"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "kakuna-1",
"pokemon": "kakuna",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"aether:skyroot_forest",
"aether:skyroot_woodland"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "kakuna-cling-1",
"pokemon": "kakuna",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"attachedTo": [
"#minecraft:logs"
],
"faces": [
"sides"
],
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "kakuna-2",
"pokemon": "kakuna",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "7-21",
"weight": 2.0,
"condition": {
"biomes": [
"#the_bumblezone:the_bumblezone"
]
},
"anticondition": {
"structures": [
"#the_bumblezone:sempiternal_sanctums"
]
}
}
]
}
@@ -1,26 +1,42 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "weepinbell-1",
"pokemon": "weepinbell",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "21-39",
"weight": 0.95,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_jungle"
]
}
}
]
}
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "weepinbell-1",
"pokemon": "weepinbell",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "21-39",
"weight": 0.95,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_jungle"
]
}
},
{
"id": "weepinbell-hanging-1",
"pokemon": "weepinbell",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "21-39",
"weight": 0.95,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_jungle"
]
}
}
]
}
@@ -1,122 +1,206 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "spinarak-1",
"pokemon": "spinarak",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 5.4,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"#cobblemon:is_spooky"
],
"timeRange": "night",
"isRaining": false
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "spinarak-2",
"pokemon": "spinarak",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 1.8,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_overworld"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_deep_dark"
]
}
},
{
"id": "spinarak-3",
"pokemon": "spinarak",
"presets": [
"derelict"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 5.4,
"condition": {
"canSeeSky": false,
"biomes": [
"#cobblemon:is_overworld"
],
"minY": 0
},
"anticondition": {
"biomes": [
"#cobblemon:is_deep_dark"
]
}
},
{
"id": "spinarak-4",
"pokemon": "spinarak",
"presets": [
"webs",
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 9.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7
}
},
{
"id": "spinarak-5",
"pokemon": "spinarak",
"presets": [
"mansion"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 9.0,
"condition": {
"canSeeSky": false,
"biomes": [
"#cobblemon:is_overworld"
],
"neededNearbyBlocks": [
"minecraft:cobweb"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "spinarak-1",
"pokemon": "spinarak",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 5.4,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"#cobblemon:is_spooky"
],
"timeRange": "night",
"isRaining": false
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "spinarak-2",
"pokemon": "spinarak",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 1.8,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_overworld"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_deep_dark"
]
}
},
{
"id": "spinarak-3",
"pokemon": "spinarak",
"presets": [
"derelict"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 5.4,
"condition": {
"canSeeSky": false,
"biomes": [
"#cobblemon:is_overworld"
],
"minY": 0
},
"anticondition": {
"biomes": [
"#cobblemon:is_deep_dark"
]
}
},
{
"id": "spinarak-4",
"pokemon": "spinarak",
"presets": [
"webs",
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 9.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7
}
},
{
"id": "spinarak-5",
"pokemon": "spinarak",
"presets": [
"mansion"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-25",
"weight": 9.0,
"condition": {
"canSeeSky": false,
"biomes": [
"#cobblemon:is_overworld"
],
"neededNearbyBlocks": [
"minecraft:cobweb"
]
}
},
{
"id": "spinarak-hanging-1",
"pokemon": "spinarak",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "1-25",
"weight": 5.4,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"#cobblemon:is_spooky"
],
"timeRange": "night",
"isRaining": false
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "spinarak-cling-1",
"pokemon": "spinarak",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "1-25",
"weight": 5.4,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"attachedTo": [
"#minecraft:logs"
],
"faces": [
"sides"
],
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"#cobblemon:is_spooky"
],
"timeRange": "night",
"isRaining": false
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
},
{
"id": "spinarak-cling-2",
"pokemon": "spinarak",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "1-25",
"weight": 5.4,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_forest",
"#cobblemon:is_jungle",
"#cobblemon:is_spooky"
],
"timeRange": "night",
"isRaining": false,
"faces": [
"ceiling"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_freezing"
]
}
}
]
}
@@ -1,27 +1,23 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "pineco-1",
"pokemon": "pineco",
"presets": [
"natural",
"treetop"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "4-29",
"weight": 9.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_taiga"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "pineco-1",
"pokemon": "pineco",
"type": "pokemon",
"spawnablePositionType": "hanging",
"bucket": "common",
"level": "4-29",
"weight": 9.0,
"condition": {
"minSkyLight": 8,
"maxSkyLight": 15,
"biomes": [
"#cobblemon:is_taiga"
]
}
}
]
}
@@ -1,62 +1,85 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "ferroseed-1",
"pokemon": "ferroseed",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "6-31",
"weight": 9.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_lush"
]
},
"anticondition": {
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
}
},
{
"id": "ferroseed-2",
"pokemon": "ferroseed",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "6-31",
"weight": 9.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_overworld"
],
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
},
"anticondition": {
"biomes": [
"#cobblemon:is_lush"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "ferroseed-1",
"pokemon": "ferroseed",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "6-31",
"weight": 9.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_lush"
]
},
"anticondition": {
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
}
},
{
"id": "ferroseed-2",
"pokemon": "ferroseed",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "6-31",
"weight": 9.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_overworld"
],
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
},
"anticondition": {
"biomes": [
"#cobblemon:is_lush"
]
}
},
{
"id": "ferroseed-cling-1",
"pokemon": "ferroseed",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "6-31",
"weight": 9.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"attachedTo": [
"#minecraft:logs"
],
"faces": [
"sides"
],
"biomes": [
"#cobblemon:is_lush",
"#cobblemon:is_jungle"
]
}
}
]
}
@@ -1,62 +1,84 @@
{
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "ferrothorn-1",
"pokemon": "ferrothorn",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "40-49",
"weight": 1.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_lush"
]
},
"anticondition": {
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
}
},
{
"id": "ferrothorn-2",
"pokemon": "ferrothorn",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "40-49",
"weight": 1.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_overworld"
],
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
},
"anticondition": {
"biomes": [
"#cobblemon:is_lush"
]
}
}
]
"enabled": true,
"neededInstalledMods": [],
"neededUninstalledMods": [],
"spawns": [
{
"id": "ferrothorn-1",
"pokemon": "ferrothorn",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "40-49",
"weight": 1.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_lush"
]
},
"anticondition": {
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
}
},
{
"id": "ferrothorn-2",
"pokemon": "ferrothorn",
"presets": [
"natural"
],
"type": "pokemon",
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "40-49",
"weight": 1.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"biomes": [
"#cobblemon:is_overworld"
],
"structures": [
"cobblemon:shipwreck_coves/lush_shipwreck_cove"
],
"minY": -41,
"maxY": 9
},
"anticondition": {
"biomes": [
"#cobblemon:is_lush"
]
}
},
{
"id": "ferrothorn-cling-1",
"pokemon": "ferrothorn",
"type": "pokemon",
"spawnablePositionType": "clinging",
"bucket": "common",
"level": "40-49",
"weight": 1.0,
"condition": {
"minSkyLight": 0,
"maxSkyLight": 7,
"attachedTo": [
"#minecraft:base_stone_overworld"
],
"faces": [
"ceiling"
],
"biomes": [
"#cobblemon:is_lush"
]
}
}
]
}
@@ -57,7 +57,14 @@
"light": "0-4",
"willSleepOnBed": true,
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"moving": {
"swim": {
@@ -59,6 +59,11 @@
"drowsyChance": 0.0333,
"rouseChance": 0.0042
},
"clinging": {
"canClingToWalls": true,
"canClingToCeilings": true,
"xOffset": 0.15
},
"moving": {
"walk": {
"walkSpeed": 0.26
@@ -58,9 +58,17 @@
}
},
"resting": {
"canSleep": true,
"light": "0-4",
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -63,11 +63,27 @@
"resting": {
"canSleep": true,
"light": "0-4",
"canSeeSky": false,
"times": [
"any"
"day"
],
"drowsyChance": 0.0014,
"rouseChance": 0.0042
"drowsyChance": 0.5,
"rouseChance": 0.002,
"places": [
{
"faces": ["ceiling"],
"onlyAir": true
},
{
"faces": ["ceiling"],
"blocks": ["#minecraft:leaves"],
"onlyAir": true,
"light": "0-15"
}
]
},
"clinging": {
"yOffset": -0.2
},
"herd": {
"maxSize": "9",
@@ -55,6 +55,10 @@
"drowsyChance": 0.0333,
"rouseChance": 0.0042
},
"clinging": {
"canClingToWalls": true,
"xOffset": 0.3
},
"moving": {
"walk": {
"canWalk": false
@@ -130,4 +134,4 @@
}
}
]
}
}
@@ -57,6 +57,11 @@
"drowsyChance": 0.0333,
"rouseChance": 0.0042
},
"clinging": {
"canClingToWalls": true,
"canClingToCeilings": true,
"xOffset": 0.15
},
"moving": {
"walk": {
"canWalk": false
@@ -130,4 +135,4 @@
}
}
]
}
}
@@ -150,9 +150,17 @@
}
},
"resting": {
"canSleep": true,
"drowsyChance": 0.0333,
"light": "0-4",
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
}
},
"drops": {
@@ -62,7 +62,14 @@
"canSleep": true,
"light": "0-4",
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"combat": {
"fightsMelee": true,
@@ -64,7 +64,14 @@
"light": "0-4",
"willSleepOnBed": true,
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"combat": {
"willDefendOwner": true
@@ -59,10 +59,18 @@
}
},
"resting": {
"canSleep": true,
"light": "0-4",
"willSleepOnBed": true,
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -68,7 +68,14 @@
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"combat": {
"willDefendOwner": true
@@ -57,6 +57,11 @@
"drowsyChance": 0.0333,
"rouseChance": 0.0042
},
"clinging": {
"canClingToWalls": true,
"canClingToCeilings": true,
"xOffset": 0.15
},
"moving": {
"walk": {
"walkSpeed": 0.26
@@ -118,4 +123,4 @@
]
}
]
}
}
@@ -67,6 +67,10 @@
"drowsyChance": 0.0014,
"rouseChance": 0.0042
},
"hanging": {
"usesThread": false,
"yOffset": -0.6
},
"combat": {
"willDefendOwner": true
}
@@ -212,4 +216,4 @@
"requiredContext": "cobblemon:leaf_stone"
}
]
}
}
@@ -64,12 +64,28 @@
"resting": {
"canSleep": true,
"light": "0-4",
"canSeeSky": false,
"willSleepOnBed": true,
"times": [
"any"
"day"
],
"drowsyChance": 0.0014,
"rouseChance": 0.0042
"drowsyChance": 0.5,
"rouseChance": 0.002,
"places": [
{
"faces": ["ceiling"],
"onlyAir": true
},
{
"faces": ["ceiling"],
"blocks": ["#minecraft:leaves"],
"onlyAir": true,
"light": "0-15"
}
]
},
"clinging": {
"yOffset": -0.2
},
"herd": {
"maxSize": "9",
@@ -139,12 +139,28 @@
},
"resting": {
"canSleep": true,
"drowsyChance": 0.0014,
"drowsyChance": 0.5,
"light": "0-4",
"rouseChance": 0.0042,
"canSeeSky": false,
"rouseChance": 0.002,
"times": [
"any"
"day"
],
"places": [
{
"faces": ["ceiling"],
"onlyAir": true
},
{
"faces": ["ceiling"],
"blocks": ["#minecraft:leaves"],
"onlyAir": true,
"light": "0-15"
}
]
},
"clinging": {
"yOffset": -0.2
}
},
"drops": {
@@ -112,10 +112,18 @@
}
},
"resting": {
"canSleep": true,
"drowsyChance": 0.0021,
"rouseChance": 0.0042,
"times": [
"167-11833,13702-22299"
],
"places": [
{
"faces": ["sides"],
"blocks": ["#cobblemon:saccharine_logs"],
"light": "0-15"
}
]
}
},
@@ -66,7 +66,14 @@
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "4",
@@ -69,7 +69,14 @@
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -67,7 +67,14 @@
"light": "0-4",
"willSleepOnBed": true,
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -69,7 +69,14 @@
],
"willSleepOnBed": true,
"drowsyChance": 0.0014,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -65,11 +65,19 @@
"maxSize": "5"
},
"resting": {
"canSleep": true,
"times": [
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"combat": {
"willDefendOwner": true
@@ -238,6 +238,11 @@
"drowsyChance": 0.0014,
"rouseChance": 0.0042
},
"clinging": {
"canClingToWalls": true,
"canClingToCeilings": true,
"xOffset": 0.15
},
"moving": {
"swim": {
"avoidsWater": true
@@ -252,4 +257,4 @@
"immuneToCobwebBlock": true
}
}
}
}
@@ -53,7 +53,14 @@
"resting": {
"canSleep": true,
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"moving": {
"fly": {
@@ -65,8 +65,16 @@
"willDefendOwner": true
},
"resting": {
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"canSleep": true,
"drowsyChance": 0.5,
"rouseChance": 0.002,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
}
},
"drops": {
@@ -131,7 +131,14 @@
"canSleep": true,
"drowsyChance": 0.0333,
"light": "0-4",
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
}
},
"drops": {
@@ -169,9 +169,17 @@
"evolutions": [],
"behaviour": {
"resting": {
"canSleep": true,
"willSleepOnBed": true,
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"moving": {
"swim": {
@@ -172,12 +172,20 @@
"evolutions": [],
"behaviour": {
"resting": {
"canSleep": true,
"willSleepOnBed": true,
"times": [
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"moving": {
"swim": {
@@ -66,7 +66,14 @@
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "2",
@@ -70,7 +70,14 @@
"willSleepOnBed": true,
"light": "0-4",
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -61,7 +61,14 @@
"canSleep": true,
"light": "0-4",
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -63,7 +63,14 @@
"willSleepOnBed": true,
"light": "0-4",
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "9",
@@ -54,7 +54,16 @@
"canSleep": true,
"light": "0-4",
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"light": "0-15"
}
]
},
"clinging": {
"xOffset": -0.1
},
"moving": {
"fly": {
@@ -66,7 +66,14 @@
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"herd": {
"maxSize": "2",
@@ -69,9 +69,17 @@
]
},
"resting": {
"canSleep": true,
"willSleepOnBed": true,
"drowsyChance": 0.0333,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"combat": {
"willDefendOwner": true
@@ -76,7 +76,14 @@
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["floor"],
"blocks": ["#minecraft:leaves"],
"light": "0-15"
}
]
},
"combat": {
"willDefendSelf": true,
@@ -162,12 +162,20 @@
"evolutions": [],
"behaviour": {
"resting": {
"canSleep": true,
"willSleepOnBed": true,
"times": [
"day"
],
"drowsyChance": 0.0033,
"rouseChance": 0.0042
"rouseChance": 0.0042,
"places": [
{
"faces": ["sides"],
"blocks": ["#minecraft:logs"],
"light": "0-15"
}
]
},
"moving": {
"swim": {

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