mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-20 14:16:26 -04:00
Improved land wandering, added path type filtering to pokemon pathing
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
- Nodemaker bug, it thinks jumps are possible from water up an entire block - they aint
|
||||||
|
https://gyazo.com/759b8285e7c07046ff2e54adf0d7a7ac
|
||||||
|
|
||||||
|
- Why is magikarp trying to path through ice
|
||||||
|
https://gyazo.com/ae230758c529f885eeb0dd91e60530d2
|
||||||
|
|
||||||
|
- We should use mixins to put the path node filtering from OmniPathNodeMaker in the base classes otherwise
|
||||||
|
NPC wandering will be jank too.
|
||||||
@@ -37,7 +37,7 @@ object CobblemonMemories {
|
|||||||
val POKEMON_DROWSY = register("pokemon_drowsy", PrimitiveCodec.BOOL)
|
val POKEMON_DROWSY = register("pokemon_drowsy", PrimitiveCodec.BOOL)
|
||||||
val POKEMON_SLEEPING = register("pokemon_sleeping", PrimitiveCodec.BOOL)
|
val POKEMON_SLEEPING = register("pokemon_sleeping", PrimitiveCodec.BOOL)
|
||||||
val POKEMON_BATTLE = register<UUID>("pokemon_battle")
|
val POKEMON_BATTLE = register<UUID>("pokemon_battle")
|
||||||
val PATH_COOLDOWN = register("path_cooldown", PrimitiveCodec.BOOL)
|
val PATH_COOLDOWN = register<Boolean>("path_cooldown")
|
||||||
val TARGETED_BATTLE_POKEMON = register<UUID>("targeted_battle_pokemon")
|
val TARGETED_BATTLE_POKEMON = register<UUID>("targeted_battle_pokemon")
|
||||||
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
|
val NEAREST_VISIBLE_ATTACKER = register<LivingEntity>("nearest_visible_attacker")
|
||||||
val NEARBY_GROWABLE_CROPS = register<BlockPos>("nearby_growable_crops")
|
val NEARBY_GROWABLE_CROPS = register<BlockPos>("nearby_growable_crops")
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ class FindAirTaskConfig : SingleTaskConfig {
|
|||||||
val blockPos = entity.closestPosition(iterable) { isAirPos(entity.level(), it) }
|
val blockPos = entity.closestPosition(iterable) { isAirPos(entity.level(), it) }
|
||||||
?: return@Trigger false
|
?: return@Trigger false
|
||||||
|
|
||||||
walkTarget.set(WalkTarget(blockPos.above(), 0.35F, 1))
|
walkTarget.set(WalkTarget(blockPos.above(), 0.35F, 0))
|
||||||
return@Trigger true
|
return@Trigger true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+66
-69
@@ -12,25 +12,17 @@ import com.cobblemon.mod.common.CobblemonMemories
|
|||||||
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
import com.cobblemon.mod.common.api.ai.BrainConfigurationContext
|
||||||
import com.cobblemon.mod.common.api.ai.asVariables
|
import com.cobblemon.mod.common.api.ai.asVariables
|
||||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
|
||||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
|
||||||
import com.cobblemon.mod.common.util.canFit
|
|
||||||
import com.cobblemon.mod.common.util.toVec3d
|
|
||||||
import com.cobblemon.mod.common.util.withQueryValue
|
import com.cobblemon.mod.common.util.withQueryValue
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.tags.BlockTags
|
|
||||||
import net.minecraft.world.entity.LivingEntity
|
import net.minecraft.world.entity.LivingEntity
|
||||||
import net.minecraft.world.entity.PathfinderMob
|
import net.minecraft.world.entity.PathfinderMob
|
||||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||||
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
|
||||||
import net.minecraft.world.entity.ai.behavior.RandomStroll
|
|
||||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
|
||||||
import net.minecraft.world.entity.ai.util.LandRandomPos
|
import net.minecraft.world.entity.ai.util.LandRandomPos
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.pathfinder.PathType
|
||||||
import net.minecraft.world.phys.Vec3
|
|
||||||
|
|
||||||
class WanderTaskConfig : SingleTaskConfig {
|
class WanderTaskConfig : SingleTaskConfig {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -76,69 +68,74 @@ class WanderTaskConfig : SingleTaskConfig {
|
|||||||
|
|
||||||
pathCooldown.setWithExpiry(true, 40L)
|
pathCooldown.setWithExpiry(true, 40L)
|
||||||
|
|
||||||
val targetVec = getLandTarget(entity) ?: return@Trigger true //LandRandomPos.getPos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt()) ?: return@Trigger false
|
// val targetVec = getLandTarget(entity) ?: return@Trigger true
|
||||||
walkTarget.set(WalkTarget(targetVec, speedMultiplier.resolveFloat(), 1))
|
val targetVec = LandRandomPos.getPos(entity, horizontalRange.resolveInt(), verticalRange.resolveInt()) ?: return@Trigger false
|
||||||
lookTarget.set(BlockPosTracker(targetVec.add(0.0, entity.eyeHeight.toDouble(), 0.0)))
|
val pos = BlockPos.containing(targetVec)
|
||||||
|
walkTarget.set(CobblemonWalkTarget(pos, speedMultiplier.resolveFloat(), 0, { it !in listOf(PathType.WATER, PathType.WATER_BORDER) }))
|
||||||
|
lookTarget.erase()
|
||||||
return@Trigger true
|
return@Trigger true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION", "MemberVisibilityCanBePrivate")
|
/*
|
||||||
fun getLandTarget(entity: PathfinderMob): Vec3? {
|
* This method is from the old wander goal. It is very verbose but reliably finds decent land wander targets. Its only advantage over
|
||||||
val roamDistanceCondition: (BlockPos) -> Boolean = if (entity is PokemonEntity) ({ entity.tethering?.canRoamTo(it) != false }) else ({ true })
|
* the LandRandomPos method (with our CobblemonWalkTarget) is that it doesn't lead entities in the direction of water.
|
||||||
val iterable: Iterable<BlockPos> = BlockPos.randomBetweenClosed(entity.random, 64, entity.blockX - 10, entity.blockY, entity.blockZ - 10, entity.blockX + 10, entity.blockY, entity.blockZ + 10)
|
*/
|
||||||
val condition: (BlockState, BlockPos) -> Boolean = { _, pos -> entity.canFit(pos) && roamDistanceCondition(pos) }
|
// fun getLandTarget(entity: PathfinderMob): Vec3? {
|
||||||
val iterator = iterable.iterator()
|
// val roamDistanceCondition: (BlockPos) -> Boolean = if (entity is PokemonEntity) ({ entity.tethering?.canRoamTo(it) != false }) else ({ true })
|
||||||
position@
|
// val iterable: Iterable<BlockPos> = BlockPos.randomBetweenClosed(entity.random, 64, entity.blockX - 10, entity.blockY, entity.blockZ - 10, entity.blockX + 10, entity.blockY, entity.blockZ + 10)
|
||||||
while (iterator.hasNext()) {
|
// val condition: (BlockState, BlockPos) -> Boolean = { _, pos -> entity.canFit(pos) && roamDistanceCondition(pos) }
|
||||||
val pos = iterator.next().mutable()
|
// val iterator = iterable.iterator()
|
||||||
var blockState = entity.level().getBlockState(pos)
|
// position@
|
||||||
|
// while (iterator.hasNext()) {
|
||||||
val maxSteps = 16
|
// val pos = iterator.next().mutable()
|
||||||
var steps = 0
|
// var blockState = entity.level().getBlockState(pos)
|
||||||
var good = false
|
//
|
||||||
if (!blockState.isSolid && !blockState.liquid()) {
|
// val maxSteps = 16
|
||||||
pos.move(0, -1, 0)
|
// var steps = 0
|
||||||
var previousWasAir = true
|
// var good = false
|
||||||
while (steps++ < maxSteps && pos.y > entity.level().minBuildHeight) {
|
// if (!blockState.isSolid && !blockState.liquid()) {
|
||||||
if (pos.y <= entity.level().minBuildHeight) {
|
// pos.move(0, -1, 0)
|
||||||
continue@position
|
// var previousWasAir = true
|
||||||
}
|
// while (steps++ < maxSteps && pos.y > entity.level().minBuildHeight) {
|
||||||
blockState = entity.level().getBlockState(pos)
|
// if (pos.y <= entity.level().minBuildHeight) {
|
||||||
if (blockState.isSolid && !blockState.`is`(BlockTags.LEAVES) && previousWasAir) {
|
// continue@position
|
||||||
pos.move(0, 1, 0)
|
// }
|
||||||
blockState = entity.level().getBlockState(pos)
|
// blockState = entity.level().getBlockState(pos)
|
||||||
good = true
|
// if (blockState.isSolid && !blockState.`is`(BlockTags.LEAVES) && previousWasAir) {
|
||||||
break
|
// pos.move(0, 1, 0)
|
||||||
} else {
|
// blockState = entity.level().getBlockState(pos)
|
||||||
previousWasAir = blockState.isAir
|
// good = true
|
||||||
}
|
// break
|
||||||
pos.move(0, -1, 0)
|
// } else {
|
||||||
}
|
// previousWasAir = blockState.isAir
|
||||||
} else {
|
// }
|
||||||
var previousWasSolid = blockState.isSolid && !blockState.`is`(BlockTags.LEAVES)
|
// pos.move(0, -1, 0)
|
||||||
pos.move(0, 1, 0)
|
// }
|
||||||
while (steps++ < maxSteps) {
|
// } else {
|
||||||
if (pos.y >= entity.level().maxBuildHeight) {
|
// var previousWasSolid = blockState.isSolid && !blockState.`is`(BlockTags.LEAVES)
|
||||||
continue@position
|
// pos.move(0, 1, 0)
|
||||||
}
|
// while (steps++ < maxSteps) {
|
||||||
blockState = entity.level().getBlockState(pos)
|
// if (pos.y >= entity.level().maxBuildHeight) {
|
||||||
if (blockState.isAir && previousWasSolid) {
|
// continue@position
|
||||||
good = true
|
// }
|
||||||
break
|
// blockState = entity.level().getBlockState(pos)
|
||||||
}
|
// if (blockState.isAir && previousWasSolid) {
|
||||||
previousWasSolid = blockState.isSolid && !blockState.`is`(BlockTags.LEAVES)
|
// good = true
|
||||||
pos.move(0, 1, 0)
|
// break
|
||||||
}
|
// }
|
||||||
}
|
// previousWasSolid = blockState.isSolid && !blockState.`is`(BlockTags.LEAVES)
|
||||||
|
// pos.move(0, 1, 0)
|
||||||
if (good && condition(blockState, pos)) {
|
// }
|
||||||
return pos.toVec3d()
|
// }
|
||||||
}
|
//
|
||||||
}
|
// if (good && condition(blockState, pos)) {
|
||||||
|
// return pos.toVec3d()
|
||||||
return null
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// return null
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Cobblemon Contributors
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.cobblemon.mod.common.entity.ai
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos
|
||||||
|
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||||
|
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||||
|
import net.minecraft.world.level.pathfinder.PathType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a trick to allow us to instruct the node-maker to only consider specific node types,
|
||||||
|
* even if the entity can, in a pinch, use more.
|
||||||
|
*
|
||||||
|
* @author Hiroku
|
||||||
|
* @since March 24th, 2025
|
||||||
|
*/
|
||||||
|
class CobblemonWalkTarget(
|
||||||
|
pos: BlockPos,
|
||||||
|
speedModifier: Float,
|
||||||
|
completionRange: Int,
|
||||||
|
val nodeTypeFilter: (PathType) -> Boolean = { true },
|
||||||
|
) : WalkTarget(
|
||||||
|
BlockPosTracker(pos),
|
||||||
|
speedModifier,
|
||||||
|
completionRange
|
||||||
|
)
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
package com.cobblemon.mod.common.entity.ai
|
package com.cobblemon.mod.common.entity.ai
|
||||||
|
|
||||||
|
import com.cobblemon.mod.common.pokemon.ai.OmniPathNodeMaker
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.server.level.ServerLevel
|
import net.minecraft.server.level.ServerLevel
|
||||||
import net.minecraft.world.entity.PathfinderMob
|
import net.minecraft.world.entity.PathfinderMob
|
||||||
@@ -18,6 +19,7 @@ import net.minecraft.world.entity.ai.memory.MemoryStatus
|
|||||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||||
import net.minecraft.world.entity.ai.util.DefaultRandomPos
|
import net.minecraft.world.entity.ai.util.DefaultRandomPos
|
||||||
import net.minecraft.world.level.pathfinder.Path
|
import net.minecraft.world.level.pathfinder.Path
|
||||||
|
import net.minecraft.world.level.pathfinder.PathType
|
||||||
import net.minecraft.world.phys.Vec3
|
import net.minecraft.world.phys.Vec3
|
||||||
|
|
||||||
class FollowWalkTargetTask(
|
class FollowWalkTargetTask(
|
||||||
@@ -102,9 +104,22 @@ class FollowWalkTargetTask(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun withNodeFilter(entity: PathfinderMob, nodeFilter: (PathType) -> Boolean, block: () -> Unit) {
|
||||||
|
val nodeEvaluator = entity.navigation.nodeEvaluator
|
||||||
|
if (nodeEvaluator is OmniPathNodeMaker) {
|
||||||
|
nodeEvaluator.nodeFilter = nodeFilter
|
||||||
|
block()
|
||||||
|
nodeEvaluator.nodeFilter = { true }
|
||||||
|
} else {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun hasFinishedPath(entity: PathfinderMob, walkTarget: WalkTarget, time: Long): Boolean {
|
private fun hasFinishedPath(entity: PathfinderMob, walkTarget: WalkTarget, time: Long): Boolean {
|
||||||
val blockPos = walkTarget.target.currentBlockPosition()
|
val blockPos = walkTarget.target.currentBlockPosition()
|
||||||
|
withNodeFilter(entity, (walkTarget as? CobblemonWalkTarget)?.nodeTypeFilter ?: { true }) {
|
||||||
this.path = entity.navigation.createPath(blockPos, 0)
|
this.path = entity.navigation.createPath(blockPos, 0)
|
||||||
|
}
|
||||||
this.speed = walkTarget.speedModifier
|
this.speed = walkTarget.speedModifier
|
||||||
val brain = entity.brain
|
val brain = entity.brain
|
||||||
if (hasReached(entity, walkTarget)) {
|
if (hasReached(entity, walkTarget)) {
|
||||||
@@ -126,10 +141,12 @@ class FollowWalkTargetTask(
|
|||||||
10,
|
10,
|
||||||
7,
|
7,
|
||||||
Vec3.atBottomCenterOf(blockPos),
|
Vec3.atBottomCenterOf(blockPos),
|
||||||
1.5707963705062866
|
Math.PI / 2F
|
||||||
)
|
)
|
||||||
if (vec3d != null) {
|
if (vec3d != null) {
|
||||||
|
withNodeFilter(entity, (walkTarget as? CobblemonWalkTarget)?.nodeTypeFilter ?: { true }) {
|
||||||
this.path = entity.navigation.createPath(vec3d.x, vec3d.y, vec3d.z, 0)
|
this.path = entity.navigation.createPath(vec3d.x, vec3d.y, vec3d.z, 0)
|
||||||
|
}
|
||||||
return this.path != null
|
return this.path != null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,13 +12,9 @@ import net.minecraft.server.level.ServerLevel
|
|||||||
import net.minecraft.tags.FluidTags
|
import net.minecraft.tags.FluidTags
|
||||||
import net.minecraft.world.entity.PathfinderMob
|
import net.minecraft.world.entity.PathfinderMob
|
||||||
import net.minecraft.world.entity.ai.behavior.Behavior
|
import net.minecraft.world.entity.ai.behavior.Behavior
|
||||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
|
||||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
|
||||||
|
|
||||||
class StayAfloatTask(private val chance: Float = 0F) : Behavior<PathfinderMob>(
|
class StayAfloatTask(private val chance: Float = 0F) : Behavior<PathfinderMob>(
|
||||||
mapOf(
|
mapOf()
|
||||||
MemoryModuleType.WALK_TARGET to MemoryStatus.VALUE_ABSENT,
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
override fun checkExtraStartConditions(world: ServerLevel, entity: PathfinderMob): Boolean {
|
override fun checkExtraStartConditions(world: ServerLevel, entity: PathfinderMob): Boolean {
|
||||||
return entity.isInWater && entity.getFluidHeight(FluidTags.WATER) > entity.fluidJumpThreshold || entity.isInLava
|
return entity.isInWater && entity.getFluidHeight(FluidTags.WATER) > entity.fluidJumpThreshold || entity.isInLava
|
||||||
|
|||||||
+1
@@ -59,6 +59,7 @@ class EatGrassTask(
|
|||||||
|
|
||||||
override fun start(world: ServerLevel, entity: PokemonEntity, time: Long) {
|
override fun start(world: ServerLevel, entity: PokemonEntity, time: Long) {
|
||||||
timer = 40
|
timer = 40
|
||||||
|
entity.brain.setMemoryWithExpiry(CobblemonMemories.PATH_COOLDOWN, true, 40L)
|
||||||
entity.playAnimation("eat")
|
entity.playAnimation("eat")
|
||||||
world.broadcastEntityEvent(entity, 10.toByte())
|
world.broadcastEntityEvent(entity, 10.toByte())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,13 +125,9 @@ class Species : ClientDataSynchronizer<Species>, ShowdownIdentifiable {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
ApplyPresets().apply {
|
ApplyPresets().apply {
|
||||||
presets.add(cobblemonResource("floats"))
|
presets.addAll(listOf(cobblemonResource("floats"), cobblemonResource("avoids_water")))
|
||||||
condition = Either.left("!q.entity.behaviour.moving.swim.can_breathe_underwater".asExpression())
|
condition = Either.left("!q.entity.behaviour.moving.swim.can_breathe_underwater".asExpression())
|
||||||
},
|
},
|
||||||
ApplyPresets().apply {
|
|
||||||
presets.add(cobblemonResource("avoids_water"))
|
|
||||||
condition = Either.left("q.entity.behaviour.moving.swim.avoids_water".asExpression())
|
|
||||||
},
|
|
||||||
ApplyPresets().apply {
|
ApplyPresets().apply {
|
||||||
condition = Either.left("!q.entity.is_in_party".asExpression())
|
condition = Either.left("!q.entity.is_in_party".asExpression())
|
||||||
presets.add(cobblemonResource("pokemon_sleeps"))
|
presets.add(cobblemonResource("pokemon_sleeps"))
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
|||||||
|
|
||||||
var canPathThroughFire: Boolean = false
|
var canPathThroughFire: Boolean = false
|
||||||
|
|
||||||
|
var nodeFilter: (PathType) -> Boolean = { true }
|
||||||
|
|
||||||
override fun prepare(cachedWorld: PathNavigationRegion, entity: Mob) {
|
override fun prepare(cachedWorld: PathNavigationRegion, entity: Mob) {
|
||||||
super.prepare(cachedWorld, entity)
|
super.prepare(cachedWorld, entity)
|
||||||
nodePosToType.clear()
|
nodePosToType.clear()
|
||||||
@@ -188,6 +190,10 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isValidPathType(type: PathType): Boolean {
|
fun isValidPathType(type: PathType): Boolean {
|
||||||
|
if (!nodeFilter(type)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
(type == PathType.BREACH || type == PathType.WATER || type == PathType.WATER_BORDER) && canSwimInWater() -> true
|
(type == PathType.BREACH || type == PathType.WATER || type == PathType.WATER_BORDER) && canSwimInWater() -> true
|
||||||
type == PathType.OPEN && canFly() -> true
|
type == PathType.OPEN && canFly() -> true
|
||||||
|
|||||||
@@ -939,6 +939,7 @@
|
|||||||
"cobblemon.command.dialogue.invalid-dialogue": "Invalid dialogue identifier",
|
"cobblemon.command.dialogue.invalid-dialogue": "Invalid dialogue identifier",
|
||||||
"cobblemon.command.pc.invalid-box": "Box number %1$s exceeds max boxes of %2$s.",
|
"cobblemon.command.pc.invalid-box": "Box number %1$s exceeds max boxes of %2$s.",
|
||||||
"cobblemon.command.unlockablepcboxwallpaper.invalid-wallpaper": "Invalid wallpaper identifier",
|
"cobblemon.command.unlockablepcboxwallpaper.invalid-wallpaper": "Invalid wallpaper identifier",
|
||||||
|
"cobblemon.command.brainedit.non_scriptable": "You are not looking at a MoLang scriptable entity.",
|
||||||
|
|
||||||
"cobblemon.ui.generic.yes": "Yes",
|
"cobblemon.ui.generic.yes": "Yes",
|
||||||
"cobblemon.ui.generic.no": "No",
|
"cobblemon.ui.generic.no": "No",
|
||||||
@@ -2823,6 +2824,9 @@
|
|||||||
"cobblemon.brain_preset.avoids_water.name": "Avoids Water",
|
"cobblemon.brain_preset.avoids_water.name": "Avoids Water",
|
||||||
"cobblemon.brain_preset.avoids_water.desc": "Tries to find air and then gets away from water.",
|
"cobblemon.brain_preset.avoids_water.desc": "Tries to find air and then gets away from water.",
|
||||||
|
|
||||||
|
"cobblemon.brain_preset.pokemon_eats_grass.name": "Eats Grass",
|
||||||
|
"cobblemon.brain_preset.pokemon_eats_grass.desc": "The Pokémon occasionally eats grass underfoot.",
|
||||||
|
|
||||||
"cobblemon.move.10000000voltthunderbolt": "10,000,000 Volt Thunderbolt",
|
"cobblemon.move.10000000voltthunderbolt": "10,000,000 Volt Thunderbolt",
|
||||||
"cobblemon.move.10000000voltthunderbolt.desc": "The user, Pikachu wearing a cap, powers up a jolt of electricity using its Z-Power and unleashes it. Critical hits land more easily.",
|
"cobblemon.move.10000000voltthunderbolt.desc": "The user, Pikachu wearing a cap, powers up a jolt of electricity using its Z-Power and unleashes it. Critical hits land more easily.",
|
||||||
"cobblemon.move.absorb": "Absorb",
|
"cobblemon.move.absorb": "Absorb",
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "cobblemon.brain_preset.pokemon_eats_grass.name",
|
||||||
|
"description": "cobblemon.brain_preset.pokemon_eats_grass.desc",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "add_tasks_to_activity",
|
||||||
|
"activity": "idle",
|
||||||
|
"tasksByPriority": {
|
||||||
|
"2": [
|
||||||
|
"eat_grass"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -64,13 +64,8 @@
|
|||||||
},
|
},
|
||||||
"ai": [
|
"ai": [
|
||||||
{
|
{
|
||||||
"type": "add_tasks_to_activity",
|
"type": "apply_presets",
|
||||||
"activity": "idle",
|
"preset": "cobblemon:eats_grass"
|
||||||
"tasksByPriority": {
|
|
||||||
"2": [
|
|
||||||
"eat_grass"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"drops": {
|
"drops": {
|
||||||
|
|||||||
@@ -59,13 +59,8 @@
|
|||||||
},
|
},
|
||||||
"ai": [
|
"ai": [
|
||||||
{
|
{
|
||||||
"type": "add_tasks_to_activity",
|
"type": "apply_presets",
|
||||||
"activity": "idle",
|
"presets": ["cobblemon:eats_grass"]
|
||||||
"tasksByPriority": {
|
|
||||||
"2": [
|
|
||||||
"eat_grass"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"drops": {
|
"drops": {
|
||||||
|
|||||||
@@ -53,13 +53,8 @@
|
|||||||
},
|
},
|
||||||
"ai": [
|
"ai": [
|
||||||
{
|
{
|
||||||
"type": "add_tasks_to_activity",
|
"type": "apply_presets",
|
||||||
"activity": "idle",
|
"presets": ["cobblemon:eats_grass"]
|
||||||
"tasksByPriority": {
|
|
||||||
"2": [
|
|
||||||
"eat_grass"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"standingEyeHeight": 0.6,
|
"standingEyeHeight": 0.6,
|
||||||
|
|||||||
Reference in New Issue
Block a user