Compare commits

..
61 Commits
Author SHA1 Message Date
Hiroku 0bc5bb5caa Snap off and changelog updates 2026-09-13 08:03:56 +10:00
Hiroku 3330941a2c Merge remote-tracking branch 'origin/lang-updates' 2026-09-13 07:58:31 +10:00
Polymeta 79ea082d7e Merge branch '1.8.1-final-engi-fixes' into 'main'
1.8.1 final engi fixes

See merge request cable-mc/cobblemon!2404
2026-09-12 20:09:26 +00:00
Kenji_64 3d78929ff0 Entire Applin line has placeholder anims now! + other Applin related minor fixes 2026-09-12 21:36:12 +02:00
Kenji_64 5d94b03f7a Fixed Lucario's aura particles not emitting 2026-09-12 21:32:48 +02:00
Kenji_64 587305eb52 Added Fickle Beam's double damage text to en_us 2026-09-12 21:28:52 +02:00
Polymeta e363ce5e0e Merge branch 'Log-Spam-Fix' into 'main'
Fixed console spam with carved_ice_spikes. Fixed air pockets in deep sea spires

See merge request cable-mc/cobblemon!2403
2026-09-12 17:14:50 +00:00
Slippy e49b704200 Fixed console spam with carved_ice_spikes. Fixed air pockets in deep sea spires 2026-09-12 11:39:48 -05:00
Polymeta ec8b35860c Merge branch '1.8.1-implementation-fixes' into 'main'
fixed sableye's shoulder mount animations (thanks @kiteman.exe from discord)

See merge request cable-mc/cobblemon!2402
2026-09-12 06:40:07 +00:00
ewwww 74c49bf2da fixed sableye's shoulder mount animations (thanks @kiteman.exe from discord) 2026-09-11 22:39:37 -04:00
Gustavo PuerariandWeblate c03e7d9ed3 Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.8% (9175 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-10 18:30:26 +00:00
Polymeta b54f2442c9 Merge branch '1.8.1-implementation-fixes' into 'main'
1.8.1 implementation fixes (again)

See merge request cable-mc/cobblemon!2393
2026-09-10 12:07:05 +00:00
Jerzykv 62c0545ea7 Moved recent implement_pokemon fixes to this branch 2026-09-10 13:49:26 +02:00
Polymeta f821abd7e5 fix helditem notation in spawn file 2026-09-10 11:04:04 +00:00
Gustavo PuerariandWeblate 2652e53e0c Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.0% (9097 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-10 10:03:46 +00:00
Polymeta 08ac7d478d Merge branch 'shoulder-fix' into 'main'
Fixed Pokémon on shoulders not animating if they are visibly holding a held item.

Closes #1859

See merge request cable-mc/cobblemon!2392
2026-09-10 09:37:54 +00:00
Polymeta 4f51016ca9 Merge branch '1.8.1-implementation-fixes' into 'main'
1.8.1-implementation-fixes

See merge request cable-mc/cobblemon!2390
2026-09-10 09:34:16 +00:00
Paul ef8b4fd3cd Fixed Pokémon on shoulders not animating if they are visibly holding a held item.
Closes #1859
2026-09-10 19:20:36 +10:00
FrankTheFarmer f55972c190 Mantyke, Mantine, Quaxly recoil expression changelog 2026-09-10 19:15:14 +10:00
FrankTheFarmer 2dbf304ebe Merge branch 'main' into 1.8.1-implementation-fixes 2026-09-10 19:08:55 +10:00
FrankTheFarmer 1c5feab9c9 Removed recoil animation from Mantyke, Mantine, and Quaxly 2026-09-10 19:08:35 +10:00
Paul 1c720793c4 Rescraped spawns 2026-09-10 18:56:17 +10:00
FrankTheFarmer 6a170f8ce8 Merge branch 'main' into 1.8.1-implementation-fixes 2026-09-10 18:09:00 +10:00
Polymeta b4aba94f89 bump neoforge.mods.toml loaderVersion to be in line with what cobblemon is built against
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-09-10 08:22:19 +01:00
Polymeta 9832730f5c Merge branch 'Ancient-Wellspring-&-Chorus-Briar-Fixes' into 'main'
Ancient Wellsprings now how the correct habitat spawn pool. Chorus Briars no...

See merge request cable-mc/cobblemon!2391
2026-09-10 06:53:35 +00:00
Slippy ffdaec3e15 Ancient Wellsprings now how the correct habitat spawn pool. Chorus Briars no longer have air pockets. 2026-09-10 01:50:38 -05:00
ewwww d481f887a8 i just wanted to make it tinier c: 2026-09-10 02:47:35 -04:00
ewwww df3aec6222 updated region bias pack icon 2026-09-10 02:47:23 -04:00
Gustavo PuerariandWeblate b423fb1c46 Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.4% (9040 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-10 00:39:17 +00:00
Gustavo PuerariandWeblate 8ae26a268a Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.1% (9016 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-10 00:11:34 +00:00
Gustavo PuerariandWeblate 39b522abcc Translated using Weblate (Portuguese (Brazil))
Currently translated at 95.0% (9005 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-10 00:05:18 +00:00
Gustavo PuerariandWeblate 9bcfcef4fd Translated using Weblate (Portuguese (Brazil))
Currently translated at 94.8% (8983 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-09 23:29:29 +00:00
Gustavo PuerariandWeblate 60ac2d8058 Translated using Weblate (Portuguese (Brazil))
Currently translated at 94.4% (8947 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-09 23:06:46 +00:00
Gustavo PuerariandWeblate 9366d28141 Translated using Weblate (Portuguese (Brazil))
Currently translated at 94.4% (8946 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-09-09 22:24:00 +00:00
阿鱼andWeblate 75b48196b7 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (9472 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-09-09 14:13:55 +00:00
FrankTheFarmer 5180e2b501 Changelog for blastoise mount fix 2026-09-09 22:42:08 +10:00
FrankTheFarmer bb407b1d65 Removed unintentional second seat for Blastoise mount 2026-09-09 22:40:02 +10:00
FrankTheFarmer 8b308e5595 RIP Hisiuan Melon 2026-09-09 22:16:18 +10:00
FrankTheFarmer 148526e5e8 Added a blank watermelon png to prevent unintentional applications of melon cosmetic for hisuian electrode 2026-09-09 22:13:45 +10:00
FrankTheFarmer f319efcf12 Removed Hisuian Electrode's ability to turn into a watermelon. witermlon 2026-09-09 22:13:02 +10:00
Polymeta 5055e3926c Merge branch '1.8.1-engi-fixes' into 'main'
ampharos + alolan raticate fixes

See merge request cable-mc/cobblemon!2387
2026-09-09 08:05:11 +00:00
ewwww 3d92de18b8 ampharos + alolan raticate fixes 2026-09-09 03:47:57 -04:00
Polymeta ab9851fd12 fixed size altering effect and ensure pokemon dont get too small to live
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-09-09 08:05:55 +01:00
Polymeta a9df6bc709 Merge branch 'pokeball-catchrate-fix' into 'main'
Fixed Beast, Moon, Love, Timer and Luxury Ball behaviour not matching their tooltips

Closes #2062, #2063, #2064, #2065, and #2066

See merge request cable-mc/cobblemon!2384
2026-09-09 06:33:15 +00:00
Polymeta 3681813976 Merge branch 'misc-bug-fixes' into 'main'
Fix spawn file typos and type gem cluster bug.

See merge request cable-mc/cobblemon!2386
2026-09-08 14:38:12 +00:00
Polymeta 333d234dbe [skip-ci] push new tag documentation for 1.8
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-09-08 10:21:46 +01:00
Deltric ee42825dc3 Fix spawn file typos and type gem cluster bug. 2026-09-07 15:31:10 -05:00
Paul 0d9a4f9392 Some changelog [skip-ci] 2026-09-07 20:04:41 +10:00
Kiritiop 5e90c05fdd Fixed Beast, Moon, Love, Timer and Luxury Ball behaviour not matching their tooltips
Closes #2062
Closes #2063
Closes #2064
Closes #2065
Closes #2066
2026-09-07 05:42:05 +00:00
Hiroku 9a0648d956 Merge branch 'issue-2061' into 'main'
Fixed the TM Machine rejecting moves unlocked by unlockAllMoveDexMovesByDefault

Closes #2061

See merge request cable-mc/cobblemon!2383
2026-09-07 01:43:53 +00:00
Paul 91187ce952 Fixed NPCs getting their own TM progress file. Closes #2059 2026-09-07 11:42:33 +10:00
Hiroku 686bc62996 Merge branch 'refactor/molang-fn-code-smell' into 'main'
style: MoLang functions autumn codestyle cleanup

See merge request cable-mc/cobblemon!2368
2026-09-07 01:22:48 +00:00
Hiroku 5925247ace Merge branch 'wing_flap_fix' into 'main'
Removed incorrect sound keyframes from Rufflet, Braviary and Hisuian Braviary

See merge request cable-mc/cobblemon!2381
2026-09-07 01:05:11 +00:00
Kiritiop c6a4bec3f3 Fixed the TM Machine rejecting moves unlocked by unlockAllMoveDexMovesByDefault
The server-side guard in SetActiveTMPacketHandler ignored the config, so it rejected every move the config had revealed.

Closes #2061
2026-09-07 01:01:17 +00:00
Hiroku 7e582090f8 Merge branch 'issue-1774v2' into 'main'
Fixed stat_compare and stat_equal evolution requirements crashing on special stats (Version 2)

Closes #1774

See merge request cable-mc/cobblemon!2373
2026-09-07 00:25:47 +00:00
Kiritiop 55eef6ea69 Fixed stat_compare and stat_equal evolution requirements crashing on special stats
Stats.getStat did not recognise special_attack or special_defence and fell through to ACCURACY, which has no IV entry, so the requirement threw a NullPointerException from the server tick loop. Added the identifier names to getStat and made both requirements fail instead of crash for any non-permanent stat.

Closes #1774
2026-09-07 00:18:45 +00:00
Watuneni iteiteandWeblate f65cb9538c Translated using Weblate (Japanese)
Currently translated at 100.0% (9472 of 9472 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-09-06 14:57:47 +00:00
Sterrezo 8dbce8fefe Removed incorrect sound keyframes from Rufflet, Braviary and Hisuian Braviary 2026-09-06 10:00:31 +02:00
Gitoido d034469ebb style: additional cleanups 2026-09-05 16:00:00 +03:00
Gitoido 4f8a44c95b style: missed one return 2026-09-05 12:52:22 +00:00
Gitoido 52b17ca39e style: homogeneous code style in molang function classes 2026-09-05 12:52:22 +00:00
157 changed files with 11131 additions and 3745 deletions
+34 -18
View File
@@ -1,25 +1,41 @@
# Changelog
## [1.x.x (MONTH Xth, 2026)](#1-x-x)
### Additions
### New rideable Pokémon
### Pokémon Added
### Model updates for the following Pokémon
## [1.8.1 (September 13th, 2026)](#1-8-1)
### Animation updates for the following Pokémon
### Changes
- Flapple, Appletun, Dipplin, Hydrapple (placeholder animations only).
### Fixes
### Developer
### Molang & Datapacks
### Particles
- Fixed a potential world generation stall caused by Type Gem clusters.
- Fixed Pokémon on shoulders not animating if they are visibly holding a held item.
- Fixed NPCs getting their own TM progress file.
- Fixed odd NeoForge crash due to a dependency being outdated. It will now correctly flag the dependency for being outdated.
- Fixed the TM Machine refusing move selections that the `unlockAllMoveDexMovesByDefault` config had made visible, leaving the move slot blank and the craft button unresponsive.
- Fixed the Beast Ball not applying its 0.1× penalty to Pokémon that are not Ultra Beasts.
- Fixed the Moon Ball reading the world's total elapsed time instead of the time of day, so its bonus applied during the day instead.
- Fixed the Love Ball never awarding its 2.5× opposite gender bonus, and matching species by display name instead of identifier.
- Fixed the Timer Ball being weaker than a regular Poké Ball on early turns and only reaching 4× on turn 14 instead of turn 10.
- Fixed the Luxury Ball only doubling Friendship gains of 1, leaving level up and berry gains unaffected.
- Fixed Rufflet, Braviary, and Hisuian Braviary flooding logs with errors about missing sound events.
- Fixed Pokémon property typos in Pangoro and Dedenne herd spawn files.
- Fixed unintentional watermelon cosmetic for Hisuian Electrode.
- Fixed Blastoise having an unintentional passenger seat.
- Fixed form typo in Rockruff-Dusk spawn, preventing it from being able to spawn.
- Fixed the `stat_compare` and `stat_equal` evolution requirements crashing the game when given `special_attack` or `special_defence`, and made them treat any non-permanent stat as a failed requirement instead of crashing.
- Fixed Rowap and Jacoba berries not correctly altering Pokémon sizes when used as bait.
- Fixed Ampharos' eyes not emitting particles.
- Fixed Alolan Raticate's cry not playing.
- Fixed several incorrect light-based spawning conditions for ghosts and bugs.
- Removed unused, placeholder habitat pools.
- Fixed Mantyke, Mantine, and Quaxly getting stuck in a recoil 'expression' during battles due to having an expression assigned as a recoil animation.
- Fixed Lucario's aura particles not emitting.
- Fixed Lycanroc's head movement.
- Added head movement to Archaludon.
- Fixed Duraludon line not having their sleep animations.
- Fixed Diglett line not having their faint animations.
- Fixed Kingambit moving its legs while walking.
### Localization
- Updated translations for:
- Updated translations for:
- Brazilian Portuguese
- Simplified Chinese
- Japanese
@@ -21,7 +21,8 @@ import com.cobblemon.mod.common.pokemon.Pokemon
*/
data class FriendshipUpdatedEvent(
val pokemon: Pokemon,
val newFriendshipInitial: Int
val newFriendshipInitial: Int,
val earned: Boolean = false
) {
var newFriendship: Int = newFriendshipInitial
set(value) {
@@ -83,12 +83,6 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.biome.Biome
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.dimension.DimensionType
import net.minecraft.world.level.levelgen.Heightmap
import net.minecraft.world.level.pathfinder.PathType
import net.minecraft.world.level.storage.loot.LootParams
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import java.util.function.Function
@@ -99,25 +93,31 @@ import java.util.function.Function
* @since October 2nd, 2023
*/
object MoLangFunctions {
fun ItemStack.asMoLangValue(registryAccess: RegistryAccess) = ObjectValue(this)
.addStandardFunctions()
.addFunctions(ItemStackMoLangFunctions.attach(Pair(this, registryAccess)))
fun ItemStack.asMoLangValue(registryAccess: RegistryAccess) =
ObjectValue(this)
.addStandardFunctions()
.addFunctions(ItemStackMoLangFunctions.attach(Pair(this, registryAccess)))
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME)
.addFunctions(BiomeMoLangFunctions.attach(this))
fun Holder<Biome>.asBiomeMoLangValue() =
asMoLangValue(Registries.BIOME)
.addFunctions(BiomeMoLangFunctions.attach(this))
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION)
.addFunctions(WorldMoLangFunctions.attach(this))
fun Holder<Level>.asWorldMoLangValue() =
asMoLangValue(Registries.DIMENSION)
.addFunctions(WorldMoLangFunctions.attach(this))
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK)
.addFunctions(BlockMoLangFunctions.attach(this))
fun Holder<Block>.asBlockMoLangValue() =
asMoLangValue(Registries.BLOCK)
.addFunctions(BlockMoLangFunctions.attach(this))
fun MinecraftServer.asMoLangValue() = ObjectValue(this)
.addStandardFunctions()
.addFunctions(ServerMoLangFunctions.attach(this))
fun MinecraftServer.asMoLangValue() =
ObjectValue(this)
.addStandardFunctions()
.addFunctions(ServerMoLangFunctions.attach(this))
fun Holder<DimensionType>.asDimensionTypeMoLangValue() = asMoLangValue(Registries.DIMENSION_TYPE)
.addFunctions(DimensionTypeMoLangFunctions.attach(this))
fun Holder<DimensionType>.asDimensionTypeMoLangValue() =
asMoLangValue(Registries.DIMENSION_TYPE)
.addFunctions(DimensionTypeMoLangFunctions.attach(this))
fun Player.asMoLangValue(): ObjectValue<Player> {
if (this is ServerPlayer && uuid in Cobblemon.serverPlayerStructs) {
@@ -129,10 +129,11 @@ object MoLangFunctions {
}
}
val value = ObjectValue(
obj = this,
stringify = { it.effectiveName().string }
)
val value =
ObjectValue(
obj = this,
stringify = { it.effectiveName().string },
)
value.addFunctions(EntityMoLangFunctions.attach(this))
value.addFunctions(LivingEntityMoLangFunctions.attach(this))
@@ -153,57 +154,63 @@ object MoLangFunctions {
}
fun PartyStore.asMoLangValue(): ObjectValue<PartyStore> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.toString() },
)
value.addFunctions(PokemonStoreMoLangFunctions.attach(this))
value.addFunctions(PartyMoLangFunctions.attach(this))
return value
}
fun DropEntry.asMoLangValue(): ObjectValue<DropEntry> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.toString() },
)
value.addFunctions(DropEntryMoLangFunctions.attach(this))
return value
}
fun PokemonProperties.asMoLangValue(): ObjectValue<PokemonProperties> {
val value = ObjectValue(
obj = this,
stringify = { it.asString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.asString() },
)
value.addFunctions(PokemonPropertiesMoLangFunctions.attach(this))
return value
}
fun Evolution.asMoLangValue(): ObjectValue<Evolution> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.toString() },
)
value.addFunctions(EvolutionMoLangFunctions.attach(this))
return value
}
fun PCStore.asMoLangValue(): ObjectValue<PCStore> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.toString() },
)
value.addFunctions(PokemonStoreMoLangFunctions.attach(this))
value.addFunctions(PCMoLangFunctions.attach(this))
return value
}
fun NPCEntity.asMoLangValue(): ObjectValue<NPCEntity> {
val value = ObjectValue(
obj = this,
stringify = { it.name.string }
)
val value =
ObjectValue(
obj = this,
stringify = { it.name.string },
)
value.addFunctions(EntityMoLangFunctions.attach(this))
value.addFunctions(LivingEntityMoLangFunctions.attach(this))
value.addFunctions(NPCMoLangFunctions.attach(this))
@@ -211,10 +218,11 @@ object MoLangFunctions {
}
fun PokemonEntity.asMoLangValue(): ObjectValue<PokemonEntity> {
val value = ObjectValue(
obj = this,
stringify = { it.pokemon.uuid.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.pokemon.uuid.toString() },
)
value.addFunctions(EntityMoLangFunctions.attach(this))
value.addFunctions(LivingEntityMoLangFunctions.attach(this))
@@ -225,36 +233,40 @@ object MoLangFunctions {
}
fun PokemonBattle.asMoLangValue(): ObjectValue<PokemonBattle> {
val value = ObjectValue(
obj = this,
stringify = { it.battleId.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.battleId.toString() },
)
value.addFunctions(BattleMoLangFunctions.attach(this))
return value
}
fun BattleActor.asMoLangValue(): ObjectValue<BattleActor> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.toString() },
)
value.addFunctions(BattleActorMoLangFunctions.attach(this))
return value
}
fun SpawnablePosition.asMoLangValue(): ObjectValue<SpawnablePosition> {
val value = ObjectValue(
obj = this,
stringify = { it.toString() }
)
val value =
ObjectValue(
obj = this,
stringify = { it.toString() },
)
value.addFunctions(SpawnablePositionMoLangFunctions.attach(this))
return value
}
fun Vec3.asMoLangValue(): ObjectValue<Vec3> {
val value = ObjectValue(
obj = this
)
val value =
ObjectValue(
obj = this,
)
value.addFunction("x") { this.x }
value.addFunction("y") { this.y }
value.addFunction("z") { this.z }
@@ -265,45 +277,66 @@ object MoLangFunctions {
/**
* Different functions exist depending on the entity type, this tries to make the struct that's most specific to the type.
*/
fun Entity.asMostSpecificMoLangValue(): ObjectValue<out Entity> {
return when (this) {
is Player -> asMoLangValue()
is PokemonEntity -> struct
is NPCEntity -> struct
is ItemEntity -> ObjectValue(this).also { item ->
item.addStandardFunctions()
item.addFunctions(EntityMoLangFunctions.attach(this))
item.addFunctions(ItemStackMoLangFunctions.attach(Pair(this.item, this.registryAccess())))
fun Entity.asMostSpecificMoLangValue(): ObjectValue<out Entity> =
when (this) {
is Player -> {
asMoLangValue()
}
else -> ObjectValue(this).also { objectValue ->
objectValue.addStandardFunctions()
objectValue.addFunctions(EntityMoLangFunctions.attach(this))
if (this is LivingEntity) {
objectValue.addFunctions(LivingEntityMoLangFunctions.attach(this))
is PokemonEntity -> {
struct
}
is NPCEntity -> {
struct
}
is ItemEntity -> {
ObjectValue(this).also { item ->
item.addStandardFunctions()
item.addFunctions(EntityMoLangFunctions.attach(this))
item.addFunctions(ItemStackMoLangFunctions.attach(Pair(this.item, this.registryAccess())))
}
}
else -> {
ObjectValue(this).also { objectValue ->
objectValue.addStandardFunctions()
objectValue.addFunctions(EntityMoLangFunctions.attach(this))
if (this is LivingEntity) {
objectValue.addFunctions(LivingEntityMoLangFunctions.attach(this))
}
}
}
}
}
fun <T> Holder<T>.asMoLangValue(key: ResourceKey<Registry<T>>): ObjectValue<Holder<T>> {
val value = ObjectValue(
obj = this,
stringify = { it.unwrapKey().get().location().toString() }
)
value.functions["is_in"] = Function put@{ params: MoParams ->
val tag = TagKey.create(key, ResourceLocation.parse(params.getString(0).replace("#", "")))
return@put DoubleValue(if (value.obj.`is`(tag)) 1.0 else 0.0)
}
value.functions["is_of"] = Function put@{ params: MoParams ->
val identifier = ResourceLocation.parse(params.getString(0))
return@put DoubleValue(if (value.obj.`is`(identifier)) 1.0 else 0.0)
}
val value =
ObjectValue(
obj = this,
stringify = {
it
.unwrapKey()
.get()
.location()
.toString()
},
)
value.functions["is_in"] =
Function put@{ params: MoParams ->
val tag = TagKey.create(key, ResourceLocation.parse(params.getString(0).replace("#", "")))
return@put DoubleValue(if (value.obj.`is`(tag)) 1.0 else 0.0)
}
value.functions["is_of"] =
Function put@{ params: MoParams ->
val identifier = ResourceLocation.parse(params.getString(0))
return@put DoubleValue(if (value.obj.`is`(identifier)) 1.0 else 0.0)
}
return value
}
fun QueryStruct.addStandardFunctions(): QueryStruct {
addFunctions(GeneralMoLangFunctions.holder)
addFunctions(GeneralMoLangFunctions.functions)
return this
}
@@ -370,23 +403,17 @@ object MoLangFunctions {
return this
}
fun moLangFunctionMap(
vararg functions: Pair<String, (MoParams) -> MoValue>
): Map<String, (MoParams) -> MoValue> {
return functions.toMap()
}
fun moLangFunctionMap(vararg functions: Pair<String, (MoParams) -> MoValue>): Map<String, (MoParams) -> MoValue> = functions.toMap()
fun queryStructOf(
vararg functions: Pair<String, (MoParams) -> MoValue>
): QueryStruct {
return QueryStruct(
fun queryStructOf(vararg functions: Pair<String, (MoParams) -> MoValue>): QueryStruct =
QueryStruct(
hashMapOf<String, Function<MoParams, Any>>(
*functions.map { (name, func) ->
name to Function<MoParams, Any> { params -> func(params) }
}.toTypedArray()
)
*functions
.map { (name, func) ->
name to Function<MoParams, Any> { params -> func(params) }
}.toTypedArray(),
),
)
}
fun MoLangRuntime.setup(): MoLangRuntime {
environment.query.addStandardFunctions()
@@ -395,8 +422,14 @@ object MoLangFunctions {
fun writeMoValueToNBT(value: MoValue): Tag? {
return when (value) {
is DoubleValue -> DoubleTag.valueOf(value.value)
is StringValue -> StringTag.valueOf(value.value)
is DoubleValue -> {
DoubleTag.valueOf(value.value)
}
is StringValue -> {
StringTag.valueOf(value.value)
}
is ArrayStruct -> {
val list = value.map.values
val nbtList = ListTag()
@@ -413,14 +446,22 @@ object MoLangFunctions {
nbt
}
else -> null
else -> {
null
}
}
}
fun readMoValueFromNBT(nbt: Tag): MoValue {
return when (nbt) {
is DoubleTag -> DoubleValue(nbt.asDouble)
is StringTag -> StringValue(nbt.asString)
fun readMoValueFromNBT(nbt: Tag): MoValue =
when (nbt) {
is DoubleTag -> {
DoubleValue(nbt.asDouble)
}
is StringTag -> {
StringValue(nbt.asString)
}
is ListTag -> {
val array = ArrayStruct(hashMapOf())
var index = 0
@@ -441,11 +482,12 @@ object MoLangFunctions {
variable
}
else -> VariableStruct()
else -> {
VariableStruct()
}
}
}
}
// TODO: this one is unused. Should we move it to [MoLangFunctions] object?
fun Either<ResourceLocation, ExpressionLike>.runScript(runtime: MoLangRuntime) =
map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
@@ -17,30 +17,29 @@ import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
object BattleActorMoLangFunctions : AbstractMoLangFunctionHolder<BattleActor>() {
override fun BattleActor.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val actor = this
val map = mutableMapOf<String, (MoParams) -> Any>(
"is_npc" to { DoubleValue(actor.type == ActorType.NPC) },
"is_player" to { DoubleValue(actor.type == ActorType.PLAYER) },
"is_wild" to { DoubleValue(actor.type == ActorType.WILD) }
)
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["is_npc"] = { DoubleValue(actor.type == ActorType.NPC) }
functions["is_player"] = { DoubleValue(actor.type == ActorType.PLAYER) }
functions["is_wild"] = { DoubleValue(actor.type == ActorType.WILD) }
when (actor) {
is NPCBattleActor -> {
map["npc"] = { actor.entity.struct }
functions["npc"] = { actor.entity.struct }
}
is PlayerBattleActor -> {
map["player"] = { actor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
functions["player"] = { actor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
}
is PokemonBattleActor -> {
map["pokemon"] = { actor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
functions["pokemon"] = { actor.entity?.asMoLangValue() ?: DoubleValue.ZERO }
}
}
return map
return functions
}
}
@@ -16,17 +16,19 @@ import com.cobblemon.mod.common.util.getStringOrNull
object BattleMessageMoLangFunctions : AbstractMoLangFunctionHolder<BattleMessage>() {
override fun BattleMessage.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val battleMessage = this
return mutableMapOf(
"has_argument_at" to { params ->
val index = params.getInt(0)
val value = params.getStringOrNull(1) ?: ""
DoubleValue(value == battleMessage.argumentAt(index))
},
"has_argument" to { params ->
val argumentName = params.getString(0)
val value = params.getStringOrNull(1) ?: ""
DoubleValue(value == battleMessage.optionalArgument(argumentName))
}
)
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["has_argument_at"] = { params ->
val index = params.getInt(0)
val value = params.getStringOrNull(1) ?: ""
DoubleValue(value == battleMessage.argumentAt(index))
}
functions["has_argument"] = { params ->
val argumentName = params.getString(0)
val value = params.getStringOrNull(1) ?: ""
DoubleValue(value == battleMessage.optionalArgument(argumentName))
}
return functions
}
}
@@ -18,20 +18,22 @@ import java.util.*
object BattleMoLangFunctions : AbstractMoLangFunctionHolder<PokemonBattle>() {
override fun PokemonBattle.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val battle = this
return mutableMapOf(
"environment" to { battle.runtime.environment },
"battle_id" to { StringValue(battle.battleId.toString()) },
"battle_type" to { StringValue(battle.format.toString()) },
"is_pvn" to { DoubleValue(battle.isPvN) },
"is_pvp" to { DoubleValue(battle.isPvP) },
"is_pvw" to { DoubleValue(battle.isPvW) },
"stop" to { battle.stop() },
"actors" to { battle.actors.toList().asArrayValue { it.struct } },
"get_actor" to getActor@{ params ->
val uuid = UUID.fromString(params.getString(0))
val actor = battle.actors.find { it.uuid == uuid } ?: return@getActor DoubleValue.ZERO
actor.struct
}
)
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["environment"] = { battle.runtime.environment }
functions["battle_id"] = { StringValue(battle.battleId.toString()) }
functions["battle_type"] = { StringValue(battle.format.toString()) }
functions["is_pvn"] = { DoubleValue(battle.isPvN) }
functions["is_pvp"] = { DoubleValue(battle.isPvP) }
functions["is_pvw"] = { DoubleValue(battle.isPvW) }
functions["stop"] = { battle.stop() }
functions["actors"] = { battle.actors.toList().asArrayValue { it.struct } }
functions["get_actor"] = getActor@{ params ->
val uuid = UUID.fromString(params.getString(0))
val actor = battle.actors.find { it.uuid == uuid } ?: return@getActor DoubleValue.ZERO
actor.struct
}
return functions
}
}
@@ -12,8 +12,11 @@ import com.bedrockk.molang.runtime.MoParams
import net.minecraft.core.Holder
import net.minecraft.world.level.biome.Biome
object BiomeMoLangFunctions: AbstractMoLangFunctionHolder<Holder<Biome>>() {
object BiomeMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Biome>>() {
override fun Holder<Biome>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
return mutableMapOf()
val biome = this
val functions = hashMapOf<String, (MoParams) -> Any>()
return functions
}
}
@@ -12,8 +12,11 @@ import com.bedrockk.molang.runtime.MoParams
import net.minecraft.core.Holder
import net.minecraft.world.level.block.Block
object BlockMoLangFunctions: AbstractMoLangFunctionHolder<Holder<Block>>() {
object BlockMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Block>>() {
override fun Holder<Block>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
return mutableMapOf()
val block = this
val functions = hashMapOf<String, (MoParams) -> Any>()
return functions
}
}
@@ -14,6 +14,9 @@ import net.minecraft.world.level.dimension.DimensionType
object DimensionTypeMoLangFunctions : AbstractMoLangFunctionHolder<Holder<DimensionType>>() {
override fun Holder<DimensionType>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
return mutableMapOf()
val dimension = this
val functions = hashMapOf<String, (MoParams) -> Any>()
return functions
}
}
@@ -18,15 +18,16 @@ import com.cobblemon.mod.common.util.getOrNull
object DropEntryMoLangFunctions : AbstractMoLangFunctionHolder<DropEntry>() {
override fun DropEntry.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val drop = this
val map = mutableMapOf<String, (MoParams) -> Any>()
val functions = hashMapOf<String, (MoParams) -> Any>()
map["percentage"] = { DoubleValue(drop.percentage.toDouble()) }
map["quantity"] = { DoubleValue(drop.quantity.toDouble()) }
map["max_selectable_times"] = { DoubleValue(drop.maxSelectableTimes.toDouble()) }
map["can_drop"] = { params ->
functions["percentage"] = { DoubleValue(drop.percentage.toDouble()) }
functions["quantity"] = { DoubleValue(drop.quantity.toDouble()) }
functions["max_selectable_times"] = { DoubleValue(drop.maxSelectableTimes.toDouble()) }
functions["can_drop"] = { params ->
val pokemon = params.getOrNull<ObjectValue<Pokemon>>(0)?.obj
DoubleValue(if (drop.canDrop(pokemon)) 1.0 else 0.0)
}
return map
return functions
}
}
@@ -56,258 +56,300 @@ import kotlin.math.sqrt
object EntityMoLangFunctions : AbstractMoLangFunctionHolder<Entity>() {
override fun Entity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val thisEntity = this
val map = mutableMapOf<String, (MoParams) -> Any>(
"uuid" to { StringValue(thisEntity.uuid.toString()) },
"name" to { _ -> StringValue(thisEntity.effectiveName().string) },
"yaw" to { _ -> DoubleValue(thisEntity.yRot.toDouble()) },
"pitch" to { _ -> DoubleValue(thisEntity.xRot.toDouble()) },
"x" to { _ -> DoubleValue(thisEntity.x) },
"y" to { _ -> DoubleValue(thisEntity.y) },
"z" to { _ -> DoubleValue(thisEntity.z) },
"velocity_x" to { _ -> DoubleValue(thisEntity.deltaMovement.x) },
"velocity_y" to { _ -> DoubleValue(thisEntity.deltaMovement.y) },
"velocity_z" to { _ -> DoubleValue(thisEntity.deltaMovement.z) },
"width" to { DoubleValue(thisEntity.boundingBox.xsize) },
"height" to { DoubleValue(thisEntity.boundingBox.ysize) },
"this_size" to { DoubleValue(thisEntity.boundingBox.run { if (xsize > ysize) xsize else ysize }) },
"this_width" to { DoubleValue(thisEntity.boundingBox.xsize) },
"this_height" to { DoubleValue(thisEntity.boundingBox.ysize) },
"id_modulo" to { params -> DoubleValue(thisEntity.uuid.hashCode() % params.getDouble(0)) },
"horizontal_velocity" to { _ -> DoubleValue(thisEntity.deltaMovement.horizontalDistance()) },
"vertical_velocity" to { DoubleValue(thisEntity.deltaMovement.y) },
"is_on_ground" to { _ -> DoubleValue(thisEntity.onGround()) },
"world" to { _ -> thisEntity.level().worldRegistry.wrapAsHolder(thisEntity.level()).asWorldMoLangValue() },
"biome" to { _ -> thisEntity.level().getBiome(thisEntity.blockPosition()).asBiomeMoLangValue() },
"is_passenger" to { DoubleValue(thisEntity.isPassenger) },
"discard" to { thisEntity.discard() },
"is_sneaking" to { _ -> DoubleValue(thisEntity.isShiftKeyDown) },
"is_sprinting" to { _ -> DoubleValue(thisEntity.isSprinting) },
"is_in_water" to { _ -> DoubleValue(thisEntity.isUnderWater) },
"is_in_rain" to { _ -> DoubleValue(thisEntity.isInWaterOrRain && !thisEntity.isInWater) },
"is_touching_water_or_rain" to { _ -> DoubleValue(thisEntity.isInWaterRainOrBubble) },
"is_touching_water" to { _ -> DoubleValue(thisEntity.isInWater) },
"is_underwater" to { DoubleValue(thisEntity.getIsSubmerged()) },
"is_in_lava" to { _ -> DoubleValue(thisEntity.isInLava) },
"is_on_fire" to { _ -> DoubleValue(thisEntity.isOnFire) },
"is_invisible" to { _ -> DoubleValue(thisEntity.isInvisible) },
"is_riding" to { _ -> DoubleValue(thisEntity.isPassenger) },
"set_name" to { params ->
val name = params.getString(0)
thisEntity.customName = name.text()
DoubleValue.ONE
},
"damage" to { params ->
val amount = params.getDouble(0)
val source = DamageSource(
thisEntity.level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE)
.getHolder(DamageTypes.GENERIC).get()
val entity = this
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["uuid"] = { StringValue(entity.uuid.toString()) }
functions["name"] = { StringValue(entity.effectiveName().string) }
functions["yaw"] = { DoubleValue(entity.yRot.toDouble()) }
functions["pitch"] = { DoubleValue(entity.xRot.toDouble()) }
functions["x"] = { DoubleValue(entity.x) }
functions["y"] = { DoubleValue(entity.y) }
functions["z"] = { DoubleValue(entity.z) }
functions["velocity_x"] = { DoubleValue(entity.deltaMovement.x) }
functions["velocity_y"] = { DoubleValue(entity.deltaMovement.y) }
functions["velocity_z"] = { DoubleValue(entity.deltaMovement.z) }
functions["width"] = { DoubleValue(entity.boundingBox.xsize) }
functions["height"] = { DoubleValue(entity.boundingBox.ysize) }
functions["this_size"] = { DoubleValue(entity.boundingBox.run { if (xsize > ysize) xsize else ysize }) }
functions["this_width"] = { DoubleValue(entity.boundingBox.xsize) }
functions["this_height"] = { DoubleValue(entity.boundingBox.ysize) }
functions["id_modulo"] = { params -> DoubleValue(entity.uuid.hashCode() % params.getDouble(0)) }
functions["horizontal_velocity"] = { DoubleValue(entity.deltaMovement.horizontalDistance()) }
functions["vertical_velocity"] = { DoubleValue(entity.deltaMovement.y) }
functions["is_on_ground"] = { DoubleValue(entity.onGround()) }
functions["world"] = {
entity
.level()
.worldRegistry
.wrapAsHolder(entity.level())
.asWorldMoLangValue()
}
functions["biome"] = { entity.level().getBiome(entity.blockPosition()).asBiomeMoLangValue() }
functions["is_passenger"] = { DoubleValue(entity.isPassenger) }
functions["discard"] = { entity.discard() }
functions["is_sneaking"] = { DoubleValue(entity.isShiftKeyDown) }
functions["is_sprinting"] = { DoubleValue(entity.isSprinting) }
functions["is_in_water"] = { DoubleValue(entity.isUnderWater) }
functions["is_in_rain"] = { DoubleValue(entity.isInWaterOrRain && !entity.isInWater) }
functions["is_touching_water_or_rain"] = { DoubleValue(entity.isInWaterRainOrBubble) }
functions["is_touching_water"] = { DoubleValue(entity.isInWater) }
functions["is_underwater"] = { DoubleValue(entity.getIsSubmerged()) }
functions["is_in_lava"] = { DoubleValue(entity.isInLava) }
functions["is_on_fire"] = { DoubleValue(entity.isOnFire) }
functions["is_invisible"] = { DoubleValue(entity.isInvisible) }
functions["is_riding"] = { DoubleValue(entity.isPassenger) }
functions["set_name"] = { params ->
val name = params.getString(0)
entity.customName = name.text()
DoubleValue.ONE
}
functions["damage"] = { params ->
val amount = params.getDouble(0)
val source =
DamageSource(
entity
.level()
.registryAccess()
.registryOrThrow(Registries.DAMAGE_TYPE)
.getHolder(DamageTypes.GENERIC)
.get(),
)
thisEntity.hurt(source, amount.toFloat())
},
"distance_to_owner" to distanceToOwner@{
if (thisEntity !is TamableAnimal) {
return@distanceToOwner DoubleValue.ZERO
}
val owner = thisEntity.owner ?: return@distanceToOwner DoubleValue.ZERO
DoubleValue(thisEntity.distanceTo(owner))
},
"owner" to owner@{
if (thisEntity !is TamableAnimal) return@owner DoubleValue.ZERO
val owner = thisEntity.owner
owner?.asMostSpecificMoLangValue() ?: DoubleValue.ZERO
},
"delta_movement" to {
listOf(thisEntity.deltaMovement.x, thisEntity.deltaMovement.y, thisEntity.deltaMovement.z)
.asArrayValue(::DoubleValue)
},
"tags" to {
val tags = thisEntity.tags
val array = ArrayStruct(hashMapOf())
tags.forEachIndexed { index, tag -> array.setDirectly("$index", StringValue(tag)) }
array
},
"add_tag" to { params ->
val tag = params.getString(0)
thisEntity.addTag(tag)
DoubleValue.ONE
},
"remove_tag" to { params ->
val tag = params.getString(0)
thisEntity.removeTag(tag)
DoubleValue.ONE
},
"has_tag" to { params ->
val tag = params.getString(0)
DoubleValue(thisEntity.tags.contains(tag))
},
"distance_to_pos" to { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
DoubleValue(sqrt(thisEntity.distanceToSqr(Vec3(x, y, z))))
},
"type" to { _ ->
thisEntity.registryAccess().registry(Registries.ENTITY_TYPE).get().getKey(thisEntity.type)?.toString()?.let {
entity.hurt(source, amount.toFloat())
}
functions["distance_to_owner"] = distanceToOwner@{
if (entity !is TamableAnimal) {
return@distanceToOwner DoubleValue.ZERO
}
val owner = entity.owner ?: return@distanceToOwner DoubleValue.ZERO
DoubleValue(entity.distanceTo(owner))
}
functions["owner"] = owner@{
if (entity !is TamableAnimal) return@owner DoubleValue.ZERO
val owner = entity.owner
owner?.asMostSpecificMoLangValue() ?: DoubleValue.ZERO
}
functions["delta_movement"] = {
listOf(entity.deltaMovement.x, entity.deltaMovement.y, entity.deltaMovement.z)
.asArrayValue(::DoubleValue)
}
functions["tags"] = {
val tags = entity.tags
val array = ArrayStruct(hashMapOf())
tags.forEachIndexed { index, tag -> array.setDirectly("$index", StringValue(tag)) }
array
}
functions["add_tag"] = { params ->
val tag = params.getString(0)
entity.addTag(tag)
DoubleValue.ONE
}
functions["remove_tag"] = { params ->
val tag = params.getString(0)
entity.removeTag(tag)
DoubleValue.ONE
}
functions["has_tag"] = { params ->
val tag = params.getString(0)
DoubleValue(entity.tags.contains(tag))
}
functions["distance_to_pos"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
DoubleValue(sqrt(entity.distanceToSqr(Vec3(x, y, z))))
}
functions["type"] = {
entity
.registryAccess()
.registry(Registries.ENTITY_TYPE)
.get()
.getKey(entity.type)
?.toString()
?.let {
StringValue(it)
} ?: DoubleValue.ZERO
},
"find_nearby_block" to findNearbyBlock@{ params ->
val input = params.getString(0)
val isTag = input.contains("#")
val type = input.replace("#", "").asIdentifierDefaultingNamespace(namespace = "minecraft")
val range = params.getDoubleOrNull(1) ?: 10
val blockPos = thisEntity.level().getBlockStatesWithPos(
AABB.ofSize(
thisEntity.position(),
range.toDouble(),
range.toDouble(),
range.toDouble()
)
)
.filter { blockPosPair ->
}
functions["find_nearby_block"] = findNearbyBlock@{ params ->
val input = params.getString(0)
val isTag = input.contains("#")
val type = input.replace("#", "").asIdentifierDefaultingNamespace(namespace = "minecraft")
val range = params.getDoubleOrNull(1) ?: 10
val blockPos =
entity
.level()
.getBlockStatesWithPos(
AABB.ofSize(
entity.position(),
range.toDouble(),
range.toDouble(),
range.toDouble(),
),
).filter { blockPosPair ->
blockPosPair.first.blockHolder.let {
if (isTag) it.`is`(
TagKey.create(
Registries.BLOCK,
type
if (isTag) {
it.`is`(
TagKey.create(
Registries.BLOCK,
type,
),
)
) else it.`is`(type)
} else {
it.`is`(type)
}
}
}
.minByOrNull { it.second.distSqr(thisEntity.blockPosition()) }
}.minByOrNull { it.second.distSqr(entity.blockPosition()) }
?.second
if (blockPos != null) {
return@findNearbyBlock ArrayStruct(
mapOf(
"0" to DoubleValue(blockPos.x),
"1" to DoubleValue(blockPos.y),
"2" to DoubleValue(blockPos.z)
)
)
}
return@findNearbyBlock DoubleValue.ZERO
},
"get_nearby_entities" to { params ->
val distance = params.getDouble(0)
val entities =
thisEntity.level().getEntities(thisEntity, AABB.ofSize(thisEntity.position(), distance, distance, distance))
if (blockPos != null) {
return@findNearbyBlock ArrayStruct(
mapOf(
"0" to DoubleValue(blockPos.x),
"1" to DoubleValue(blockPos.y),
"2" to DoubleValue(blockPos.z),
),
)
}
return@findNearbyBlock DoubleValue.ZERO
}
functions["get_nearby_entities"] = { params ->
val distance = params.getDouble(0)
val entities =
entity
.level()
.getEntities(entity, AABB.ofSize(entity.position(), distance, distance, distance))
entities
.filterIsInstance<Entity>()
.map { it.asMostSpecificMoLangValue() }
.asArrayValue()
},
"is_standing_on_blocks" to { params ->
val depth = params.getDouble(0).toInt()
val blockStrings: MutableSet<String> = mutableSetOf()
for (blockIndex in 1..<params.params.size) {
blockStrings.add(params.getString(blockIndex))
}
entities
.filterIsInstance<Entity>()
.map { it.asMostSpecificMoLangValue() }
.asArrayValue()
}
functions["is_standing_on_blocks"] = { params ->
val depth = params.getDouble(0).toInt()
val blockStrings: MutableSet<String> = mutableSetOf()
for (blockIndex in 1..<params.params.size) {
blockStrings.add(params.getString(blockIndex))
}
if (thisEntity.isStandingOn(blockStrings, depth)) DoubleValue.ONE else DoubleValue.ZERO
},
if (entity.isStandingOn(blockStrings, depth)) DoubleValue.ONE else DoubleValue.ZERO
}
// q.entity.spawn_bedrock_particles(effect, locator, [player])
// sends to everyone nearby or just to the player if they're set.
// Locator is necessary even if unused on non-posables.
"spawn_bedrock_particles" to { params ->
val particle = params.getString(0).asResource()
val locator = params.getString(1)
val player = params.getOrNull<MoValue>(2)?.let {
// q.entity.spawn_bedrock_particles(effect, locator, [player])
// sends to everyone nearby or just to the player if they're set.
// Locator is necessary even if unused on non-posables.
functions["spawn_bedrock_particles"] = { params ->
val particle = params.getString(0).asResource()
val locator = params.getString(1)
val player =
params.getOrNull<MoValue>(2)?.let {
when (it) {
is StringValue -> thisEntity.level().getPlayerByUUID(UUID.fromString(it.value))
is StringValue -> entity.level().getPlayerByUUID(UUID.fromString(it.value))
is ObjectValue<*> -> it.obj
else -> null
}
} as? ServerPlayer
val packet = SpawnSnowstormEntityParticlePacket(particle, thisEntity.id, listOf(locator))
if (player == null) {
packet.sendToPlayersAround(thisEntity.x, thisEntity.y, thisEntity.z, 64.0, thisEntity.level().dimension())
} else {
packet.sendToPlayer(player)
}
},
"make_intangible" to { params ->
val intangible = params.getBooleanOrNull(0) ?: true
thisEntity.noPhysics = intangible
DoubleValue.ONE
val packet = SpawnSnowstormEntityParticlePacket(particle, entity.id, listOf(locator))
if (player == null) {
packet.sendToPlayersAround(
entity.x,
entity.y,
entity.z,
64.0,
entity.level().dimension(),
)
} else {
packet.sendToPlayer(player)
}
)
}
functions["make_intangible"] = { params ->
val intangible = params.getBooleanOrNull(0) ?: true
entity.noPhysics = intangible
DoubleValue.ONE
}
if (thisEntity is PosableEntity) {
map["play_animation"] = playAnimation@{ params ->
val animation = params.getString(0)
val packet = PlayPosableAnimationPacket(thisEntity.id, setOf(animation), emptyList())
val target = params.getStringOrNull(1)
if (target != null) {
val targetPlayer = if (target.asUUID != null) {
thisEntity.level().getPlayerByUUID(target.asUUID!!) as ServerPlayer
} else if (thisEntity.level() is ServerLevel) {
thisEntity.level().server!!.playerList.getPlayerByName(target)
when (entity) {
is PosableEntity -> {
functions["play_animation"] = playAnimation@{ params ->
val animation = params.getString(0)
val packet = PlayPosableAnimationPacket(entity.id, setOf(animation), emptyList())
val target = params.getStringOrNull(1)
if (target != null) {
val targetPlayer =
if (target.asUUID != null) {
entity.level().getPlayerByUUID(target.asUUID!!) as ServerPlayer
} else if (entity.level() is ServerLevel) {
entity
.level()
.server!!
.playerList
.getPlayerByName(target)
} else {
null
}
if (targetPlayer != null) {
packet.sendToPlayer(targetPlayer)
return@playAnimation DoubleValue.ONE
} else {
return@playAnimation DoubleValue.ZERO
}
} else {
null
}
if (targetPlayer != null) {
packet.sendToPlayer(targetPlayer)
packet.sendToPlayersAround(
entity.x,
entity.y,
entity.z,
64.0,
entity.level().dimension(),
)
return@playAnimation DoubleValue.ONE
} else {
return@playAnimation DoubleValue.ZERO
}
} else {
packet.sendToPlayersAround(thisEntity.x, thisEntity.y, thisEntity.z, 64.0, thisEntity.level().dimension())
return@playAnimation DoubleValue.ONE
}
functions["face"] = { params ->
ObjectValue(ReferenceDialogueFaceProvider(entity.id, params.getBooleanOrNull(0) != false))
}
}
map["face"] = { params ->
ObjectValue(ReferenceDialogueFaceProvider(thisEntity.id, params.getBooleanOrNull(0) != false))
is Schedulable -> {
functions["run_molang_after"] = { params ->
val expression = params.getString(0).asExpressionLike()
val delayInSeconds = params.getDouble(1).toFloat()
val runtime = MoLangRuntime()
runtime.environment.cloneFrom(params.environment)
entity.after(delayInSeconds) {
runtime.resolve(expression)
}
}
}
}
if (thisEntity is Schedulable) {
map["run_molang_after"] = { params ->
val expression = params.getString(0).asExpressionLike()
val delayInSeconds = params.getDouble(1).toFloat()
val runtime = MoLangRuntime()
runtime.environment.cloneFrom(params.environment)
thisEntity.after(delayInSeconds) {
runtime.resolve(expression)
is MoLangScriptingEntity -> {
functions["add_callback"] = { params ->
val type = params.getString(0).asIdentifierDefaultingNamespace()
val callback = params.getString(1).asIdentifierDefaultingNamespace()
val allowDuplicates = params.getBooleanOrNull(2) ?: false
entity.callbacks.addCallback(type, callback, allowDuplicates)
}
functions["remove_callback"] = { params ->
val type = params.getString(0).asIdentifierDefaultingNamespace()
val callback = params.getString(1).asIdentifierDefaultingNamespace()
entity.callbacks.removeCallback(type, callback)
}
functions["has_callback"] = { params ->
val type = params.getString(0).asIdentifierDefaultingNamespace()
val callback = params.getString(1).asIdentifierDefaultingNamespace()
DoubleValue(callback in (entity.callbacks[type] ?: emptySet()))
}
functions["clear_callbacks"] = { params ->
val type = params.getStringOrNull(0)?.asIdentifierDefaultingNamespace()
if (type != null) {
entity.callbacks[type]?.clear()
} else {
entity.callbacks.clear()
}
DoubleValue.ONE
}
}
}
if (thisEntity is MoLangScriptingEntity) {
map["add_callback"] = { params ->
val type = params.getString(0).asIdentifierDefaultingNamespace()
val callback = params.getString(1).asIdentifierDefaultingNamespace()
val allowDuplicates = params.getBooleanOrNull(2) ?: false
thisEntity.callbacks.addCallback(type, callback, allowDuplicates)
}
map["remove_callback"] = { params ->
val type = params.getString(0).asIdentifierDefaultingNamespace()
val callback = params.getString(1).asIdentifierDefaultingNamespace()
thisEntity.callbacks.removeCallback(type, callback)
}
map["has_callback"] = { params ->
val type = params.getString(0).asIdentifierDefaultingNamespace()
val callback = params.getString(1).asIdentifierDefaultingNamespace()
DoubleValue(callback in (thisEntity.callbacks[type] ?: emptySet()))
}
map["clear_callbacks"] = { params ->
val type = params.getStringOrNull(0)?.asIdentifierDefaultingNamespace()
if (type != null) {
thisEntity.callbacks[type]?.clear()
} else {
thisEntity.callbacks.clear()
}
DoubleValue.ONE
}
}
return map
return functions
}
}
@@ -19,26 +19,26 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
object EvolutionMoLangFunctions : AbstractMoLangFunctionHolder<Evolution>() {
override fun Evolution.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val evolution = this
val map = hashMapOf<String, (MoParams) -> Any>()
val functions = hashMapOf<String, (MoParams) -> Any>()
map["result"] = { evolution.result.asMoLangValue() }
map["is_optional"] = { DoubleValue(evolution.optional) }
map["consumes_held_item"] = { DoubleValue(evolution.consumeHeldItem) }
functions["result"] = { evolution.result.asMoLangValue() }
functions["is_optional"] = { DoubleValue(evolution.optional) }
functions["consumes_held_item"] = { DoubleValue(evolution.consumeHeldItem) }
when (evolution) {
is LevelUpEvolution -> {
map["is_level_up"] = { DoubleValue.ONE }
functions["is_level_up"] = { DoubleValue.ONE }
}
is TradeEvolution -> {
map["is_trade"] = { DoubleValue.ONE }
functions["is_trade"] = { DoubleValue.ONE }
}
is ItemInteractionEvolution -> {
map["is_item"] = { DoubleValue.ONE }
functions["is_item"] = { DoubleValue.ONE }
}
}
return map
return functions
}
}
@@ -42,101 +42,99 @@ import net.minecraft.world.item.ItemStack
import java.text.ParseException
object GeneralMoLangFunctions {
val holder: HashMap<String, (MoParams) -> Any> = hashMapOf(
"print" to { params ->
val functions: MutableMap<String, (MoParams) -> Any> = mutableMapOf()
init {
functions["print"] = { params ->
val message = params.get<MoValue>(0).asString()
LOGGER.info(message)
},
"delete_variable" to deleteVar@{ params ->
}
functions["delete_variable"] = { params ->
val struct = params.get<VariableStruct>(0)
val variable = params.getString(1)
struct.map.remove(variable)
return@deleteVar DoubleValue.ONE
},
"delete_variables" to { params ->
val struct = params.get<VariableStruct>(0)
struct.map.clear()
DoubleValue.ONE
},
"get_variable" to { params ->
}
functions["get_variable"] = { params ->
val struct = params.get<VariableStruct>(0)
val variable = params.getString(1)
struct.map[variable] ?: DoubleValue.ZERO
},
"set_variable" to { params ->
}
functions["set_variable"] = { params ->
val struct = params.get<VariableStruct>(0)
val variable = params.getString(1)
val value = params.get<MoValue>(2)
struct.map[variable] = value
value
},
"set_query" to { params ->
}
functions["set_query"] = { params ->
val variable = params.getString(0)
val value = params.get<MoValue>(1)
params.environment.query.addFunction(variable) { value }
value
},
"replace" to { params ->
}
functions["replace"] = { params ->
val text = params.getString(0)
val search = params.getString(1)
val replace = params.getString(2)
StringValue(text.replace(search, replace))
},
"is_included" to { params ->
}
functions["is_included"] = { params ->
val text = params.getString(0)
val search = params.getString(1)
DoubleValue(text.contains(search))
},
"to_lower" to { params ->
}
functions["to_lower"] = { params ->
StringValue(params.getString(0).lowercase())
},
"to_upper" to { params ->
}
functions["to_upper"] = { params ->
StringValue(params.getString(0).uppercase())
},
"string_length" to { params ->
}
functions["string_length"] = { params ->
DoubleValue(params.getString(0).length)
},
"split_string" to { params ->
}
functions["split_string"] = { params ->
val text = params.getString(0)
val delimiter = params.getString(1)
val parts = text.split(delimiter).map { StringValue(it) }
val struct = ArrayStruct(hashMapOf())
parts.forEachIndexed { index, moValue -> struct.setDirectly("$index", moValue) }
struct
},
"is_blank" to { params ->
}
functions["is_blank"] = { params ->
val arg = params.get<MoValue>(0)
DoubleValue((arg is StringValue && (arg.value.isBlank() || arg.value.toDoubleOrNull() == 0.0)) || (arg is DoubleValue && arg.value == 0.0))
},
"run_command" to { params ->
DoubleValue(
(arg is StringValue && (arg.value.isBlank() || arg.value.toDoubleOrNull() == 0.0)) ||
(arg is DoubleValue && arg.value == 0.0),
)
}
functions["run_command"] = { params ->
val command = params.getString(0)
try {
server()!!.commands.performPrefixedCommand(server()!!.createCommandSourceStack(), command)
} catch (_: NullPointerException) {
DoubleValue.ZERO
}
},
"is_int" to { params -> DoubleValue(params.get<MoValue>(0).asString().isInt()) },
"is_number" to { params ->
}
functions["is_int"] = { params -> DoubleValue(params.get<MoValue>(0).asString().isInt()) }
functions["is_number"] = { params ->
DoubleValue(
params.get<MoValue>(0).asString().toDoubleOrNull() != null
params.get<MoValue>(0).asString().toDoubleOrNull() != null,
)
},
"to_number" to { params ->
}
functions["to_number"] = { params ->
DoubleValue(
params.get<MoValue>(0).asString().toDoubleOrNull() ?: 0.0
params.get<MoValue>(0).asString().toDoubleOrNull() ?: 0.0,
)
},
"to_int" to { params ->
}
functions["to_int"] = { params ->
DoubleValue(
params.get<MoValue>(0).asString().toIntOrNull() ?: 0
params.get<MoValue>(0).asString().toIntOrNull() ?: 0,
)
},
"to_string" to { params -> StringValue(params.get<MoValue>(0).asString()) },
"do_effect_walks" to { _ ->
DoubleValue(Cobblemon.config.walkingInBattleAnimations)
},
"random" to { params ->
}
functions["to_string"] = { params -> StringValue(params.get<MoValue>(0).asString()) }
functions["do_effect_walks"] = { DoubleValue(Cobblemon.config.walkingInBattleAnimations) }
functions["random"] = { params ->
val options = mutableListOf<MoValue>()
var index = 0
while (params.contains(index)) {
@@ -144,35 +142,35 @@ object GeneralMoLangFunctions {
index++
}
options.random() // Can throw an exception if they specified no args. They'd be idiots though.
},
"curve" to { params ->
}
functions["curve"] = { params ->
val curveName = params.getString(0)
val curve =
WaveFunctions.functions[curveName] ?: throw IllegalArgumentException("Unknown curve: $curveName")
ObjectValue(curve)
},
"array" to { params ->
}
functions["array"] = { params ->
val values = params.params
val array = ArrayStruct(hashMapOf())
values.forEachIndexed { index, moValue -> array.setDirectly("$index", moValue) }
array
},
"length" to { params ->
}
functions["length"] = { params ->
val array = (params.getOrNull<MoValue>(0) as? VariableStruct)
if (array == null) {
DoubleValue.ZERO
} else {
DoubleValue(array.map.size.toDouble())
}
},
"append" to { params ->
}
functions["append"] = { params ->
val array = params.get<ArrayStruct>(0)
val value = params.get<MoValue>(1)
val nextIndex = array.map.size
array.setDirectly("$nextIndex", value)
array
},
"insert" to { params ->
}
functions["insert"] = { params ->
val array = params.get<ArrayStruct>(0)
val index = params.getInt(1)
val value = params.get<MoValue>(2)
@@ -187,36 +185,40 @@ object GeneralMoLangFunctions {
}
array.map[index.toString()] = value
array
},
"delete" to { params ->
}
functions["delete"] = { params ->
val array = params.get<ArrayStruct>(0)
val index = params.getInt(1)
if (index in 0 until array.map.size) {
array.map.remove(index.toString())
// Re-index the array to keep keys sequential in numerical order
val newMap = hashMapOf<String, MoValue>()
array.map.keys.mapNotNull { it.toIntOrNull() }
array.map.keys
.mapNotNull { it.toIntOrNull() }
.sorted()
.forEachIndexed { i, k -> newMap[i.toString()] = array.map[k.toString()]!! }
array.map.clear()
array.map.putAll(newMap)
}
array
},
"run_script" to { params ->
}
functions["run_script"] = { params ->
val runtime = MoLangRuntime()
runtime.environment.query = params.environment.query
runtime.environment.variable = params.environment.variable
val args = params.params.subList(1, params.params.size)
runtime.environment.context = ContextStruct(
(params.environment.context?.map
?: emptyMap()) + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
)
runtime.environment.context =
ContextStruct(
(
params.environment.context?.map
?: emptyMap()
) + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap(),
)
val script = params.getString(0).asIdentifierDefaultingNamespace()
// store the args in the
CobblemonScripts.run(script, runtime) ?: DoubleValue.ZERO
},
"run_molang" to { params ->
}
functions["run_molang"] = { params ->
val runtime = MoLangRuntime()
runtime.environment.query = params.environment.query
runtime.environment.variable = params.environment.variable
@@ -224,17 +226,16 @@ object GeneralMoLangFunctions {
val expression = params.getString(0).asExpressionLike()
val delayInSeconds = params.getDoubleOrNull(1)?.toFloat() ?: 0.0f
fun evaluate(): MoValue {
return try {
fun evaluate(): MoValue =
try {
runtime.resolve(expression)
} catch (ex: Exception) {
LOGGER.warn(
"Failed to evaluate MoLang expression${if (delayInSeconds > 0.0f) " (delayed)" else ""}: $expression",
ex
ex,
)
DoubleValue.ZERO
}
}
if (delayInSeconds > 0.0f) {
val tracker =
@@ -246,55 +247,55 @@ object GeneralMoLangFunctions {
} else {
evaluate()
}
},
"system_time_millis" to { _ ->
DoubleValue(System.currentTimeMillis())
},
}
functions["system_time_millis"] = { DoubleValue(System.currentTimeMillis()) }
// the rest of the world use dd/MM/yyyy grow up america (this comment was generated by copilot)
"date_local_time" to { _ ->
functions["date_local_time"] = {
val time = System.currentTimeMillis()
val date = java.util.Date(time)
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
StringValue(formatted)
},
"date_of" to { params ->
}
functions["date_of"] = { params ->
val time = params.getDouble(0).toLong()
val date = java.util.Date(time)
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
StringValue(formatted)
},
"date_is_after" to { params ->
}
functions["date_is_after"] = { params ->
val dateA = params.getString(0)
val dateB = params.getString(1)
val format = java.text.SimpleDateFormat("dd/MM/yyyy")
val a = try {
format.parse(dateA)
} catch (_: ParseException) {
throw RuntimeException("Cannot parse date ${dateA}, expected it to be in dd/MM/yyyy format, other provided")
}
val b = try {
format.parse(dateB)
} catch (_: ParseException) {
throw RuntimeException("Cannot parse date ${dateB}, expected it to be in dd/MM/yyyy format, other provided")
}
val a =
try {
format.parse(dateA)
} catch (_: ParseException) {
throw RuntimeException("Cannot parse date $dateA, expected it to be in dd/MM/yyyy format, other provided")
}
val b =
try {
format.parse(dateB)
} catch (_: ParseException) {
throw RuntimeException("Cannot parse date $dateB, expected it to be in dd/MM/yyyy format, other provided")
}
DoubleValue(a.after(b))
},
"get_move_from_id" to { params ->
}
functions["get_move_from_id"] = { params ->
val moveId = params.getString(0)
val moveTemplate = Moves.getByName(moveId)
moveTemplate?.struct ?: DoubleValue.ZERO
},
"create_simple_party_provider" to { _ ->
}
functions["create_simple_party_provider"] = {
val partyProvider = SimplePartyProvider()
partyProvider.struct
},
"create_pickup_item" to { params ->
}
functions["create_pickup_item"] = { params ->
val item = params.getOrNull<MoValue>(0)?.asString()?.let(ObtainableItemCondition::parseFromString)
val pickupPriority = params.getIntOrNull(1) ?: 0
val pickupItem = ObtainableItem(item = item, pickupPriority = pickupPriority)
pickupItem.struct
},
"create_itemstack" to { params ->
}
functions["create_itemstack"] = { params ->
val itemId = params.getString(0).asIdentifierDefaultingNamespace()
try {
val item = BuiltInRegistries.ITEM.get(itemId)
@@ -305,7 +306,7 @@ object GeneralMoLangFunctions {
LOGGER.error("Cannot create item stack from identifier: $itemId, item with that ID does not exist. Possible typo?")
DoubleValue.ZERO
}
},
"file" to { MoLangLoadedFilesCache.struct }
)
}
functions["file"] = { MoLangLoadedFilesCache.struct }
}
}
@@ -26,43 +26,44 @@ object ItemStackMoLangFunctions : AbstractMoLangFunctionHolder<Pair<ItemStack, R
val registryAccess = this.second
val itemRegistry = registryAccess.registryOrThrow(Registries.ITEM)
val holder = itemRegistry.wrapAsHolder(stack.item)
val functions = mutableMapOf<String, (MoParams) -> Any>()
val map = hashMapOf<String, (MoParams) -> Any>()
map["item"] = { _ -> holder.asMoLangValue(Registries.ITEM) }
map["count"] = { _ -> DoubleValue(stack.count.toDouble()) }
map["damage_value"] = { _ -> DoubleValue(stack.damageValue) }
map["max_damage"] = { _ -> DoubleValue(stack.maxDamage) }
map["is_empty"] = { _ -> DoubleValue(stack.isEmpty) }
map["shrink"] = { params -> stack.shrink(params.getInt(0)) }
map["grow"] = { params -> stack.grow(params.getInt(0)) }
map["is_of"] = { params ->
functions["item"] = { holder.asMoLangValue(Registries.ITEM) }
functions["count"] = { DoubleValue(stack.count.toDouble()) }
functions["damage_value"] = { DoubleValue(stack.damageValue) }
functions["max_damage"] = { DoubleValue(stack.maxDamage) }
functions["is_empty"] = { DoubleValue(stack.isEmpty) }
functions["shrink"] = { params -> stack.shrink(params.getInt(0)) }
functions["grow"] = { params -> stack.grow(params.getInt(0)) }
functions["is_of"] = { params ->
DoubleValue(
holder.`is`(
params.getString(0).asIdentifierDefaultingNamespace()
)
params.getString(0).asIdentifierDefaultingNamespace(),
),
)
}
map["is_in"] = { params ->
functions["is_in"] = { params ->
DoubleValue(
holder.`is`(
TagKey.create(
Registries.ITEM,
params.getString(0).replace("#", "").asIdentifierDefaultingNamespace()
)
)
params.getString(0).replace("#", "").asIdentifierDefaultingNamespace(),
),
),
)
}
map["is_food"] = { _ -> DoubleValue(stack.has(DataComponents.FOOD)) }
map["is_enchanted"] = { _ -> DoubleValue(stack.hasFoil()) }
map["has_enchantment"] = put@{ params ->
functions["is_food"] = { DoubleValue(stack.has(DataComponents.FOOD)) }
functions["is_enchanted"] = { DoubleValue(stack.hasFoil()) }
functions["has_enchantment"] = hasEnchantment@{ params ->
val enchantmentId = params.getString(0).asIdentifierDefaultingNamespace()
val minLevel = params.getIntOrNull(1) ?: 1
val enchantmentRegistry = registryAccess.registryOrThrow(Registries.ENCHANTMENT)
val holder =
enchantmentRegistry.getHolder(enchantmentId).orElse(null) ?: return@put DoubleValue.ZERO
enchantmentRegistry.getHolder(enchantmentId).orElse(null) ?: return@hasEnchantment DoubleValue.ZERO
val level = EnchantmentHelper.getItemEnchantmentLevel(holder, stack)
return@put DoubleValue(level >= minLevel)
DoubleValue(level >= minLevel)
}
return map
return functions
}
}
@@ -53,26 +53,27 @@ import java.util.*
object LivingEntityMoLangFunctions : AbstractMoLangFunctionHolder<LivingEntity>() {
override fun LivingEntity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val entity = this
val map = mutableMapOf<String, (MoParams) -> Any>()
map["is_player"] = { _ -> DoubleValue(entity is Player) }
map["is_npc"] = { _ -> DoubleValue(entity is NPCEntity) }
map["is_mob"] = { _ -> DoubleValue(entity is Mob) }
map["is_pokemon"] = { _ -> DoubleValue(entity is PokemonEntity) }
map["is_animal"] = { _ -> DoubleValue(entity is Animal) }
map["is_tamable"] = { _ -> DoubleValue(entity is TamableAnimal) }
map["is_tamed"] = { _ -> DoubleValue(entity is TamableAnimal && entity.isTame) }
map["is_hostile"] = { _ -> DoubleValue(entity is Monster) }
map["is_baby"] = { _ -> DoubleValue(entity.isBaby) }
map["is_adult"] = { _ -> DoubleValue(!entity.isBaby) }
map["remove_effect"] = put@{ params ->
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["is_player"] = { DoubleValue(entity is Player) }
functions["is_npc"] = { DoubleValue(entity is NPCEntity) }
functions["is_mob"] = { DoubleValue(entity is Mob) }
functions["is_pokemon"] = { DoubleValue(entity is PokemonEntity) }
functions["is_animal"] = { DoubleValue(entity is Animal) }
functions["is_tamable"] = { DoubleValue(entity is TamableAnimal) }
functions["is_tamed"] = { DoubleValue(entity is TamableAnimal && entity.isTame) }
functions["is_hostile"] = { DoubleValue(entity is Monster) }
functions["is_baby"] = { DoubleValue(entity.isBaby) }
functions["is_adult"] = { DoubleValue(!entity.isBaby) }
functions["remove_effect"] = removeEffect@{ params ->
val effectId = params.getString(0).asIdentifierDefaultingNamespace()
val effectHolder = BuiltInRegistries.MOB_EFFECT.getHolder(effectId).orElse(null)
if (effectHolder != null) {
entity.removeEffect(effectHolder)
return@put DoubleValue.ONE
return@removeEffect DoubleValue.ONE
}
}
map["add_effect"] = put@{ params ->
functions["add_effect"] = addEffect@{ params ->
val effectId = params.getString(0).asIdentifierDefaultingNamespace()
val duration = params.getInt(1)
val amplifier = params.getIntOrNull(2) ?: 0
@@ -81,36 +82,37 @@ object LivingEntityMoLangFunctions : AbstractMoLangFunctionHolder<LivingEntity>(
val effectHolder = BuiltInRegistries.MOB_EFFECT.getHolder(effectId).orElse(null)
if (effectHolder != null) {
entity.addEffect(MobEffectInstance(effectHolder, duration, amplifier, ambient, visible))
return@put DoubleValue.ONE
return@addEffect DoubleValue.ONE
}
}
map["has_effect"] = put@{ params ->
functions["has_effect"] = { params ->
val effectId = params.getString(0).asIdentifierDefaultingNamespace()
val effectHolder = BuiltInRegistries.MOB_EFFECT.getHolder(effectId).orElse(null)
return@put DoubleValue(if (effectHolder != null) entity.hasEffect(effectHolder) else false)
DoubleValue(effectHolder != null && entity.hasEffect(effectHolder))
}
map["heal"] = { params ->
functions["heal"] = { params ->
val amount = params.getDouble(0)
entity.heal(amount.toFloat())
}
map["is_looking_at"] = put@{ params ->
functions["is_looking_at"] = isLookingAt@{ params ->
val targetEntity = params.get<MoValue>(0)
val maxDistance = params.getDoubleOrNull(1)?.toFloat() ?: 2.0F
val entity = if (targetEntity is ObjectValue<*> && targetEntity.obj is Entity) {
targetEntity.obj as Entity
} else {
return@put DoubleValue.ZERO
}
val entity =
if (targetEntity is ObjectValue<*> && targetEntity.obj is Entity) {
targetEntity.obj as Entity
} else {
return@isLookingAt DoubleValue.ZERO
}
return@put DoubleValue(entity.isLookingAt(entity, maxDistance))
DoubleValue(entity.isLookingAt(entity, maxDistance))
}
map["is_living_entity"] = { DoubleValue.ONE }
map["is_flying"] = { _ -> DoubleValue(entity.isFallFlying) }
map["is_sleeping"] = { _ -> DoubleValue(entity.isSleeping) }
map["health"] = { _ -> DoubleValue(entity.health) }
map["max_health"] = { _ -> DoubleValue(entity.maxHealth) }
map["look_at_position"] = { params ->
functions["is_living_entity"] = { DoubleValue.ONE }
functions["is_flying"] = { DoubleValue(entity.isFallFlying) }
functions["is_sleeping"] = { DoubleValue(entity.isSleeping) }
functions["health"] = { DoubleValue(entity.health) }
functions["max_health"] = { DoubleValue(entity.maxHealth) }
functions["look_at_position"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
@@ -120,159 +122,174 @@ object LivingEntityMoLangFunctions : AbstractMoLangFunctionHolder<LivingEntity>(
brain.setMemoryWithExpiry(
MemoryModuleType.LOOK_TARGET,
CobblemonBlockPosTracker(Vec3(x, y, z), flags.toSet()),
duration.toLong()
duration.toLong(),
)
}
map["get_wander_control_memory"] = put@{
val value = entity.brain.getMemorySafely(CobblemonMemories.WANDER_CONTROL).orElse(null)
?: CobblemonWanderControl()
functions["get_wander_control_memory"] = {
val value =
entity.brain.getMemorySafely(CobblemonMemories.WANDER_CONTROL).orElse(null)
?: CobblemonWanderControl()
if (
!entity.brain.checkMemory(CobblemonMemories.WANDER_CONTROL, MemoryStatus.VALUE_PRESENT)
&& entity.brain.checkMemory(CobblemonMemories.WANDER_CONTROL, MemoryStatus.REGISTERED)
!entity.brain.checkMemory(CobblemonMemories.WANDER_CONTROL, MemoryStatus.VALUE_PRESENT) &&
entity.brain.checkMemory(CobblemonMemories.WANDER_CONTROL, MemoryStatus.REGISTERED)
) {
entity.brain.setMemory(CobblemonMemories.WANDER_CONTROL, value)
}
return@put value.struct
value.struct
}
map["get_position_memory"] = put@{ params ->
functions["get_position_memory"] = getPosMemory@{ params ->
val id = params.getString(0).asIdentifierDefaultingNamespace()
val memoryType = BuiltInRegistries.MEMORY_MODULE_TYPE.get(id)
if (entity.brain.checkMemory(memoryType, MemoryStatus.VALUE_PRESENT)) {
return@put when (val memory = entity.brain.getMemory(memoryType).get()) {
is Vec3i -> VariableStruct(
mapOf(
"x" to DoubleValue(memory.x),
"y" to DoubleValue(memory.y),
"z" to DoubleValue(memory.z)
return@getPosMemory when (val memory = entity.brain.getMemory(memoryType).get()) {
is Vec3i -> {
VariableStruct(
mapOf(
"x" to DoubleValue(memory.x),
"y" to DoubleValue(memory.y),
"z" to DoubleValue(memory.z),
),
)
)
}
is Position -> VariableStruct(
mapOf(
"x" to DoubleValue(memory.x()),
"y" to DoubleValue(memory.y()),
"z" to DoubleValue(memory.z())
is Position -> {
VariableStruct(
mapOf(
"x" to DoubleValue(memory.x()),
"y" to DoubleValue(memory.y()),
"z" to DoubleValue(memory.z()),
),
)
)
}
else -> DoubleValue.ZERO
else -> {
DoubleValue.ZERO
}
}
} else {
return@put DoubleValue.ZERO
}
DoubleValue.ZERO
}
map["set_uuid_memory"] = put@{ params ->
val memory = params.getString(0).asIdentifierDefaultingNamespace()
.let(BuiltInRegistries.MEMORY_MODULE_TYPE::get) as MemoryModuleType<UUID>
val uuid = params.getString(1).asUUID ?: return@put DoubleValue.ZERO
functions["set_uuid_memory"] = setUuidMemory@{ params ->
val memory =
params
.getString(0)
.asIdentifierDefaultingNamespace()
.let(BuiltInRegistries.MEMORY_MODULE_TYPE::get) as MemoryModuleType<UUID>
val uuid = params.getString(1).asUUID ?: return@setUuidMemory DoubleValue.ZERO
val expiry = params.getIntOrNull(2) ?: -1
if (expiry != -1) {
entity.brain.setMemoryWithExpiry(memory, uuid, expiry.toLong())
} else {
entity.brain.setMemory(memory, uuid)
}
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["erase_memory"] = put@{ params ->
val memories = params.params.map { it.asString().asIdentifierDefaultingNamespace() }
.map(BuiltInRegistries.MEMORY_MODULE_TYPE::get)
functions["erase_memory"] = { params ->
val memories =
params.params
.map { it.asString().asIdentifierDefaultingNamespace() }
.map(BuiltInRegistries.MEMORY_MODULE_TYPE::get)
memories.forEach { entity.brain.eraseMemory(it) }
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["has_memory_value"] = put@{ params ->
functions["has_memory_value"] = hasMemoryValue@{ params ->
for (param in params.params) {
if (!entity.hasMemoryFromString(param.asString())) {
return@put DoubleValue.ZERO
return@hasMemoryValue DoubleValue.ZERO
}
}
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["lacks_memory_value"] = put@{ params ->
functions["lacks_memory_value"] = lacksMemoryValue@{ params ->
for (param in params.params) {
if (entity.hasMemoryFromString(param.asString())) {
return@put DoubleValue.ZERO
return@lacksMemoryValue DoubleValue.ZERO
}
}
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["is_doing_activity"] = put@{ params ->
functions["is_doing_activity"] = isDoingActivity@{ params ->
for (param in params.params) {
if (entity.isDoingActivityFromString(param.asString())) {
return@put DoubleValue.ONE
return@isDoingActivity DoubleValue.ONE
}
}
return@put DoubleValue.ZERO
DoubleValue.ZERO
}
map["can_see"] = put@{ params ->
functions["can_see"] = canSee@{ params ->
val target = params.get<MoValue>(0)
val range = params.getDoubleOrNull(1) ?: 32.0
if (target is ObjectValue<*>) {
val targetEntity = target.obj as? LivingEntity ?: return@put DoubleValue.ZERO
val targetEntity = target.obj as? LivingEntity ?: return@canSee DoubleValue.ZERO
val vector = targetEntity.eyePosition.subtract(entity.eyePosition).normalize()
val trace = entity.traceEntityCollision(
maxDistance = range.toFloat(),
stepDistance = 0.1F,
direction = vector,
entityClass = targetEntity.javaClass,
collideBlock = ClipContext.Fluid.NONE
)
return@put DoubleValue(targetEntity in (trace?.entities ?: emptyList()))
} else {
return@put DoubleValue.ZERO
val trace =
entity.traceEntityCollision(
maxDistance = range.toFloat(),
stepDistance = 0.1F,
direction = vector,
entityClass = targetEntity.javaClass,
collideBlock = ClipContext.Fluid.NONE,
)
return@canSee DoubleValue(targetEntity in (trace?.entities ?: emptyList()))
}
DoubleValue.ZERO
}
when (entity) {
is PathfinderMob -> {
functions["walk_to"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val speedMultiplier = params.getDoubleOrNull(3) ?: 0.35
if (entity.brain.checkMemory(MemoryModuleType.WALK_TARGET, MemoryStatus.REGISTERED)) {
entity.brain.setMemory(
MemoryModuleType.WALK_TARGET,
WalkTarget(Vec3(x, y, z), speedMultiplier.toFloat(), 1),
)
entity.brain.setMemory(
MemoryModuleType.LOOK_TARGET,
BlockPosTracker(Vec3(x, y + entity.eyeHeight, z)),
)
} else {
entity.navigation.moveTo(x, y, z, speedMultiplier)
entity.lookControl.setLookAt(Vec3(x, y + entity.eyeHeight, z))
}
}
functions["has_walk_target"] = {
DoubleValue(entity.brain.getMemorySafely(MemoryModuleType.WALK_TARGET).isPresent || entity.isPathFinding)
}
functions["set_can_float"] = { params ->
val canFloat = params.getBooleanOrNull(0) != false
entity.navigation.setCanFloat(canFloat)
DoubleValue.ONE
}
functions["get_pathfinding_malus"] = getPfMalus@{ params ->
val type = PathType.entries.find { it.name == params.getString(0).uppercase() }
if (type != null) {
return@getPfMalus DoubleValue(entity.getPathfindingMalus(type))
}
Cobblemon.LOGGER.error("Cannot get pathfinding type, unknown value: ${params.getString(0)}")
DoubleValue.ZERO
}
functions["set_pathfinding_malus"] = setPfMalus@{ params ->
val type = PathType.entries.find { it.name == params.getString(0).uppercase() }
val malus = params.getDouble(1).toFloat()
if (type != null) {
entity.setPathfindingMalus(type, malus)
return@setPfMalus DoubleValue.ONE
}
Cobblemon.LOGGER.error("Cannot set pathfinding type, unknown value: ${params.getString(0)}")
DoubleValue.ZERO
}
}
}
if (entity is PathfinderMob) {
map["walk_to"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val speedMultiplier = params.getDoubleOrNull(3) ?: 0.35
if (entity.brain.checkMemory(MemoryModuleType.WALK_TARGET, MemoryStatus.REGISTERED)) {
entity.brain.setMemory(
MemoryModuleType.WALK_TARGET,
WalkTarget(Vec3(x, y, z), speedMultiplier.toFloat(), 1)
)
entity.brain.setMemory(
MemoryModuleType.LOOK_TARGET,
BlockPosTracker(Vec3(x, y + entity.eyeHeight, z))
)
} else {
entity.navigation.moveTo(x, y, z, speedMultiplier)
entity.lookControl.setLookAt(Vec3(x, y + entity.eyeHeight, z))
}
}
map["has_walk_target"] = { _ ->
DoubleValue(entity.brain.getMemorySafely(MemoryModuleType.WALK_TARGET).isPresent || entity.isPathFinding)
}
map["set_can_float"] = { params ->
val canFloat = params.getBooleanOrNull(0) != false
entity.navigation.setCanFloat(canFloat)
DoubleValue.ONE
}
map["get_pathfinding_malus"] = put@{ params ->
val type = PathType.entries.find { it.name == params.getString(0).uppercase() }
if (type != null) {
return@put DoubleValue(entity.getPathfindingMalus(type))
}
Cobblemon.LOGGER.error("Unknown pathfinding type: ${params.getString(0)}")
return@put DoubleValue.ZERO
}
map["set_pathfinding_malus"] = put@{ params ->
val type = PathType.entries.find { it.name == params.getString(0).uppercase() }
val malus = params.getDouble(1).toFloat()
if (type != null) {
entity.setPathfindingMalus(type, malus)
return@put DoubleValue.ONE
}
Cobblemon.LOGGER.error("Unknown pathfinding type: ${params.getString(0)}")
return@put DoubleValue.ZERO
}
}
return map
return functions
}
}
@@ -50,18 +50,23 @@ import kotlin.collections.any
object NPCMoLangFunctions : AbstractMoLangFunctionHolder<NPCEntity>() {
override fun NPCEntity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val npc = this
val map = hashMapOf<String, (MoParams) -> Any>()
map["class"] = { StringValue(npc.npc.id.toString()) }
map["name"] = { StringValue(npc.name.string) }
map["level"] = { DoubleValue(npc.level) }
map["has_aspect"] = { params -> DoubleValue(npc.aspects.contains(params.getString(0))) }
map["in_battle"] = { DoubleValue(npc.isInBattle()) }
map["battles"] = {
ArrayStruct(npc.battleIds.mapNotNull { BattleRegistry.getBattle(it)?.struct }
.mapIndexed { index, value -> "$index" to value }.toMap())
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["class"] = { StringValue(npc.npc.id.toString()) }
functions["name"] = { StringValue(npc.name.string) }
functions["level"] = { DoubleValue(npc.level) }
functions["has_aspect"] = { params -> DoubleValue(npc.aspects.contains(params.getString(0))) }
functions["in_battle"] = { DoubleValue(npc.isInBattle()) }
functions["battles"] = {
ArrayStruct(
npc.battleIds
.mapNotNull { BattleRegistry.getBattle(it)?.struct }
.mapIndexed { index, value -> "$index" to value }
.toMap(),
)
}
map["stop_battles"] = { _ -> npc.battleIds.forEach { BattleRegistry.getBattle(it)?.stop() } }
map["run_script_on_client"] = { params ->
functions["stop_battles"] = { npc.battleIds.forEach { BattleRegistry.getBattle(it)?.stop() } }
functions["run_script_on_client"] = { params ->
val world = npc.level()
if (world is ServerLevel) {
val script = params.getString(0)
@@ -70,141 +75,142 @@ object NPCMoLangFunctions : AbstractMoLangFunctionHolder<NPCEntity>() {
}
Unit
}
map["run_script"] = { params ->
functions["run_script"] = { params ->
val script = params.getString(0).asIdentifierDefaultingNamespace()
val runtime = MoLangRuntime()
runtime.environment.cloneFrom(params.environment)
CobblemonScripts.run(script, runtime) ?: DoubleValue(0)
}
map["set_movable"] = put@{ params ->
functions["set_movable"] = { params ->
val movable = params.getBooleanOrNull(0) != false
npc.isMovable = movable
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["set_invulnerable"] = put@{ params ->
functions["set_invulnerable"] = { params ->
val invulnerable = params.getBooleanOrNull(0) != false
npc.isInvulnerable = invulnerable
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["set_leashable"] = put@{ params ->
functions["set_leashable"] = { params ->
val leashable = params.getBooleanOrNull(0) != false
npc.isLeashable = leashable
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["set_allow_projectile_hits"] = put@{ params ->
functions["set_allow_projectile_hits"] = { params ->
val allowProjectileHits = params.getBooleanOrNull(0) != false
npc.allowProjectileHits = allowProjectileHits
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["set_name_tag_visible"] = put@{ params ->
functions["set_name_tag_visible"] = { params ->
val nameTagVisible = params.getBooleanOrNull(0) != false
npc.hideNameTag = !nameTagVisible
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["unset_interaction"] = put@{
functions["unset_interaction"] = {
npc.interaction = null
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["set_dialogue_interaction"] = put@{ params ->
functions["set_dialogue_interaction"] = { params ->
val dialogue = params.getString(0).asIdentifierDefaultingNamespace()
npc.interaction = DialogueNPCInteractionConfiguration().also {
it.dialogue = dialogue
}
return@put DoubleValue.ONE
npc.interaction =
DialogueNPCInteractionConfiguration().also {
it.dialogue = dialogue
}
DoubleValue.ONE
}
map["set_script_interaction"] = put@{ params ->
functions["set_script_interaction"] = { params ->
val script = params.getString(0).asIdentifierDefaultingNamespace()
npc.interaction = ScriptNPCInteractionConfiguration().also {
it.script = script
}
return@put DoubleValue.ONE
npc.interaction =
ScriptNPCInteractionConfiguration().also {
it.script = script
}
DoubleValue.ONE
}
map["set_player_texture"] = put@{ params ->
functions["set_player_texture"] = setPlayerTexture@{ params ->
val username = params.getString(0)
// Re-applying it would be unnecessarily laggy.
if (username == npc.data.map["player_texture_username"]?.asString()) {
return@put DoubleValue.ZERO
return@setPlayerTexture DoubleValue.ZERO
}
npc.loadTextureFromGameProfileName(username)
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["unset_player_texture"] = put@{
functions["unset_player_texture"] = {
npc.unloadTexture()
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["set_resource_identifier"] = put@{ params ->
functions["set_resource_identifier"] = { params ->
val identifier = params.getStringOrNull(0)?.asIdentifierDefaultingNamespace()
npc.forcedResourceIdentifier = identifier
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["unset_resource_identifier"] = put@{
functions["unset_resource_identifier"] = {
npc.forcedResourceIdentifier = null
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["set_class"] = put@{ params ->
functions["set_class"] = setClass@{ params ->
val identifier = params.getString(0).asIdentifierDefaultingNamespace()
val npcClass = NPCClasses.getByIdentifier(identifier)
if (npcClass != null) {
npc.npc = npcClass
return@put DoubleValue.ONE
} else {
Cobblemon.LOGGER.error("Unknown NPC class: $identifier")
return@put DoubleValue.ZERO
return@setClass DoubleValue.ONE
}
Cobblemon.LOGGER.error("Unknown NPC class: $identifier")
DoubleValue.ZERO
}
map["set_render_scale"] = put@{ params ->
functions["set_render_scale"] = { params ->
val scale = params.getDouble(0)
npc.renderScale = scale.toFloat()
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["render_scale"] = { _ -> DoubleValue(npc.renderScale) }
map["set_hitbox_scale"] = put@{ params ->
functions["render_scale"] = { DoubleValue(npc.renderScale) }
functions["set_hitbox_scale"] = { params ->
val scale = params.getDouble(0).toFloat()
npc.hitboxScale = scale
npc.refreshDimensions()
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["hitbox_scale"] = { _ -> DoubleValue(npc.hitboxScale) }
map["set_hitbox"] = put@{ params ->
functions["hitbox_scale"] = { DoubleValue(npc.hitboxScale) }
functions["set_hitbox"] = setHitbox@{ params ->
if (params.params.isEmpty()) {
npc.hitbox = null
return@put DoubleValue.ONE
return@setHitbox DoubleValue.ONE
}
val width = params.getDouble(0).toFloat()
val height = params.getDouble(1).toFloat()
val eyeHeight = params.getDoubleOrNull(2)?.toFloat() ?: (height * 0.85F)
npc.hitbox = EntityDimensions.scalable(width, height).withEyeHeight(eyeHeight)
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["unset_hitbox"] = put@{
functions["unset_hitbox"] = {
npc.hitbox = null
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["aspects"] = put@{
functions["aspects"] = {
val aspects = npc.aspects
return@put aspects.asArrayValue { StringValue(it) }
aspects.asArrayValue { StringValue(it) }
}
map["add_aspect"] = put@{ params ->
functions["add_aspect"] = { params ->
val aspects = params.params.map { it.asString() }
npc.appliedAspects.addAll(aspects)
npc.updateAspects()
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["remove_aspect"] = put@{ params ->
functions["remove_aspect"] = { params ->
val aspects = params.params.map { it.asString() }
npc.appliedAspects.removeAll(aspects.toSet())
npc.updateAspects()
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["party"] = put@{
val party = npc.party ?: return@put DoubleValue.ZERO
return@put party.asMoLangValue()
functions["party"] = party@{
val party = npc.party ?: return@party DoubleValue.ZERO
party.asMoLangValue()
}
map["create_npc_party"] = put@{
functions["create_npc_party"] = {
val party = NPCPartyStore(npc)
return@put party.asMoLangValue()
party.asMoLangValue()
}
map["set_npc_party"] = { params ->
functions["set_npc_party"] = { params ->
val party = params.get<MoValue>(0)
if (party is ObjectValue<*>) {
npc.party = party.obj as NPCPartyStore
@@ -213,18 +219,19 @@ object NPCMoLangFunctions : AbstractMoLangFunctionHolder<NPCEntity>() {
}
DoubleValue.ONE
}
map["run_action_effect"] = put@{ params ->
functions["run_action_effect"] = runActionEffect@{ params ->
val runtime = MoLangRuntime().setup()
runtime.environment.cloneFrom(params.environment)
runtime.withNPCValue(value = npc)
val actionEffect = ActionEffects.actionEffects[params.getString(0).asIdentifierDefaultingNamespace()]
if (actionEffect != null) {
val context = ActionEffectContext(
actionEffect = actionEffect,
providers = mutableListOf(NPCProvider(npc)),
runtime = runtime,
level = npc.level()
)
val context =
ActionEffectContext(
actionEffect = actionEffect,
providers = mutableListOf(NPCProvider(npc)),
runtime = runtime,
level = npc.level(),
)
npc.actionEffect = context
npc.brain.setMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT, context)
npc.brain.setActiveActivityIfPossible(CobblemonActivities.ACTION_EFFECT)
@@ -236,37 +243,40 @@ object NPCMoLangFunctions : AbstractMoLangFunctionHolder<NPCEntity>() {
}
}
return@put DoubleValue.ONE
return@runActionEffect DoubleValue.ONE
}
return@put DoubleValue.ZERO
DoubleValue.ZERO
}
map["put_pokemon_in_healer"] = put@{ params ->
val healer = npc.level()
.getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE)
.orElse(null) ?: return@put DoubleValue.ZERO
val party = npc.party ?: return@put DoubleValue.ZERO
functions["put_pokemon_in_healer"] = putPokeInHealer@{ params ->
val healer =
npc
.level()
.getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE)
.orElse(null) ?: return@putPokeInHealer DoubleValue.ZERO
val party = npc.party ?: return@putPokeInHealer DoubleValue.ZERO
if (healer.canHeal(party)) {
healer.activate(npc.uuid, party)
return@put DoubleValue.ONE
} else {
return@put DoubleValue.ZERO
return@putPokeInHealer DoubleValue.ONE
}
DoubleValue.ZERO
}
map["look_at_position"] = { params ->
functions["look_at_position"] = { params ->
val pos = Vec3(params.getDouble(0), params.getDouble(1), params.getDouble(2))
npc.lookAt(EntityAnchorArgument.Anchor.EYES, pos)
}
map["environment"] = { _ -> npc.runtime.environment }
map["party"] = { npc.party?.struct ?: DoubleValue.ZERO }
map["has_party"] = { DoubleValue(npc.party != null) }
map["is_npc"] = { DoubleValue.ONE }
map["can_battle"] =
{ DoubleValue(npc.party?.any { it.currentHealth > 0 } == true || npc.npc.party?.isStatic == false) }
map["set_battle_theme"] = put@{ params ->
functions["environment"] = { npc.runtime.environment }
functions["party"] = { npc.party?.struct ?: DoubleValue.ZERO }
functions["has_party"] = { DoubleValue(npc.party != null) }
functions["is_npc"] = { DoubleValue.ONE }
functions["can_battle"] = {
DoubleValue(npc.party?.any { it.currentHealth > 0 } == true || npc.npc.party?.isStatic == false)
}
functions["set_battle_theme"] = { params ->
val soundId = params.getString(0).asResource()
npc.npc.battleTheme = soundId
return@put DoubleValue.ONE
DoubleValue.ONE
}
return map
return functions
}
}
@@ -23,40 +23,40 @@ import com.cobblemon.mod.common.util.getBooleanOrNull
object PCMoLangFunctions : AbstractMoLangFunctionHolder<PCStore>() {
override fun PCStore.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val pc = this
val map = mutableMapOf<String, (MoParams) -> Any>()
val functions = hashMapOf<String, (MoParams) -> Any>()
map["get_pokemon"] = getPokemon@{ params ->
functions["get_pokemon"] = getPokemon@{ params ->
val box = params.getInt(0)
val slot = params.getInt(1)
val pokemon = pc[PCPosition(box, slot)] ?: return@getPokemon DoubleValue.ZERO
return@getPokemon pokemon.struct
pokemon.struct
}
map["set_pokemon"] = { params ->
functions["set_pokemon"] = { params ->
val box = params.getInt(0)
val slot = params.getInt(1)
val pokemon = params.get<ObjectValue<Pokemon>>(2).obj
pc[PCPosition(box, slot)] = pokemon
DoubleValue.ONE
}
map["resize"] = { params ->
functions["resize"] = { params ->
val newSize = params.getInt(0)
val lockNewSize = params.getBooleanOrNull(1) == true
pc.resize(newSize, lockNewSize)
DoubleValue.ONE
}
map["get_box_count"] = { DoubleValue(pc.boxes.size.toDouble()) }
map["has_unlocked_wallpaper"] = { params ->
functions["get_box_count"] = { DoubleValue(pc.boxes.size.toDouble()) }
functions["has_unlocked_wallpaper"] = { params ->
val wallpaper = params.getString(0).asIdentifierDefaultingNamespace()
DoubleValue(pc.unlockedWallpapers.contains(wallpaper))
}
map["get_unlocked_wallpapers"] = { pc.unlockedWallpapers.asArrayValue { StringValue(it.toString()) } }
map["unlock_wallpaper"] = unlockWallpaper@{
functions["get_unlocked_wallpapers"] = { pc.unlockedWallpapers.asArrayValue { StringValue(it.toString()) } }
functions["unlock_wallpaper"] = unlockWallpaper@{
val wallpaper = it.getString(0).asIdentifierDefaultingNamespace()
val playSound = it.getBooleanOrNull(1) != false
CobblemonUnlockableWallpapers.unlockableWallpapers[wallpaper] ?: return@unlockWallpaper DoubleValue.ZERO
return@unlockWallpaper DoubleValue(pc.unlockWallpaper(wallpaper, playSound))
DoubleValue(pc.unlockWallpaper(wallpaper, playSound))
}
return map
return functions
}
}
@@ -14,21 +14,23 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.pokemon.Pokemon
object PartyMoLangFunctions: AbstractMoLangFunctionHolder<PartyStore>() {
object PartyMoLangFunctions : AbstractMoLangFunctionHolder<PartyStore>() {
override fun PartyStore.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val party = this
val map = hashMapOf<String, (MoParams) -> Any>()
map["get_pokemon"] = getPokemon@{ params ->
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["get_pokemon"] = getPokemon@{ params ->
val index = params.getInt(0)
val pokemon = party.get(index) ?: return@getPokemon DoubleValue.ZERO
pokemon.struct
}
map["set_pokemon"] = { params ->
functions["set_pokemon"] = { params ->
val index = params.getInt(0)
val pokemon = params.get<ObjectValue<Pokemon>>(1).obj
party.set(index, pokemon)
DoubleValue.ONE
}
return map
return functions
}
}
@@ -17,12 +17,12 @@ import com.bedrockk.molang.runtime.value.MoValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonBlockEntities
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.tms.TechnicalMachines
import com.cobblemon.mod.common.api.dialogue.PlayerDialogueFaceProvider
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
import com.cobblemon.mod.common.api.molang.ObjectValue
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.api.tms.TechnicalMachines
import com.cobblemon.mod.common.battles.BattleBuilder
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.entity.npc.NPCEntity
@@ -52,355 +52,389 @@ import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
import net.minecraft.stats.Stats
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.GameType
import kotlin.collections.iterator
object PlayerMoLangFunctions : AbstractMoLangFunctionHolder<Player>() {
override fun Player.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val player = this
val map = mutableMapOf<String, (MoParams) -> Any>()
map["username"] = { _ -> StringValue(player.gameProfile.name) }
map["uuid"] = { _ -> StringValue(player.gameProfile.id.toString()) }
map["main_held_item"] = { _ -> player.mainHandItem.asMoLangValue(player.registryAccess()) }
map["off_held_item"] = { _ -> player.offhandItem.asMoLangValue(player.registryAccess()) }
map["inventory"] = put@{ _ ->
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["username"] = { StringValue(player.gameProfile.name) }
functions["uuid"] = { StringValue(player.gameProfile.id.toString()) }
functions["main_held_item"] = { player.mainHandItem.asMoLangValue(player.registryAccess()) }
functions["off_held_item"] = { player.offhandItem.asMoLangValue(player.registryAccess()) }
functions["inventory"] = {
val inventory = player.inventory
val items = ArrayStruct(hashMapOf())
for (i in 0 until inventory.containerSize) {
items.setDirectly("$i", inventory.getItem(i).asMoLangValue(player.registryAccess()))
}
return@put items
items
}
map["has_inventory_space"] = put@{ _ ->
functions["has_inventory_space"] = {
val inventory = player.inventory
return@put if (inventory.getFreeSlot() != -1) DoubleValue.ONE else DoubleValue.ZERO
if (inventory.freeSlot != -1) DoubleValue.ONE else DoubleValue.ZERO
}
map["set_inventory_slot"] = put@{ params ->
functions["set_inventory_slot"] = setInvSlot@{ params ->
val slot = params.getInt(0)
val inventory = player.inventory
if (slot !in 0 until inventory.containerSize) return@put DoubleValue.ZERO
if (slot !in 0 until inventory.containerSize) return@setInvSlot DoubleValue.ZERO
val value = params.getOrNull<MoValue>(1) ?: return@put DoubleValue.ZERO
val value = params.getOrNull<MoValue>(1) ?: return@setInvSlot DoubleValue.ZERO
val stack: ItemStack? = when (value) {
is ObjectValue<*> -> value.obj as? ItemStack
is StringValue -> {
val id = ResourceLocation.parse(value.value)
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(id)
?: return@put DoubleValue.ZERO
ItemStack(item)
val stack: ItemStack? =
when (value) {
is ObjectValue<*> -> {
value.obj as? ItemStack
}
is StringValue -> {
val id = ResourceLocation.parse(value.value)
val item =
player.registryAccess().registryOrThrow(Registries.ITEM).get(id)
?: return@setInvSlot DoubleValue.ZERO
ItemStack(item)
}
else -> {
null
}
}
else -> null
}
if (stack == null) return@put DoubleValue.ZERO
if (stack == null) return@setInvSlot DoubleValue.ZERO
inventory.setItem(slot, stack)
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["give_item"] = put@{ params ->
functions["give_item"] = giveItem@{ params ->
val inventory = player.inventory
val freeSlot = inventory.getFreeSlot()
val value = params.getOrNull<MoValue>(0) ?: return@put DoubleValue.ZERO
val freeSlot = inventory.freeSlot
val value = params.getOrNull<MoValue>(0) ?: return@giveItem DoubleValue.ZERO
val dropIfFull = params.getBooleanOrNull(1) ?: false
val stack: ItemStack? = when (value) {
is ObjectValue<*> -> value.obj as? ItemStack
is StringValue -> {
val id = ResourceLocation.parse(value.value)
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(id)
?: return@put DoubleValue.ZERO
ItemStack(item)
val stack: ItemStack? =
when (value) {
is ObjectValue<*> -> {
value.obj as? ItemStack
}
is StringValue -> {
val id = ResourceLocation.parse(value.value)
val item =
player.registryAccess().registryOrThrow(Registries.ITEM).get(id)
?: return@giveItem DoubleValue.ZERO
ItemStack(item)
}
else -> {
null
}
}
else -> null
}
if (stack == null) return@put DoubleValue.ZERO
if (stack == null) return@giveItem DoubleValue.ZERO
if (freeSlot == -1) {
if (dropIfFull) {
player.drop(stack, false)
return@put DoubleValue.ONE
return@giveItem DoubleValue.ONE
} else {
return@put DoubleValue.ZERO
return@giveItem DoubleValue.ZERO
}
}
inventory.setItem(freeSlot, stack)
return@put DoubleValue.ONE
DoubleValue.ONE
}
map["face"] = { params ->
functions["face"] = { params ->
ObjectValue(
PlayerDialogueFaceProvider(
player.uuid,
params.getBooleanOrNull(0) != false
)
params.getBooleanOrNull(0) != false,
),
)
}
map["swing_hand"] = { _ -> player.swing(player.usedItemHand) }
map["food_level"] = { _ -> DoubleValue(player.foodData.foodLevel) }
map["saturation_level"] = { _ -> DoubleValue(player.foodData.saturationLevel) }
map["tell"] = { params ->
functions["swing_hand"] = { player.swing(player.usedItemHand) }
functions["food_level"] = { DoubleValue(player.foodData.foodLevel) }
functions["saturation_level"] = { DoubleValue(player.foodData.saturationLevel) }
functions["tell"] = { params ->
val message = params.getString(0).text()
val overlay = params.getBooleanOrNull(1) == true
player.displayClientMessage(message, overlay)
}
map["teleport"] = { params ->
functions["teleport"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val playParticleOptionss = params.getBooleanOrNull(3) ?: false
player.randomTeleport(x, y, z, playParticleOptionss)
val playParticleOptions = params.getBooleanOrNull(3) ?: false
player.randomTeleport(x, y, z, playParticleOptions)
}
map["heal"] = { params ->
functions["heal"] = { params ->
val amount = params.getDoubleOrNull(0) ?: player.maxHealth
player.heal(amount.toFloat())
}
map["environment"] = {
functions["environment"] = {
val environment = MoLangEnvironment()
environment.query = player.asMoLangValue()
environment
}
map["is_player"] = { DoubleValue.ONE }
map["riding_pokemon"] = put@{
functions["is_player"] = { DoubleValue.ONE }
functions["riding_pokemon"] = ridingPokemon@{
val vehicle = player.vehicle
if (vehicle is PokemonEntity) {
return@put vehicle.struct
} else {
return@put DoubleValue.ZERO
return@ridingPokemon vehicle.struct
}
DoubleValue.ZERO
}
if (player is ServerPlayer) {
map["seen_credits"] = { _ ->
DoubleValue(player.seenCredits)
}
map["is_in_dialogue"] = { _ ->
DoubleValue(player.isInDialogue)
}
map["active_dialogue"] = put@{ _ ->
if (player.isInDialogue) {
return@put player.activeDialogue?.toMoLangStruct() ?: DoubleValue.ZERO
} else {
when (player) {
is ServerPlayer -> {
functions["seen_credits"] = { DoubleValue(player.seenCredits) }
functions["is_in_dialogue"] = { DoubleValue(player.isInDialogue) }
functions["active_dialogue"] = activeDialogue@{
if (player.isInDialogue) {
return@activeDialogue player.activeDialogue?.toMoLangStruct() ?: DoubleValue.ZERO
}
DoubleValue.ZERO
}
}
map["is_spectator"] = { DoubleValue(player.isSpectator) }
map["is_creative"] = { DoubleValue(player.isCreative) }
map["is_survival"] = { DoubleValue(player.gameMode.isSurvival) }
map["is_adventure"] = { DoubleValue(player.gameMode.gameModeForPlayer == GameType.ADVENTURE) }
map["run_command"] = { params ->
val command = params.getString(0)
player.server.commands.performPrefixedCommand(player.createCommandSourceStack(), command)
}
map["set_battle_theme"] = put@{ params ->
val soundId = params.getString(0).asResource()
Cobblemon.playerDataManager.getGenericData(player).battleTheme = soundId
return@put DoubleValue.ONE
}
map["battle_music"] = put@{ params ->
val soundId = params.getString(0).asResource()
val volume = params.getDoubleOrNull(1)?.toFloat() ?: 1.0f
val pitch = params.getDoubleOrNull(2)?.toFloat() ?: 1.0f
val restart = params.getBooleanOrNull(3) ?: true
functions["is_spectator"] = { DoubleValue(player.isSpectator) }
functions["is_creative"] = { DoubleValue(player.isCreative) }
functions["is_survival"] = { DoubleValue(player.gameMode.isSurvival) }
functions["is_adventure"] = { DoubleValue(player.gameMode.gameModeForPlayer == GameType.ADVENTURE) }
functions["run_command"] = { params ->
val command = params.getString(0)
player.server.commands.performPrefixedCommand(player.createCommandSourceStack(), command)
}
functions["set_battle_theme"] = { params ->
val soundId = params.getString(0).asResource()
Cobblemon.playerDataManager.getGenericData(player).battleTheme = soundId
DoubleValue.ONE
}
functions["battle_music"] = battleMusic@{ params ->
val soundId = params.getString(0).asResource()
val volume = params.getDoubleOrNull(1)?.toFloat() ?: 1.0f
val pitch = params.getDoubleOrNull(2)?.toFloat() ?: 1.0f
val restart = params.getBooleanOrNull(3) ?: true
if (soundId != null) {
val packet = BattleMusicPacket(soundId, volume, pitch, restart)
if (soundId != null) {
val packet = BattleMusicPacket(soundId, volume, pitch, restart)
packet.sendToPlayer(player)
return@battleMusic DoubleValue.ONE
}
DoubleValue.ZERO
}
functions["stop_battle_music"] = {
val packet = BattleMusicPacket(null)
packet.sendToPlayer(player)
return@put DoubleValue.ONE
} else {
return@put DoubleValue.ZERO
DoubleValue.ONE
}
}
map["stop_battle_music"] = put@{ _ ->
val packet = BattleMusicPacket(null)
packet.sendToPlayer(player)
return@put DoubleValue.ONE
}
map["play_sound_on_server"] = { params ->
val sound = params.getString(0).asResource()
val soundSource = SoundSource.valueOf(params.getString(1).uppercase())
val volume = params.getDoubleOrNull(2)?.toFloat() ?: 1.0f
val pitch = params.getDoubleOrNull(3)?.toFloat() ?: 1.0f
functions["play_sound_on_server"] = { params ->
val sound = params.getString(0).asResource()
val soundSource = SoundSource.valueOf(params.getString(1).uppercase())
val volume = params.getDoubleOrNull(2)?.toFloat() ?: 1.0f
val pitch = params.getDoubleOrNull(3)?.toFloat() ?: 1.0f
val packet =
UnvalidatedPlaySoundS2CPacket(sound, soundSource, player.x, player.y, player.z, volume, pitch)
packet.sendToPlayer(player)
}
map["is_party_at_full_health"] = { _ ->
DoubleValue(player.party().none(Pokemon::canBeHealed))
}
map["can_heal_at_healer"] = put@{ params ->
val pos = params.get<ArrayStruct>(0).asBlockPos()
val healer = player.level().getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null)
?: return@put DoubleValue.ZERO
val party = player.party()
return@put DoubleValue(healer.canHeal(party))
}
map["put_pokemon_in_healer"] = put@{ params ->
val healer = player.level()
.getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE)
.orElse(null) ?: return@put DoubleValue.ZERO
val party = player.party()
if (healer.canHeal(party)) {
healer.activate(player.uuid, party)
return@put DoubleValue.ONE
} else {
return@put DoubleValue.ZERO
val packet =
UnvalidatedPlaySoundS2CPacket(
sound,
soundSource,
player.x,
player.y,
player.z,
volume,
pitch,
)
packet.sendToPlayer(player)
}
}
map["party"] = { player.party().struct }
map["pc"] = { player.pc().struct }
map["has_permission"] = { params ->
DoubleValue(
Cobblemon.permissionValidator.hasPermission(
player,
params.getString(0),
params.getIntOrNull(1) ?: 4
functions["is_party_at_full_health"] = { DoubleValue(player.party().none(Pokemon::canBeHealed)) }
functions["can_heal_at_healer"] = canHealAtHealer@{ params ->
val pos = params.get<ArrayStruct>(0).asBlockPos()
val healer =
player.level().getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null)
?: return@canHealAtHealer DoubleValue.ZERO
val party = player.party()
DoubleValue(healer.canHeal(party))
}
functions["put_pokemon_in_healer"] = putPokemonAtHealer@{ params ->
val healer =
player
.level()
.getBlockEntity(
params.get<ArrayStruct>(0).asBlockPos(),
CobblemonBlockEntities.HEALING_MACHINE,
).orElse(null) ?: return@putPokemonAtHealer DoubleValue.ZERO
val party = player.party()
if (healer.canHeal(party)) {
healer.activate(player.uuid, party)
return@putPokemonAtHealer DoubleValue.ONE
}
DoubleValue.ZERO
}
functions["party"] = { player.party().struct }
functions["pc"] = { player.pc().struct }
functions["has_permission"] = { params ->
DoubleValue(
Cobblemon.permissionValidator.hasPermission(
player,
params.getString(0),
params.getIntOrNull(1) ?: 4,
),
)
)
}
map["data"] = { params -> Cobblemon.molangData.load(player.uuid, params.getStringOrNull(0)) }
map["save_data"] = { params -> Cobblemon.molangData.save(player.uuid, params.getStringOrNull(0)) }
map["in_battle"] = { DoubleValue(player.isInBattle()) }
map["battle"] = { player.getBattleState()?.first?.struct ?: DoubleValue.ZERO }
map["get_npc_data"] = put@{ params ->
val npcId = ((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
?: params.getString(0)
val data = Cobblemon.molangData.load(player.uuid, params.getStringOrNull(1))
if (data.map.containsKey(npcId)) {
return@put data.map[npcId]!!
} else {
}
functions["data"] = { params -> Cobblemon.molangData.load(player.uuid, params.getStringOrNull(0)) }
functions["save_data"] = { params -> Cobblemon.molangData.save(player.uuid, params.getStringOrNull(0)) }
functions["in_battle"] = { DoubleValue(player.isInBattle()) }
functions["battle"] = { player.getBattleState()?.first?.struct ?: DoubleValue.ZERO }
functions["get_npc_data"] = getNpcData@{ params ->
val npcId =
((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
?: params.getString(0)
val data = Cobblemon.molangData.load(player.uuid, params.getStringOrNull(1))
if (data.map.containsKey(npcId)) {
return@getNpcData data.map[npcId]!!
}
val vars = VariableStruct()
data.map[npcId] = vars
return@put vars
vars
}
}
map["get_npc_variable"] = put@{ params ->
val npcId = ((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
?: params.getString(0)
val variable = params.getString(1)
val data = Cobblemon.molangData.load(player.uuid, params.getStringOrNull(2))
if (data.map.containsKey(npcId)) {
return@put (data.map[npcId] as VariableStruct).map[variable] ?: DoubleValue.ZERO
} else {
return@put DoubleValue.ZERO
}
}
map["set_npc_variable"] = put@{ params ->
val npcId = ((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
?: params.getString(0)
val variable = params.getString(1)
val value = params.get<MoValue>(2)
val saveAfterwards = params.getBooleanOrNull(3) != false
val path = params.getStringOrNull(4)
val data = Cobblemon.molangData.load(player.uuid, path)
val npcData = data.map.getOrPut(npcId) { VariableStruct() } as VariableStruct
npcData.map[variable] = value
if (saveAfterwards) {
Cobblemon.molangData.save(player.uuid, path)
}
return@put DoubleValue.ONE
}
map["pokedex"] = { player.pokedex().struct }
map["has_advancement"] = put@{ params ->
val requiredAdvancement = ResourceLocation.parse(params.getString(0))
for (entry in player.advancements.progress) {
if (entry.key.id == requiredAdvancement && entry.value.isDone) {
return@put DoubleValue.ONE
functions["get_npc_variable"] = getNpcVariable@{ params ->
val npcId =
((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
?: params.getString(0)
val variable = params.getString(1)
val data = Cobblemon.molangData.load(player.uuid, params.getStringOrNull(2))
if (data.map.containsKey(npcId)) {
return@getNpcVariable (data.map[npcId] as VariableStruct).map[variable] ?: DoubleValue.ZERO
}
DoubleValue.ZERO
}
return@put DoubleValue.ZERO
}
map["has_tm_move_unlocked"] = put@{ params ->
val move = Moves.getByName(params.getString(0)) ?: return@put DoubleValue.ZERO
val tm = TechnicalMachines.moveToTM[move] ?: return@put DoubleValue.ZERO
DoubleValue(if (player.tmList().learnedTMs.contains(tm.id)) 1.0 else 0.0)
}
map["unlock_tm_move"] = put@{ params ->
val move = Moves.getByName(params.getString(0)) ?: return@put DoubleValue.ZERO
val tm = TechnicalMachines.moveToTM[move] ?: return@put DoubleValue.ZERO
player.tmList().syncTMFromMove(move)
DoubleValue(if (player.tmList().learnedTMs.contains(tm.id)) 1.0 else 0.0)
}
map["lock_tm_move"] = put@{ params ->
val move = Moves.getByName(params.getString(0)) ?: return@put DoubleValue.ZERO
val tm = TechnicalMachines.moveToTM[move] ?: return@put DoubleValue.ZERO
player.tmList().syncTMLockFromMove(move)
DoubleValue(if (player.tmList().learnedTMs.contains(tm.id)) 0.0 else 1.0)
}
map["start_battle"] = put@{ params ->
val opponentValue = params.get<MoValue>(0)
val opponent = if (opponentValue is ObjectValue<*>) {
opponentValue.obj as ServerPlayer
} else {
val paramString = opponentValue.asString()
val playerUUID = paramString.asUUID
if (playerUUID != null) {
server()?.playerList?.getPlayer(playerUUID) ?: return@put DoubleValue.ZERO
} else {
server()?.playerList?.getPlayerByName(paramString) ?: return@put DoubleValue.ZERO
functions["set_npc_variable"] = { params ->
val npcId =
((params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? NPCEntity)?.stringUUID
?: params.getString(0)
val variable = params.getString(1)
val value = params.get<MoValue>(2)
val saveAfterwards = params.getBooleanOrNull(3) != false
val path = params.getStringOrNull(4)
val data = Cobblemon.molangData.load(player.uuid, path)
val npcData = data.map.getOrPut(npcId) { VariableStruct() } as VariableStruct
npcData.map[variable] = value
if (saveAfterwards) {
Cobblemon.molangData.save(player.uuid, path)
}
DoubleValue.ONE
}
val format = params.getStringOrNull(1)
?.let(BattleFormat::fromFormatIdentifier)
?: BattleFormat.GEN_9_SINGLES
functions["pokedex"] = { player.pokedex().struct }
functions["has_advancement"] = hasAdvancement@{ params ->
val requiredAdvancement = ResourceLocation.parse(params.getString(0))
player.advancements.progress.forEach { (holder, progress) ->
if (holder.id == requiredAdvancement && progress.isDone) {
return@hasAdvancement DoubleValue.ONE
}
}
DoubleValue.ZERO
}
functions["has_tm_move_unlocked"] = hasTmMoveUnlocked@{ params ->
val move = Moves.getByName(params.getString(0)) ?: return@hasTmMoveUnlocked DoubleValue.ZERO
val tm = TechnicalMachines.moveToTM[move] ?: return@hasTmMoveUnlocked DoubleValue.ZERO
DoubleValue(if (player.tmList().learnedTMs.contains(tm.id)) 1.0 else 0.0)
}
functions["unlock_tm_move"] = unlockTmMove@{ params ->
val move = Moves.getByName(params.getString(0)) ?: return@unlockTmMove DoubleValue.ZERO
val tm = TechnicalMachines.moveToTM[move] ?: return@unlockTmMove DoubleValue.ZERO
player.tmList().syncTMFromMove(move)
DoubleValue(if (player.tmList().learnedTMs.contains(tm.id)) 1.0 else 0.0)
}
functions["lock_tm_move"] = lockTmMove@{ params ->
val move = Moves.getByName(params.getString(0)) ?: return@lockTmMove DoubleValue.ZERO
val tm = TechnicalMachines.moveToTM[move] ?: return@lockTmMove DoubleValue.ZERO
player.tmList().syncTMLockFromMove(move)
DoubleValue(if (player.tmList().learnedTMs.contains(tm.id)) 0.0 else 1.0)
}
functions["start_battle"] = startBattle@{ params ->
val opponentValue = params.get<MoValue>(0)
val opponent =
if (opponentValue is ObjectValue<*>) {
opponentValue.obj as ServerPlayer
} else {
val paramString = opponentValue.asString()
val playerUUID = paramString.asUUID
if (playerUUID != null) {
server()?.playerList?.getPlayer(playerUUID) ?: return@startBattle DoubleValue.ZERO
} else {
server()?.playerList?.getPlayerByName(paramString)
?: return@startBattle DoubleValue.ZERO
}
}
val format =
params
.getStringOrNull(1)
?.let(BattleFormat::fromFormatIdentifier)
?: BattleFormat.GEN_9_SINGLES
val setLevel = params.getIntOrNull(2) ?: -1
format.adjustLevel = setLevel
val setLevel = params.getIntOrNull(2) ?: -1
format.adjustLevel = setLevel
val rules = params.getStringOrNull(5)
?.split(",")
?.toSet()
?: emptySet()
val rules =
params
.getStringOrNull(5)
?.split(",")
?.toSet()
?: emptySet()
val modifiedBattleFormat = BattleFormat.setBattleRules(
battleFormat = format,
rules = rules
)
val modifiedBattleFormat =
BattleFormat.setBattleRules(
battleFormat = format,
rules = rules,
)
val cloneParties = (setLevel != -1) || (params.getBooleanOrNull(3) ?: false)
val healFirst = params.getBooleanOrNull(4) ?: false
val cloneParties = (setLevel != -1) || (params.getBooleanOrNull(3) ?: false)
val healFirst = params.getBooleanOrNull(4) ?: false
val battleStartResult = BattleBuilder.pvp1v1(
player1 = player,
player2 = opponent,
battleFormat = modifiedBattleFormat,
cloneParties = cloneParties,
healFirst = healFirst
)
var returnValue: MoValue = DoubleValue.ZERO
battleStartResult.ifSuccessful { returnValue = it.struct }
return@put returnValue
val battleStartResult =
BattleBuilder.pvp1v1(
player1 = player,
player2 = opponent,
battleFormat = modifiedBattleFormat,
cloneParties = cloneParties,
healFirst = healFirst,
)
var returnValue: MoValue = DoubleValue.ZERO
battleStartResult.ifSuccessful { returnValue = it.struct }
returnValue
}
functions["get_custom_stat"] = getCustomStat@{ params ->
val statName = params.getString(0)
val resourceLocation = ResourceLocation.tryParse(statName) ?: return@getCustomStat DoubleValue.ZERO
val statResourceLocation =
BuiltInRegistries.CUSTOM_STAT.get(resourceLocation) ?: return@getCustomStat DoubleValue.ZERO
val exists = Stats.CUSTOM.contains(statResourceLocation)
if (!exists) return@getCustomStat DoubleValue.ZERO
val stat = Stats.CUSTOM.get(statResourceLocation)
val value = player.stats.getValue(stat)
DoubleValue(value)
}
functions["get_starter_uuid"] = {
Cobblemon.playerDataManager.getGenericData(player).starterUUID?.let {
StringValue(
it.toString(),
)
} ?: DoubleValue.ZERO
}
functions["has_chosen_starter"] = {
DoubleValue(Cobblemon.playerDataManager.getGenericData(player).starterSelected)
}
}
map["get_custom_stat"] = put@{ params ->
val statName = params.getString(0)
val resourceLocation = ResourceLocation.tryParse(statName) ?: return@put DoubleValue.ZERO
val statResourceLocation =
BuiltInRegistries.CUSTOM_STAT.get(resourceLocation) ?: return@put DoubleValue.ZERO
val exists = net.minecraft.stats.Stats.CUSTOM.contains(statResourceLocation)
if (!exists) return@put DoubleValue.ZERO
val stat = net.minecraft.stats.Stats.CUSTOM.get(statResourceLocation)
val value = player.stats.getValue(stat)
DoubleValue(value)
}
map["get_starter_uuid"] = { _ ->
Cobblemon.playerDataManager.getGenericData(player).starterUUID?.let {
StringValue(
it.toString()
)
} ?: DoubleValue.ZERO
}
map["has_chosen_starter"] = { _ -> DoubleValue(Cobblemon.playerDataManager.getGenericData(player).starterSelected) }
}
return map
return functions
}
}
@@ -27,57 +27,69 @@ import com.cobblemon.mod.common.util.getStringOrNull
object PokedexMoLangFunctions : AbstractMoLangFunctionHolder<AbstractPokedexManager>() {
override fun AbstractPokedexManager.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val pokedex = this
val map = mutableMapOf<String, (MoParams) -> Any>()
map["get_species_record"] = { params ->
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["get_species_record"] = { params ->
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
pokedex.speciesRecords[speciesId]?.struct ?: QueryStruct(hashMapOf())
}
map["has_seen"] = put@{ params ->
functions["has_seen"] = hasSeen@{ params ->
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
val formName = params.getStringOrNull(1)
val formName =
params.getStringOrNull(1)
?: return@hasSeen DoubleValue(
pokedex.getHighestKnowledgeForSpecies(speciesId).ordinal >= PokedexEntryProgress.SEEN.ordinal,
)
if (formName == null) {
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId).ordinal >= PokedexEntryProgress.SEEN.ordinal)
} else {
return@put DoubleValue(
(pokedex.getSpeciesRecord(speciesId)?.getFormRecord(formName)?.knowledge?.ordinal
?: 0) >= PokedexEntryProgress.SEEN.ordinal
)
}
DoubleValue(
(
pokedex
.getSpeciesRecord(speciesId)
?.getFormRecord(formName)
?.knowledge
?.ordinal
?: 0
) >= PokedexEntryProgress.SEEN.ordinal,
)
}
map["has_caught"] = put@{ params ->
functions["has_caught"] = hasCaught@{ params ->
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
val formName = params.getStringOrNull(1)
if (formName == null) {
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId) == PokedexEntryProgress.OWNED)
} else {
return@put DoubleValue(
pokedex.getSpeciesRecord(speciesId)
?.getFormRecord(formName)?.knowledge == PokedexEntryProgress.OWNED
val formName =
params.getStringOrNull(1) ?: return@hasCaught DoubleValue(
pokedex.getHighestKnowledgeForSpecies(
speciesId,
) == PokedexEntryProgress.OWNED,
)
}
DoubleValue(
pokedex
.getSpeciesRecord(speciesId)
?.getFormRecord(formName)
?.knowledge == PokedexEntryProgress.OWNED,
)
}
map["caught_count"] = { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtCount)) }
map["seen_count"] = { DoubleValue(pokedex.getGlobalCalculatedValue(SeenCount)) }
map["caught_percent"] = { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtPercent)) }
map["seen_percent"] = { DoubleValue(pokedex.getGlobalCalculatedValue(SeenPercent)) }
functions["caught_count"] = { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtCount)) }
functions["seen_count"] = { DoubleValue(pokedex.getGlobalCalculatedValue(SeenCount)) }
functions["caught_percent"] = { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtPercent)) }
functions["seen_percent"] = { DoubleValue(pokedex.getGlobalCalculatedValue(SeenPercent)) }
if (pokedex is PokedexManager) {
map["player_id"] = { StringValue(pokedex.uuid.toString()) }
map["see"] = put@{ params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
pokedex.encounter(pokemon)
return@put DoubleValue.ONE
}
map["catch"] = put@{ params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
pokedex.obtain(pokemon)
return@put DoubleValue.ONE
when (pokedex) {
is PokedexManager -> {
functions["player_id"] = { StringValue(pokedex.uuid.toString()) }
functions["see"] = { params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
pokedex.encounter(pokemon)
DoubleValue.ONE
}
functions["catch"] = { params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
pokedex.obtain(pokemon)
DoubleValue.ONE
}
}
}
return map
return functions
}
}
@@ -32,100 +32,113 @@ import com.cobblemon.mod.common.util.withQueryValue
object PokemonEntityMoLangFunctions : AbstractMoLangFunctionHolder<PokemonEntity>() {
override fun PokemonEntity.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val pokemonEntity = this
val map = mutableMapOf<String, (MoParams) -> Any>()
map["is_busy"] = { DoubleValue(pokemonEntity.isBusy) }
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["get_riding_state"] = { params ->
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["is_busy"] = { DoubleValue(pokemonEntity.isBusy) }
functions["in_battle"] = { DoubleValue(pokemonEntity.isBattling) }
functions["is_moving"] =
{ DoubleValue((pokemonEntity.moveControl as? PokemonMoveControl)?.hasWanted() == true) }
functions["is_flying"] = { DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) }
functions["get_riding_state"] = { params ->
val name = params.getStringOrNull(0)
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions[name]?.apply(MoParams.EMPTY) as? MoValue ?: moValue
}
}
map["is_gliding"] = {
functions["is_gliding"] = {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions["gliding"]?.apply(MoParams.EMPTY) as? MoValue
?: DoubleValue.ZERO
}
}
map["is_sprinting"] = {
functions["is_sprinting"] = {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions["sprinting"]?.apply(MoParams.EMPTY) as? MoValue
?: DoubleValue.ZERO
}
}
map["is_drifting"] = {
functions["is_drifting"] = {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions["drifting"]?.apply(MoParams.EMPTY) as? MoValue
?: DoubleValue.ZERO
}
}
map["is_powered_drifting"] = {
functions["is_powered_drifting"] = {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions["powered_drifting"]?.apply(MoParams.EMPTY) as? MoValue
?: DoubleValue.ZERO
}
}
map["in_air"] = {
functions["in_air"] = {
pokemonEntity.ifRidingAvailableSupply(DoubleValue.ZERO) { behaviour, settings, state ->
val moValue = behaviour.asMoLangValue(settings, state, pokemonEntity)
return@ifRidingAvailableSupply moValue.functions["in_air"]?.apply(MoParams.EMPTY) as? MoValue
?: DoubleValue.ZERO
}
}
map["is_wild"] = { DoubleValue(pokemonEntity.ownerUUID == null) }
map["is_in_party"] = { DoubleValue(pokemonEntity.pokemon.storeCoordinates.get()?.store is PartyStore) }
map["is_ridden"] = { DoubleValue(pokemonEntity.hasControllingPassenger()) }
map["has_aspect"] = { DoubleValue(it.getString(0) in pokemonEntity.aspects) }
map["is_pokemon"] = { DoubleValue.ONE }
map["is_holding_item"] = {
DoubleValue(!pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).let {
it.isEmpty || it.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS) || it.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)
})
functions["is_wild"] = { DoubleValue(pokemonEntity.ownerUUID == null) }
functions["is_in_party"] = {
DoubleValue(
pokemonEntity.pokemon.storeCoordinates
.get()
?.store is PartyStore,
)
}
map["riding_style"] = {
StringValue(pokemonEntity.ifRidingAvailableSupply("") { behaviour, settings, state ->
behaviour.getRidingStyle(settings, state).name
})
functions["is_ridden"] = { DoubleValue(pokemonEntity.hasControllingPassenger()) }
functions["has_aspect"] = { DoubleValue(it.getString(0) in pokemonEntity.aspects) }
functions["is_pokemon"] = { DoubleValue.ONE }
functions["is_holding_item"] = {
DoubleValue(
!pokemonEntity.entityData.get(PokemonEntity.SHOWN_HELD_ITEM).let {
it.isEmpty || it.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS) || it.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)
},
)
}
map["is_wearing_hat"] = {
functions["riding_style"] = {
StringValue(
pokemonEntity.ifRidingAvailableSupply("") { behaviour, settings, state ->
behaviour.getRidingStyle(settings, state).name
},
)
}
functions["is_wearing_hat"] = {
DoubleValue(
pokemonEntity.entityData
.get(PokemonEntity.SHOWN_HELD_ITEM)
.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS)
.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS),
)
}
map["is_wearing_face"] = {
functions["is_wearing_face"] = {
DoubleValue(
pokemonEntity.entityData
.get(PokemonEntity.SHOWN_HELD_ITEM)
.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)
.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS),
)
}
map["is_pastured"] = {
functions["is_pastured"] = {
DoubleValue((pokemonEntity.tethering != null))
}
map["pasture_conflict_enabled"] = {
functions["pasture_conflict_enabled"] = {
DoubleValue(pokemonEntity.getBehaviourFlag(PokemonBehaviourFlag.PASTURE_CONFLICT))
}
map["run_action_effect"] = runActionEffect@{ params ->
functions["run_action_effect"] = runActionEffect@{ params ->
val runtime = MoLangRuntime().setup()
runtime.environment.cloneFrom(params.environment)
runtime.withQueryValue("entity", pokemonEntity.struct)
val actionEffect = ActionEffects.actionEffects[params.getString(0).asIdentifierDefaultingNamespace()]
if (actionEffect != null) {
val context = ActionEffectContext(
actionEffect = actionEffect,
providers = mutableListOf(TargetsProvider(pokemonEntity)),
runtime = runtime,
level = pokemonEntity.level()
)
val context =
ActionEffectContext(
actionEffect = actionEffect,
providers = mutableListOf(TargetsProvider(pokemonEntity)),
runtime = runtime,
level = pokemonEntity.level(),
)
// This was taken from NPC run_action_effect but this variable isn't used, so I just commented it out.
// pokemonEntity.actionEffect = context
pokemonEntity.brain.setMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT, context)
@@ -135,14 +148,16 @@ object PokemonEntityMoLangFunctions : AbstractMoLangFunctionHolder<PokemonEntity
pokemonEntity.brain.getMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT).orElse(null)
if (pokemonActionEffect == context && pokemonEntity.brain.isActive(CobblemonActivities.ACTION_EFFECT)) {
pokemonEntity.brain.eraseMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT)
//pokemonEntity.actionEffect = null
// pokemonEntity.actionEffect = null
}
}
return@runActionEffect DoubleValue.ONE
}
return@runActionEffect DoubleValue.ZERO
DoubleValue.ZERO
}
return map
return functions
}
}
@@ -33,218 +33,214 @@ import com.cobblemon.mod.common.util.getDoubleOrNull
import com.cobblemon.mod.common.util.getIntOrNull
import com.cobblemon.mod.common.util.server
import com.cobblemon.mod.common.util.toProperties
import kotlin.random.Random
import net.minecraft.resources.ResourceLocation
import kotlin.random.Random
object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
override fun Pokemon.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val pokemon = this
val map = mutableMapOf<String, (MoParams) -> Any>()
map["id"] = { StringValue(pokemon.uuid.toString()) }
map["nickname"] = { StringValue(pokemon.nickname.toString()) }
map["level"] = { DoubleValue(pokemon.level.toDouble()) }
map["max_hp"] = { DoubleValue(pokemon.maxHealth.toDouble()) }
map["current_hp"] = { DoubleValue(pokemon.currentHealth.toDouble()) }
map["friendship"] = { DoubleValue(pokemon.friendship.toDouble()) }
map["max_fullness"] = { DoubleValue(pokemon.getMaxFullness().toDouble()) }
map["fullness"] = { DoubleValue(pokemon.currentFullness.toDouble()) }
map["lose_fullness"] = { params ->
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["id"] = { StringValue(pokemon.uuid.toString()) }
functions["nickname"] = { StringValue(pokemon.nickname.toString()) }
functions["level"] = { DoubleValue(pokemon.level.toDouble()) }
functions["max_hp"] = { DoubleValue(pokemon.maxHealth.toDouble()) }
functions["current_hp"] = { DoubleValue(pokemon.currentHealth.toDouble()) }
functions["friendship"] = { DoubleValue(pokemon.friendship.toDouble()) }
functions["max_fullness"] = { DoubleValue(pokemon.getMaxFullness().toDouble()) }
functions["fullness"] = { DoubleValue(pokemon.currentFullness.toDouble()) }
functions["lose_fullness"] = { params ->
val amount = params.getDouble(0)
pokemon.loseFullness(amount.toInt())
}
map["feed_pokemon"] = { params ->
functions["feed_pokemon"] = { params ->
val amount = params.getDouble(0)
val playSound = params.getBooleanOrNull(1) ?: true
pokemon.feedPokemon(amount.toInt(), playSound)
}
map["behaviour"] = { pokemon.form.behaviour.struct }
map["behavior"] = { pokemon.form.behaviour.struct } // Inferior
map["pokeball"] = { StringValue(pokemon.caughtBall.toString()) }
map["ability"] = { StringValue(pokemon.ability.name) }
map["has_learned"] = put@{ params ->
functions["behaviour"] = { pokemon.form.behaviour.struct }
functions["behavior"] = { pokemon.form.behaviour.struct } // Inferior
functions["pokeball"] = { StringValue(pokemon.caughtBall.toString()) }
functions["ability"] = { StringValue(pokemon.ability.name) }
functions["has_learned"] = hasLearned@{ params ->
val moveName = params.getString(0)
val move = pokemon.allAccessibleMoves.find { it.name == moveName }
if (move != null) {
return@put DoubleValue.ONE
} else {
return@put DoubleValue.ZERO
}
if (move != null) return@hasLearned DoubleValue.ONE
DoubleValue.ZERO
}
map["moveset"] = {
functions["moveset"] = {
val struct = QueryStruct(hashMapOf())
for ((index, move) in pokemon.moveSet.withIndex()) {
struct.addFunction(index.toString()) { move.struct }
}
struct
}
map["evs"] = {
functions["evs"] = {
val struct = QueryStruct(hashMapOf())
for (stat in Stats.PERMANENT) {
struct.addFunction(stat.showdownId) { DoubleValue(pokemon.evs.getOrDefault(stat).toDouble()) }
}
struct
}
map["ivs"] = {
functions["ivs"] = {
val struct = QueryStruct(hashMapOf())
for (stat in Stats.PERMANENT) {
struct.addFunction(stat.showdownId) { DoubleValue(pokemon.ivs.getOrDefault(stat).toDouble()) }
}
struct
}
map["hyper_trained_ivs"] = {
functions["hyper_trained_ivs"] = {
val struct = QueryStruct(hashMapOf())
for (stat in Stats.PERMANENT) {
struct.addFunction(stat.showdownId) { DoubleValue(pokemon.ivs.hyperTrainedIVs[stat] ?: -1.0) }
}
struct
}
map["ride_boosts"] = {
functions["ride_boosts"] = {
val struct = QueryStruct(hashMapOf())
for (stat in RidingStat.entries) {
struct.addFunction(stat.name.lowercase()) { DoubleValue(pokemon.getRideBoost(stat)) }
}
struct
}
map["natdex_number"] = {
functions["natdex_number"] = {
DoubleValue(pokemon.species.nationalPokedexNumber.toDouble())
}
map["types"] = {
pokemon.form.types.map { it.showdownId }.asArrayValue(::StringValue)
functions["types"] = {
pokemon.form.types
.map { it.showdownId }
.asArrayValue(::StringValue)
}
map["gender_ratio"] = {
functions["gender_ratio"] = {
DoubleValue(pokemon.form.maleRatio.toDouble())
}
map["ev_yield"] = {
functions["ev_yield"] = {
val struct = QueryStruct(hashMapOf())
for (stat in Stats.PERMANENT) {
struct.addFunction(stat.showdownId) { DoubleValue(pokemon.form.evYield[stat]?.toDouble()) }
}
struct
}
map["base_stats"] = {
functions["base_stats"] = {
val struct = QueryStruct(hashMapOf())
for (stat in Stats.PERMANENT) {
struct.addFunction(stat.showdownId) { DoubleValue(pokemon.form.baseStats[stat]?.toDouble()) }
}
struct
}
map["catch_rate"] = {
functions["catch_rate"] = {
DoubleValue(pokemon.form.catchRate.toDouble())
}
map["base_experience_yield"] = {
functions["base_experience_yield"] = {
DoubleValue(pokemon.form.baseExperienceYield.toDouble())
}
map["drops"] = {
functions["drops"] = {
val struct = QueryStruct(hashMapOf())
for ((index, drop) in pokemon.form.drops.entries.withIndex()) {
for ((index, drop) in pokemon.form.drops.entries
.withIndex()) {
struct.addFunction(index.toString()) { drop }
}
struct
}
map["tm_learnset"] = {
functions["tm_learnset"] = {
val struct = QueryStruct(hashMapOf())
for ((index, move) in pokemon.form.moves.tmMoves.withIndex()) {
for ((index, move) in pokemon.form.moves.tmMoves
.withIndex()) {
struct.addFunction(index.toString()) { move.struct }
}
struct
}
map["egg_learnset"] = {
functions["egg_learnset"] = {
val struct = QueryStruct(hashMapOf())
for ((index, move) in pokemon.form.moves.eggMoves.withIndex()) {
for ((index, move) in pokemon.form.moves.eggMoves
.withIndex()) {
struct.addFunction(index.toString()) { move.struct }
}
struct
}
map["tutor_learnset"] = {
functions["tutor_learnset"] = {
val struct = QueryStruct(hashMapOf())
for ((index, move) in pokemon.form.moves.tutorMoves.withIndex()) {
for ((index, move) in pokemon.form.moves.tutorMoves
.withIndex()) {
struct.addFunction(index.toString()) { move.struct }
}
struct
}
map["level_learnset"] = {
functions["level_learnset"] = {
val struct = QueryStruct(hashMapOf())
for ((index, move) in pokemon.form.moves.levelUpMoves) {
struct.addFunction(index.toString()) { move }
}
struct
}
map["ability_pool"] = {
functions["ability_pool"] = {
val struct = QueryStruct(hashMapOf())
for ((index, ability) in pokemon.form.abilities.withIndex()) {
struct.addFunction(index.toString()) { StringValue(ability.toString()) }
}
struct
}
map["egg_groups"] = {
functions["egg_groups"] = {
val struct = QueryStruct(hashMapOf())
for ((index, group) in pokemon.form.eggGroups.withIndex()) {
struct.addFunction(index.toString()) { StringValue(group.toString()) }
}
struct
}
map["egg_cycles"] = {
functions["egg_cycles"] = {
DoubleValue(pokemon.species.eggCycles.toDouble())
}
map["labels"] = {
functions["labels"] = {
val struct = QueryStruct(hashMapOf())
for ((index, label) in pokemon.form.labels.withIndex()) {
struct.addFunction(index.toString()) { StringValue(label) }
}
struct
}
map["aspects"] = {
functions["aspects"] = {
val aspects = pokemon.aspects
aspects.asArrayValue { StringValue(it) }
}
map["form_aspects"] = {
functions["form_aspects"] = {
val aspects = pokemon.form.aspects
aspects.asArrayValue { StringValue(it) }
}
map["form_name"] = {
functions["form_name"] = {
StringValue(pokemon.form.name)
}
// Yes, this is the lazy call for a single hardcoded pre-evolution.
// Lol. Lmao, even.
// TO-DO: Subscribe to [PokemonSpecies.observable].
// Gito: surely this is just a typo, right? not touching the function name just in case
map["prevolution"] = preEvolution@{
val preEvolution = pokemon.species.preEvolution ?: return@preEvolution DoubleValue.ZERO
return@preEvolution preEvolution
}
map["nature"] = { StringValue(pokemon.nature.toString()) }
map["is_wild"] = { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
map["is_shiny"] = { DoubleValue(pokemon.shiny) }
map["is_in_party"] = { DoubleValue(pokemon.storeCoordinates.get()?.store is PartyStore) }
map["species"] = { pokemon.species.struct }
map["form"] = { StringValue(pokemon.form.name) }
map["weight"] = { DoubleValue(pokemon.species.weight.toDouble()) }
map["matches"] = { params -> DoubleValue(params.getString(0).toProperties().matches(pokemon)) }
map["apply"] = { params ->
functions["pre_evolution"] = { pokemon.species.preEvolution ?: DoubleValue.ZERO }
functions["nature"] = { StringValue(pokemon.nature.toString()) }
functions["is_wild"] = { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
functions["is_shiny"] = { DoubleValue(pokemon.shiny) }
functions["is_in_party"] = { DoubleValue(pokemon.storeCoordinates.get()?.store is PartyStore) }
functions["species"] = { pokemon.species.struct }
functions["form"] = { StringValue(pokemon.form.name) }
functions["weight"] = { DoubleValue(pokemon.species.weight.toDouble()) }
functions["matches"] = { params -> DoubleValue(params.getString(0).toProperties().matches(pokemon)) }
functions["apply"] = { params ->
params.getString(0).toProperties().apply(pokemon)
DoubleValue.ONE
}
map["owner"] = { pokemon.getOwnerPlayer()?.asMoLangValue() ?: DoubleValue.ZERO }
map["held_item"] = { pokemon.heldItem().asMoLangValue(server()!!.registryAccess()) }
map["remove_held_item"] = { _ ->
pokemon.removeHeldItem()
}
map["add_aspects"] = { params ->
functions["owner"] = { pokemon.getOwnerPlayer()?.asMoLangValue() ?: DoubleValue.ZERO }
functions["held_item"] = { pokemon.heldItem().asMoLangValue(server()!!.registryAccess()) }
functions["remove_held_item"] = { pokemon.removeHeldItem() }
functions["add_aspects"] = { params ->
for (aspect in params.params) pokemon.forcedAspects += aspect.asString()
pokemon.updateAspects()
}
map["remove_aspects"] = { params ->
functions["remove_aspects"] = { params ->
for (aspect in params.params) pokemon.forcedAspects -= aspect.asString()
pokemon.updateAspects()
}
map["cosmetic_item"] = {
functions["cosmetic_item"] = {
pokemon.cosmeticItem().asMoLangValue(server()!!.registryAccess())
}
map["remove_cosmetic_item"] = { _ ->
pokemon.removeCosmeticItem()
}
map["marks"] = { _ -> pokemon.marks.asArrayValue { StringValue(it.identifier.toString()) } }
map["has_mark"] = { params ->
functions["remove_cosmetic_item"] = { pokemon.removeCosmeticItem() }
functions["marks"] = { pokemon.marks.asArrayValue { StringValue(it.identifier.toString()) } }
functions["has_mark"] = { params ->
var hasMark = false
val identifier = params.getString(0).asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
@@ -254,7 +250,7 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
DoubleValue(hasMark)
}
map["remove_marks"] = { params ->
functions["remove_marks"] = { params ->
var removedMark = false
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
@@ -267,7 +263,7 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
DoubleValue(removedMark)
}
map["add_marks"] = { params ->
functions["add_marks"] = { params ->
var appliedMark = false
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
@@ -280,7 +276,7 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
DoubleValue(appliedMark)
}
map["add_marks_with_chance"] = { params ->
functions["add_marks_with_chance"] = { params ->
var appliedMark = false
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
@@ -298,17 +294,15 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
DoubleValue(appliedMark)
}
map["add_potential_marks"] = { params ->
functions["add_potential_marks"] = { params ->
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
if (mark != null) pokemon.addPotentialMark(mark)
}
}
map["apply_potential_marks"] = put@{
return@put DoubleValue(pokemon.applyPotentialMarks())
}
map["hyper_train_iv"] = hyperTrainIv@{ params ->
functions["apply_potential_marks"] = { DoubleValue(pokemon.applyPotentialMarks()) }
functions["hyper_train_iv"] = hyperTrainIv@{ params ->
val statId = params.getString(0)
val stat = Stats.getStat(statId)
val value = params.getIntOrNull(1) ?: IVs.MAX_VALUE
@@ -321,12 +315,12 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
return@hyperTrainIv DoubleValue.ZERO
}
}
map["add_exp"] = { params ->
functions["add_exp"] = { params ->
val exp = params.getDouble(0).toInt()
pokemon.addExperience(SidemodExperienceSource("molang"), exp)
DoubleValue.ONE
}
map["set_iv"] = setIv@{ params ->
functions["set_iv"] = setIv@{ params ->
val statId = params.getString(0)
val stat = Stats.getStat(statId)
val value = params.getIntOrNull(1)?.coerceIn(0, IVs.MAX_VALUE) ?: IVs.MAX_VALUE
@@ -338,7 +332,7 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
return@setIv DoubleValue.ZERO
}
}
map["set_ev"] = setEv@{ params ->
functions["set_ev"] = setEv@{ params ->
val statId = params.getString(0)
val stat = Stats.getStat(statId)
val value = (params.getIntOrNull(1) ?: 0).coerceIn(0, 255)
@@ -350,49 +344,54 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
return@setEv DoubleValue.ZERO
}
}
map["set_ride_boost"] = setRideBoost@{ params ->
functions["set_ride_boost"] = setRideBoost@{ params ->
val statName = params.getString(0).uppercase()
val stat = RidingStat.entries.find { it.name.equals(statName, ignoreCase = true) }
?: return@setRideBoost DoubleValue.ZERO
val stat =
RidingStat.entries.find { it.name.equals(statName, ignoreCase = true) }
?: return@setRideBoost DoubleValue.ZERO
val value = params.getDoubleOrNull(1)?.toFloat() ?: return@setRideBoost DoubleValue.ZERO
pokemon.setRideBoost(stat, value)
return@setRideBoost DoubleValue.ONE
DoubleValue.ONE
}
map["add_ride_boost"] = addRideBoost@{ params ->
functions["add_ride_boost"] = addRideBoost@{ params ->
val statName = params.getString(0).uppercase()
val stat = RidingStat.entries.find { it.name.equals(statName, ignoreCase = true) }
?: return@addRideBoost DoubleValue.ZERO
val stat =
RidingStat.entries.find { it.name.equals(statName, ignoreCase = true) }
?: return@addRideBoost DoubleValue.ZERO
val value = params.getDoubleOrNull(1)?.toFloat() ?: return@addRideBoost DoubleValue.ZERO
return@addRideBoost DoubleValue(if (pokemon.addRideBoost(stat, value)) 1.0 else 0.0)
DoubleValue(if (pokemon.addRideBoost(stat, value)) 1.0 else 0.0)
}
map["initialize_moveset"] = put@{ params ->
functions["initialize_moveset"] = initializeMoveset@{ params ->
val param = params.get<MoValue>(0) ?: StringValue(pokemon.form.defaultWildMovesetBuilder.toString())
if (param is DoubleValue) {
pokemon.initializeMoveset(param == DoubleValue.ONE)
} else {
val movesetBuilderId = ResourceLocation.parse(param.asString())
val movesetBuilder = CobblemonMovesetBuilders.movesetBuilders[movesetBuilderId]
?: run {
Cobblemon.LOGGER.error("Tried initializing moveset from moveset builder ${param.asString()} but it does not exist.")
return@put DoubleValue.ZERO
}
val movesetBuilder =
CobblemonMovesetBuilders.movesetBuilders[movesetBuilderId]
?: run {
Cobblemon.LOGGER.error(
"Tried initializing moveset from moveset builder ${param.asString()} but it does not exist.",
)
return@initializeMoveset DoubleValue.ZERO
}
pokemon.initializeMovesetFrom(movesetBuilder)
}
DoubleValue.ONE
}
map["validate_moveset"] = { params ->
functions["validate_moveset"] = { params ->
val includeLegacy = params.getBooleanOrNull(0) ?: true
pokemon.validateMoveset(includeLegacy)
DoubleValue.ONE
}
map["teach_learnable_moves"] = { params ->
functions["teach_learnable_moves"] = { params ->
val includeLegacy = params.getBooleanOrNull(0) ?: true
pokemon.teachLearnableMoves(includeLegacy)
DoubleValue.ONE
}
map["teach_move"] = teachMove@{ params ->
functions["teach_move"] = teachMove@{ params ->
val moveName = params.getString(0)
val moveTemplate = Moves.getByName(moveName) ?: return@teachMove DoubleValue.ZERO
val bypass = params.getBooleanOrNull(1) ?: false
@@ -402,8 +401,9 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
return@teachMove DoubleValue.ZERO
}
val alreadyKnows = pokemon.moveSet.getMoves().any { it.template == moveTemplate } ||
pokemon.benchedMoves.any { it.moveTemplate == moveTemplate }
val alreadyKnows =
pokemon.moveSet.getMoves().any { it.template == moveTemplate } ||
pokemon.benchedMoves.any { it.moveTemplate == moveTemplate }
if (alreadyKnows) {
return@teachMove DoubleValue.ZERO
}
@@ -416,42 +416,43 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
DoubleValue.ONE
}
map["can_learn_move"] = canLearnMove@{ params ->
functions["can_learn_move"] = canLearnMove@{ params ->
val moveName = params.getString(0)
val moveTemplate = Moves.getByName(moveName) ?: return@canLearnMove DoubleValue.ZERO
val includeLegacy = params.getBooleanOrNull(1) ?: true
val canLearn = if (includeLegacy) {
LearnsetQuery.ANY.canLearn(moveTemplate, pokemon.form.moves)
} else {
LearnsetQuery.LEGAL.canLearn(moveTemplate, pokemon.form.moves)
}
return@canLearnMove DoubleValue(if (canLearn) 1.0 else 0.0)
val canLearn =
if (includeLegacy) {
LearnsetQuery.ANY.canLearn(moveTemplate, pokemon.form.moves)
} else {
LearnsetQuery.LEGAL.canLearn(moveTemplate, pokemon.form.moves)
}
DoubleValue(if (canLearn) 1.0 else 0.0)
}
map["unlearn_move"] = unlearnMove@{ params ->
functions["unlearn_move"] = unlearnMove@{ params ->
val moveName = params.getString(0)
val moveTemplate = Moves.getByName(moveName)
if (moveTemplate != null) {
pokemon.unlearnMove(moveTemplate)
return@unlearnMove DoubleValue.ONE
} else {
return@unlearnMove DoubleValue.ZERO
}
DoubleValue.ZERO
}
map["can_evolve"] = { _ ->
DoubleValue(pokemon.evolutions.any())
}
map["force_evolve"] = forceEvolve@{ params ->
functions["can_evolve"] = { DoubleValue(pokemon.evolutions.any()) }
functions["force_evolve"] = forceEvolve@{ params ->
val idx = params.getInt(0)
val evolution = if (idx >= 0) pokemon.evolutions.elementAtOrNull(idx) else return@forceEvolve DoubleValue.ZERO
val evolution =
if (idx >= 0) pokemon.evolutions.elementAtOrNull(idx) else return@forceEvolve DoubleValue.ZERO
evolution?.forceEvolve(pokemon)
StringValue(evolution.toString())
}
map["entity"] = { pokemon.entity?.asMoLangValue() ?: DoubleValue.ZERO }
map["is_alpha"] = { DoubleValue(pokemon.isAlpha) }
map["size_category"] = { _ -> StringValue(pokemon.getSizeCategory().name) }
functions["entity"] = { pokemon.entity?.asMoLangValue() ?: DoubleValue.ZERO }
functions["is_alpha"] = { DoubleValue(pokemon.isAlpha) }
functions["size_category"] = { StringValue(pokemon.getSizeCategory().name) }
return map
return functions
}
}
@@ -20,52 +20,50 @@ import com.cobblemon.mod.common.util.getStringOrNull
object PokemonPropertiesMoLangFunctions : AbstractMoLangFunctionHolder<PokemonProperties>() {
override fun PokemonProperties.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val props = this
val map = mutableMapOf<String, (MoParams) -> Any>()
val functions = hashMapOf<String, (MoParams) -> Any>()
map["level"] = { DoubleValue(props.level?.toDouble() ?: 0) }
map["set_level"] = { params ->
functions["level"] = { DoubleValue(props.level?.toDouble() ?: 0) }
functions["set_level"] = { params ->
props.level = params.getIntOrNull(0)
DoubleValue.ONE
}
map["shiny"] = { DoubleValue(props.shiny) }
map["set_shiny"] = { params ->
functions["shiny"] = { DoubleValue(props.shiny) }
functions["set_shiny"] = { params ->
props.shiny = params.getBooleanOrNull(0)
DoubleValue.ONE
}
map["species"] = { props.species?.let { StringValue(it) } ?: DoubleValue.ZERO }
map["set_species"] = { params ->
functions["species"] = { props.species?.let { StringValue(it) } ?: DoubleValue.ZERO }
functions["set_species"] = { params ->
props.species = params.getStringOrNull(0)
DoubleValue.ONE
}
map["gender"] = { props.gender?.let { StringValue(it.name) } ?: DoubleValue.ZERO }
map["set_gender"] = { params ->
functions["gender"] = { props.gender?.let { StringValue(it.name) } ?: DoubleValue.ZERO }
functions["set_gender"] = { params ->
props.gender = params.getStringOrNull(0)?.let { Gender.valueOf(it) }
DoubleValue.ONE
}
map["form"] = { props.form?.let { StringValue(it) } ?: DoubleValue.ZERO }
map["ivs"] = ivs@{
functions["form"] = { props.form?.let { StringValue(it) } ?: DoubleValue.ZERO }
functions["ivs"] = ivs@{
val ivs = props.ivs ?: return@ivs DoubleValue.ZERO
return@ivs ivs.struct
ivs.struct
}
map["evs"] = evs@{
functions["evs"] = evs@{
val evs = props.evs ?: return@evs DoubleValue.ZERO
return@evs evs.struct
evs.struct
}
map["friendship"] = { DoubleValue(props.friendship?.toDouble() ?: DoubleValue.ZERO) }
map["set_friendship"] = { params ->
functions["friendship"] = { DoubleValue(props.friendship?.toDouble() ?: DoubleValue.ZERO) }
functions["set_friendship"] = { params ->
props.friendship = params.getIntOrNull(0)
DoubleValue.ONE
}
map["create"] = {
val pokemon = props.create()
pokemon.struct
}
map["to_string"] = { params ->
functions["create"] = { (props.create()).struct }
functions["to_string"] = { params ->
val separator = params.getStringOrNull(0) ?: " "
StringValue(props.asString(separator = separator))
}
return map
return functions
}
}
@@ -22,83 +22,84 @@ import com.cobblemon.mod.common.util.asUUID
import com.cobblemon.mod.common.util.getPlayer
import com.cobblemon.mod.common.util.toProperties
object PokemonStoreMoLangFunctions: AbstractMoLangFunctionHolder<PokemonStore<*>>() {
object PokemonStoreMoLangFunctions : AbstractMoLangFunctionHolder<PokemonStore<*>>() {
override fun PokemonStore<*>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val store = this
val map = mutableMapOf<String, (MoParams) -> Any>()
map["uuid"] = { StringValue(store.uuid.toString()) }
map["add"] = { params ->
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["uuid"] = { StringValue(store.uuid.toString()) }
functions["add"] = { params ->
val pokemon = params.get<ObjectValue<Pokemon>>(0)
DoubleValue(store.add(pokemon.obj))
}
map["add_by_properties"] = { params ->
functions["add_by_properties"] = { params ->
val props = params.getString(0).toProperties()
val player = (store as? PlayerPartyStore)?.playerUUID?.getPlayer() // Only really know for sure when it's a player party store
val player =
(store as? PlayerPartyStore)?.playerUUID?.getPlayer() // Only really know for sure when it's a player party store
val pokemon = props.create(player = player)
DoubleValue(store.add(pokemon))
}
map["find_by_properties"] = { params ->
functions["find_by_properties"] = { params ->
val props = params.getString(0).toProperties()
val pokemon = store.find { props.matches(it) }
pokemon?.asStruct() ?: DoubleValue.ZERO
}
map["find_all_by_properties"] = { params ->
functions["find_all_by_properties"] = { params ->
val props = params.getString(0).toProperties()
val pokemon = store.filter { props.matches(it) }
ArrayStruct(pokemon.mapIndexed { index, value -> "$index" to value.asStruct() }.toMap())
}
map["find_by_id"] = { params ->
functions["find_by_id"] = { params ->
val id = params.getString(0).asUUID
val pokemon = store.find { it.uuid == id }
pokemon?.asStruct() ?: DoubleValue.ZERO
}
map["remove_by_id"] = removeById@{ params ->
functions["remove_by_id"] = removeById@{ params ->
val id = params.getString(0).asUUID
val pokemon = store.find { it.uuid == id } ?: return@removeById DoubleValue.ZERO
return@removeById DoubleValue(store.remove(pokemon))
DoubleValue(store.remove(pokemon))
}
map["average_level"] = averageLevel@{ _ ->
functions["average_level"] = averageLevel@{
var numberOfPokemon = 0
var totalLevel = 0
for (pokemon in store) {
totalLevel += pokemon.level
numberOfPokemon++
}
if (numberOfPokemon == 0) {
return@averageLevel DoubleValue.ZERO
}
return@averageLevel DoubleValue(totalLevel.toDouble() / numberOfPokemon)
if (numberOfPokemon == 0) return@averageLevel DoubleValue.ZERO
DoubleValue(totalLevel.toDouble() / numberOfPokemon)
}
map["count"] = { _ -> DoubleValue(store.count()) }
map["count_by_properties"] = { params ->
functions["count"] = { DoubleValue(store.count()) }
functions["count_by_properties"] = { params ->
val props = params.getString(0).toProperties()
DoubleValue(store.count { props.matches(it) })
}
map["highest_level"] = {
functions["highest_level"] = {
val highest = store.maxOfOrNull { it.level } ?: 0
DoubleValue(highest)
}
map["lowest_level"] = {
functions["lowest_level"] = {
val lowest = store.minOfOrNull { it.level } ?: 0
DoubleValue(lowest)
}
map["heal"] = {
functions["heal"] = {
for (pokemon in store) {
pokemon.heal()
}
DoubleValue.ONE
}
map["healing_remainder_percent"] = { _ ->
functions["healing_remainder_percent"] = {
var totalPercent = 0.0f
for (pokemon in store) {
totalPercent += (1.0f - (pokemon.currentHealth.toFloat() / pokemon.maxHealth))
}
DoubleValue(totalPercent)
}
map["has_usable_pokemon"] = { _ -> DoubleValue(store.any { !it.isFainted() }) }
map["pokemon"] = {
store.map { it.asStruct() }.asArrayValue()
}
return map
functions["has_usable_pokemon"] = { DoubleValue(store.any { !it.isFainted() }) }
functions["pokemon"] = { store.map { it.asStruct() }.asArrayValue() }
return functions
}
}
@@ -25,62 +25,63 @@ import java.util.*
object ServerMoLangFunctions : AbstractMoLangFunctionHolder<MinecraftServer>() {
override fun MinecraftServer.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val server = this
val map = mutableMapOf<String, (MoParams) -> Any>()
val functions = hashMapOf<String, (MoParams) -> Any>()
map["get_world"] = getWorld@{ params ->
val world = server.getLevel(
ResourceKey.create(
Registries.DIMENSION,
params.getString(0).asIdentifierDefaultingNamespace(namespace = "minecraft")
)
) ?: return@getWorld DoubleValue.ZERO
functions["get_world"] = getWorld@{ params ->
val world =
server.getLevel(
ResourceKey.create(
Registries.DIMENSION,
params.getString(0).asIdentifierDefaultingNamespace(namespace = "minecraft"),
),
) ?: return@getWorld DoubleValue.ZERO
return@getWorld world
world
.registryAccess()
.registryOrThrow(Registries.DIMENSION)
.wrapAsHolder(world)
.asWorldMoLangValue()
}
map["broadcast"] = { params ->
functions["broadcast"] = { params ->
val message = params.getString(0)
server.playerList.broadcastSystemMessage(message.text(), params.getBooleanOrNull(1) == true)
DoubleValue.ONE
}
map["get_player_by_uuid"] = getPlayerByUuid@{ params ->
functions["get_player_by_uuid"] = getPlayerByUuid@{ params ->
val uuid = UUID.fromString(params.getString(0))
val player = server.playerList.getPlayer(uuid) ?: return@getPlayerByUuid DoubleValue.ZERO
return@getPlayerByUuid player.asMoLangValue()
player.asMoLangValue()
}
map["get_player_by_username"] = getPlayerByUsername@{ params ->
functions["get_player_by_username"] = getPlayerByUsername@{ params ->
val username = params.getString(0)
val player = server.playerList.getPlayerByName(username) ?: return@getPlayerByUsername DoubleValue.ZERO
return@getPlayerByUsername player.asMoLangValue()
player.asMoLangValue()
}
map["data"] = { params ->
functions["data"] = { params ->
Cobblemon.molangData.load(
UUID(0L, 0L),
params.getStringOrNull(0)
params.getStringOrNull(0),
)
}
map["save_data"] = { params ->
functions["save_data"] = { params ->
Cobblemon.molangData.save(
UUID(0L, 0L),
params.getStringOrNull(index = 0)
params.getStringOrNull(index = 0),
)
DoubleValue.ONE
}
// Maybe later...
// map.put("stop") { params ->
// functions.put("stop") { params ->
// Cobblemon.LOGGER.warn("Server is being stopped from a MoLang script.")
// server.stopServer()
// }
return map
return functions
}
}
@@ -20,27 +20,34 @@ import net.minecraft.server.level.ServerPlayer
object SpawnablePositionMoLangFunctions : AbstractMoLangFunctionHolder<SpawnablePosition>() {
override fun SpawnablePosition.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val spawningContext = this
val map = mutableMapOf<String, (MoParams) -> Any>()
val worldValue = spawningContext.world.registryAccess().registryOrThrow(Registries.DIMENSION)
.wrapAsHolder(spawningContext.world).asWorldMoLangValue()
val biomeValue = spawningContext.biomeHolder.asBiomeMoLangValue()
map["biome"] = { _ -> biomeValue }
map["world"] = { _ -> worldValue }
map["light"] = { _ -> DoubleValue(spawningContext.light.toDouble()) }
map["x"] = { _ -> DoubleValue(spawningContext.position.x.toDouble()) }
map["y"] = { _ -> DoubleValue(spawningContext.position.y.toDouble()) }
map["z"] = { _ -> DoubleValue(spawningContext.position.z.toDouble()) }
map["moon_phase"] = { _ -> DoubleValue(spawningContext.moonPhase.toDouble()) }
map["can_see_sky"] = { _ -> DoubleValue(spawningContext.canSeeSky) }
map["sky_light"] = { _ -> DoubleValue(spawningContext.skyLight.toDouble()) }
map["player"] = put@{ _ ->
val causeEntity = spawningContext.cause.entity ?: return@put DoubleValue.ZERO
if (causeEntity is ServerPlayer) {
return@put causeEntity.asMoLangValue()
} else {
return@put DoubleValue.ZERO
}
val worldValue =
spawningContext
.world
.registryAccess()
.registryOrThrow(Registries.DIMENSION)
.wrapAsHolder(spawningContext.world)
.asWorldMoLangValue()
val biomeValue =
spawningContext
.biomeHolder
.asBiomeMoLangValue()
val functions = hashMapOf<String, (MoParams) -> Any>()
functions["biome"] = { biomeValue }
functions["world"] = { worldValue }
functions["light"] = { DoubleValue(spawningContext.light.toDouble()) }
functions["x"] = { DoubleValue(spawningContext.position.x.toDouble()) }
functions["y"] = { DoubleValue(spawningContext.position.y.toDouble()) }
functions["z"] = { DoubleValue(spawningContext.position.z.toDouble()) }
functions["moon_phase"] = { DoubleValue(spawningContext.moonPhase.toDouble()) }
functions["can_see_sky"] = { DoubleValue(spawningContext.canSeeSky) }
functions["sky_light"] = { DoubleValue(spawningContext.skyLight.toDouble()) }
functions["player"] = player@{
val causeEntity = spawningContext.cause.entity ?: return@player DoubleValue.ZERO
if (causeEntity is ServerPlayer) return@player causeEntity.asMoLangValue()
DoubleValue.ZERO
}
return map
return functions
}
}
@@ -17,23 +17,23 @@ import com.cobblemon.mod.common.util.asArrayValue
object SpeciesMoLangFunctions : AbstractMoLangFunctionHolder<Species>() {
override fun Species.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val species = this
val map = mutableMapOf<String, (MoParams) -> Any>(
"identifier" to { StringValue(species.resourceIdentifier.toString()) },
"name" to { StringValue(species.name) },
"primary_type" to { StringValue(species.primaryType.showdownId) },
"secondary_type" to { StringValue(species.secondaryType?.showdownId ?: "null") },
"experience_group" to { StringValue(species.experienceGroup.name) },
"height" to { DoubleValue(species.height) },
"weight" to { DoubleValue(species.weight) },
"base_scale" to { DoubleValue(species.baseScale) },
"hitbox_width" to { DoubleValue(species.hitbox.width) },
"hitbox_height" to { DoubleValue(species.hitbox.height) },
"hitbox_fixed" to { DoubleValue(species.hitbox.fixed) },
"catch_rate" to { DoubleValue(species.catchRate) },
"labels" to { species.labels.asArrayValue { StringValue(it) } },
"has_label" to { params -> DoubleValue(species.labels.contains(params.getString(0))) }
)
val functions = hashMapOf<String, (MoParams) -> Any>()
return map
functions["identifier"] = { StringValue(species.resourceIdentifier.toString()) }
functions["name"] = { StringValue(species.name) }
functions["primary_type"] = { StringValue(species.primaryType.showdownId) }
functions["secondary_type"] = { StringValue(species.secondaryType?.showdownId ?: "null") }
functions["experience_group"] = { StringValue(species.experienceGroup.name) }
functions["height"] = { DoubleValue(species.height) }
functions["weight"] = { DoubleValue(species.weight) }
functions["base_scale"] = { DoubleValue(species.baseScale) }
functions["hitbox_width"] = { DoubleValue(species.hitbox.width) }
functions["hitbox_height"] = { DoubleValue(species.hitbox.height) }
functions["hitbox_fixed"] = { DoubleValue(species.hitbox.fixed) }
functions["catch_rate"] = { DoubleValue(species.catchRate) }
functions["labels"] = { species.labels.asArrayValue { StringValue(it) } }
functions["has_label"] = { params -> DoubleValue(species.labels.contains(params.getString(0))) }
return functions
}
}
@@ -24,7 +24,6 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.util.*
import java.util.UUID
import net.minecraft.core.BlockPos
import net.minecraft.core.Holder
import net.minecraft.core.registries.Registries
@@ -46,85 +45,89 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
import net.minecraft.world.level.storage.loot.parameters.LootContextParams
import net.minecraft.world.phys.AABB
import net.minecraft.world.phys.Vec3
import java.util.UUID
object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
override fun Holder<Level>.moLangFunctions(): MutableMap<String, (MoParams) -> Any> {
val world = this.value()
val map = mutableMapOf<String, (MoParams) -> Any>(
)
val functions = hashMapOf<String, (MoParams) -> Any>()
map["is_time_of_day"] = put@{ params ->
functions["is_time_of_day"] = isTimeOfDay@{ params ->
val timeOfDay =
TimeRange.timeRanges[params.getString(0).lowercase()]
?: return@isTimeOfDay DoubleValue.ZERO
val time = world.dayTime % 24000
val timeOfDay = TimeRange.timeRanges[params.getString(0).lowercase()]
?: return@put DoubleValue.ZERO
val time = world.dayTime % 24000
return@put DoubleValue(timeOfDay.contains(time.toInt()))
DoubleValue(timeOfDay.contains(time.toInt()))
}
map["game_time"] = { _ -> DoubleValue(world.gameTime.toDouble()) }
map["time_of_day"] = put@{
val time = world.dayTime % 24000
return@put DoubleValue(time.toDouble())
}
map["server"] = { _ -> server()?.asMoLangValue() ?: DoubleValue.ZERO }
map["is_raining_at"] = put@{ params ->
functions["game_time"] = { DoubleValue(world.gameTime.toDouble()) }
functions["time_of_day"] = { DoubleValue((world.dayTime % 24000).toDouble()) }
functions["server"] = { server()?.asMoLangValue() ?: DoubleValue.ZERO }
functions["is_raining_at"] = { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
return@put DoubleValue(world.isRainingAt(BlockPos(x, y, z)))
DoubleValue(world.isRainingAt(BlockPos(x, y, z)))
}
map["is_snowing_at"] = put@{ params ->
functions["is_snowing_at"] = { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
val blockPos = BlockPos(x, y, z)
when {
!world.isRaining -> return@put DoubleValue.ZERO
!world.canSeeSky(blockPos) -> return@put DoubleValue.ZERO
!world.isRaining -> {
DoubleValue.ZERO
}
!world.canSeeSky(blockPos) -> {
DoubleValue.ZERO
}
(world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockPos).y > blockPos.y) -> {
return@put DoubleValue.ZERO
DoubleValue.ZERO
}
else -> {
val biome = world.getBiome(blockPos).value() as Biome
return@put DoubleValue(biome.getPrecipitationAt(blockPos) == Biome.Precipitation.SNOW)
DoubleValue(biome.getPrecipitationAt(blockPos) == Biome.Precipitation.SNOW)
}
}
}
map["is_chunk_loaded_at"] = put@{ params ->
functions["is_chunk_loaded_at"] = { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
return@put DoubleValue(world.isLoaded(BlockPos(x, y, z)))
DoubleValue(world.isLoaded(BlockPos(x, y, z)))
}
map["is_thundering"] = { _ -> DoubleValue(world.isThundering) }
map["is_raining"] = { _ -> DoubleValue(world.isRaining) }
map["set_block"] = put@{ params ->
functions["is_thundering"] = { DoubleValue(world.isThundering) }
functions["is_raining"] = { DoubleValue(world.isRaining) }
functions["set_block"] = setBlock@{ params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
val block = world.blockRegistry.get(params.getString(3).asIdentifierDefaultingNamespace())
?: run {
Cobblemon.LOGGER.error("Unknown block: ${params.getString(3)}")
return@put DoubleValue.ZERO
}
val block =
world.blockRegistry.get(params.getString(3).asIdentifierDefaultingNamespace())
?: run {
Cobblemon.LOGGER.error("Unknown block: ${params.getString(3)}")
return@setBlock DoubleValue.ZERO
}
world.setBlock(BlockPos(x, y, z), block.defaultBlockState(), Block.UPDATE_ALL)
}
map["is_air"] = put@{ params ->
functions["is_air"] = { params ->
val x = params.getDouble(0).toInt()
val y = params.getDouble(1).toInt()
val z = params.getDouble(2).toInt()
val blockState = world.getBlockState(BlockPos(x, y, z))
return@put DoubleValue(blockState.isAir)
DoubleValue(blockState.isAir)
}
map["get_block"] = put@{ params ->
functions["get_block"] = { params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
val block = world.getBlockState(BlockPos(x, y, z)).block
return@put world.blockRegistry.wrapAsHolder(block).asMoLangValue(Registries.BLOCK)
world.blockRegistry.wrapAsHolder(block).asMoLangValue(Registries.BLOCK)
}
map["spawn_explosion"] = { params ->
functions["spawn_explosion"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
@@ -136,32 +139,33 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
z,
range,
ExplosionInteraction.valueOf(
params.getStringOrNull(4)?.uppercase() ?: ExplosionInteraction.TNT.name
)
params.getStringOrNull(4)?.uppercase() ?: ExplosionInteraction.TNT.name,
),
)
}
map["spawn_lightning"] = put@{ params ->
functions["spawn_lightning"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val lightning = LightningBolt(EntityType.LIGHTNING_BOLT, world)
lightning.setPos(x, y, z)
world.addFreshEntity(lightning)
return@put DoubleValue.ONE
DoubleValue.ONE
}
// q.entity.world.spawn_bedrock_particles(effect, x, y, z, [player]) - sends to everyone nearby or just to the player if they're set.
map["spawn_bedrock_particles"] = { params ->
functions["spawn_bedrock_particles"] = { params ->
val particle = params.getString(0).asResource()
val x = params.getDouble(1)
val y = params.getDouble(2)
val z = params.getDouble(3)
val player = params.getOrNull<MoValue>(4)?.let {
when (it) {
is StringValue -> world.getPlayerByUUID(UUID.fromString(it.value))
is ObjectValue<*> -> it.obj
else -> null
}
} as? ServerPlayer
val player =
params.getOrNull<MoValue>(4)?.let {
when (it) {
is StringValue -> world.getPlayerByUUID(UUID.fromString(it.value))
is ObjectValue<*> -> it.obj
else -> null
}
} as? ServerPlayer
val pos = Vec3(x, y, z)
val packet = SpawnSnowstormParticlePacket(particle, pos)
@@ -171,7 +175,7 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
packet.sendToPlayersAround(x, y, z, 64.0, world.dimension())
}
}
map["spawn_pokemon"] = put@{ params ->
functions["spawn_pokemon"] = spawnPokemon@{ params ->
val x = params.getInt(0)
val y = params.getInt(1)
val z = params.getInt(2)
@@ -179,49 +183,50 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
val pos = BlockPos(x, y, z)
if (!Level.isInSpawnableBounds(pos)) {
return@put DoubleValue.ZERO
}
if (!Level.isInSpawnableBounds(pos)) return@spawnPokemon DoubleValue.ZERO
val pokemon = props.createEntity(world)
pokemon.moveTo(pos, pokemon.yRot, pokemon.xRot)
if (world.addFreshEntity(pokemon)) {
return@put pokemon.struct
} else {
return@put DoubleValue.ZERO
}
if (world.addFreshEntity(pokemon)) return@spawnPokemon pokemon.struct
DoubleValue.ZERO
}
map["spawn_npc"] = put@{ params ->
functions["spawn_npc"] = spawnNpc@{ params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val npcClass = params.getStringOrNull(3)
?.let { NPCClasses.getByIdentifier(it.asIdentifierDefaultingNamespace()) }
val npcClass =
params
.getStringOrNull(3)
?.let { NPCClasses.getByIdentifier(it.asIdentifierDefaultingNamespace()) }
val level = params.getInt(4)
if (npcClass == null) return@put DoubleValue.ZERO
if (npcClass == null) return@spawnNpc DoubleValue.ZERO
val npc = NPCEntity(world)
npc.moveTo(x, y, z, npc.yRot, npc.xRot)
npc.npc = npcClass
npc.initialize(level)
if (world.addFreshEntity(npc)) {
return@put npc.asMoLangValue()
}
return@put DoubleValue.ZERO
if (world.addFreshEntity(npc)) return@spawnNpc npc.asMoLangValue()
DoubleValue.ZERO
}
map["play_sound_on_server"] = { params ->
functions["play_sound_on_server"] = { params ->
val sound = params.getString(0).asResource()
val soundSource = params.getString(1).uppercase()
val x = params.getDouble(2)
val y = params.getDouble(3)
val z = params.getDouble(4)
val player = params.getOrNull<MoValue>(5)?.let {
when (it) {
is StringValue -> world.getPlayerByUUID(UUID.fromString(it.value))
is ObjectValue<*> -> it.obj
else -> null
}
} as? ServerPlayer
val player =
params.getOrNull<MoValue>(5)?.let {
when (it) {
is StringValue -> world.getPlayerByUUID(UUID.fromString(it.value))
is ObjectValue<*> -> it.obj
else -> null
}
} as? ServerPlayer
val volume = params.getDoubleOrNull(6)?.toFloat() ?: 1.0f
val pitch = params.getDoubleOrNull(7)?.toFloat() ?: 1.0f
@@ -233,29 +238,30 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
packet.sendToPlayersAround(x, y, z, 16.0, world.dimension())
}
}
map["get_entities_around"] = put@{ params ->
functions["get_entities_around"] = { params ->
val x = params.getDouble(0)
val y = params.getDouble(1)
val z = params.getDouble(2)
val range = params.getDouble(3) * 2
val entities = world.getEntities(null, AABB.ofSize(Vec3(x, y, z), range, range, range))
return@put entities
entities
.filterIsInstance<LivingEntity>()
.map { it.asMostSpecificMoLangValue() }
.asArrayValue()
}
map["is_healer_in_use"] = put@{ params ->
functions["is_healer_in_use"] = isHealerInUse@{ params ->
val pos = params.get<ArrayStruct>(0).asBlockPos()
val healer = world.getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null)
?: return@put DoubleValue.ONE
return@put DoubleValue(healer.isInUse)
val healer =
world.getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null)
?: return@isHealerInUse DoubleValue.ONE
return@isHealerInUse DoubleValue(healer.isInUse)
}
map["spawn_loot_table_items"] = put@{ params ->
functions["spawn_loot_table_items"] = spawnLootTableItems@{ params ->
val serverLevel = world as? ServerLevel
if (serverLevel == null) {
Cobblemon.LOGGER.warn("spawn_loot_table_items: world is not a ServerLevel")
return@put DoubleValue.ZERO
return@spawnLootTableItems DoubleValue.ZERO
}
val lootTableId = params.getString(0).asIdentifierDefaultingNamespace()
val x = params.getDouble(1)
@@ -265,9 +271,11 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
val lootTableKey = ResourceKey.create(Registries.LOOT_TABLE, lootTableId)
val lootTable = serverLevel.server.reloadableRegistries().getLootTable(lootTableKey)
val lootParams = LootParams.Builder(serverLevel)
.withParameter(LootContextParams.ORIGIN, Vec3(x, y, z))
.create(LootContextParamSets.COMMAND)
val lootParams =
LootParams
.Builder(serverLevel)
.withParameter(LootContextParams.ORIGIN, Vec3(x, y, z))
.create(LootContextParamSets.COMMAND)
val items = lootTable.getRandomItems(lootParams)
val spawnedItems = ArrayStruct(hashMapOf())
@@ -285,9 +293,10 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
}
}
}
return@put spawnedItems
spawnedItems
}
return map
return functions
}
}
@@ -269,7 +269,7 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
createDefault("dive_ball", CatchRateModifiers.SUBMERGED_IN_WATER, waterDragValue = 0.99F)
createDefault("nest_ball", CatchRateModifiers.NEST)
createDefault("repeat_ball", CatchRateModifiers.REPEAT)
createDefault("timer_ball", CatchRateModifiers.turnBased { turn -> (1F * turn * (1229F / 4096F)).coerceAtMost(4F) })
createDefault("timer_ball", CatchRateModifiers.turnBased { turn -> (1F + turn * (1229F / 4096F)).coerceAtMost(4F) })
createDefault("luxury_ball", effects = listOf(FriendshipEarningBoostEffect(2F)))
createDefault("premier_ball")
createDefault("dusk_ball", CatchRateModifiers.LIGHT_LEVEL)
@@ -278,7 +278,7 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
createDefault("cherish_ball")
createDefault("park_ball", CatchRateModifiers.PARK)
createDefault("dream_ball", CatchRateModifiers.statusBoosting(4F, Statuses.SLEEP))
createDefault("beast_ball", LabelModifier(5F, true, CobblemonPokemonLabels.ULTRA_BEAST)/*, LabelModifier(0.1F, false, CobblemonPokemonLabels.ULTRA_BEAST))*/)
createDefault("beast_ball", DynamicMultiplierModifier({ _, pokemon -> if (pokemon.hasLabels(CobblemonPokemonLabels.ULTRA_BEAST)) 5F else 0.1F }) { _, _ -> true })
createDefault("ancient_poke_ball", ancient = true)
createDefault("ancient_citrine_ball", ancient = true)
createDefault("ancient_verdant_ball", ancient = true)
@@ -297,13 +297,15 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
createDefault("ancient_origin_ball", GuaranteedModifier(), ancient = true)
// Luxury ball effect, low priority as it must be triggered before soothe bell as of gen 4
CobblemonEvents.FRIENDSHIP_UPDATED.subscribe(priority = Priority.LOW) { event ->
var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
if (increment <= 0) //these affects are only meant to affect positive gains
if (!event.earned) {
return@subscribe
if (increment <= 1F) {
event.pokemon.caughtBall.effects.filterIsInstance<FriendshipEarningBoostEffect>()
.forEach { increment *= it.multiplier }
}
var increment = (event.newFriendship - event.pokemon.friendship).toFloat()
if (increment <= 0) {
return@subscribe
}
event.pokemon.caughtBall.effects.filterIsInstance<FriendshipEarningBoostEffect>()
.forEach { increment *= it.multiplier }
event.newFriendship = event.pokemon.friendship + increment.roundToInt()
}
}
@@ -338,7 +340,6 @@ object PokeBalls : JsonDataRegistry<PokeBall> {
ancient: Boolean = false
): PokeBall {
val identifier = cobblemonResource(name)
//val finalModifiers = if (appendUltraBeastPenalty) modifiers + listOf(LabelModifier(0.1F, true, CobblemonPokemonLabels.ULTRA_BEAST)) else modifiers
val pokeball = PokeBall(identifier, modifier, effects, waterDragValue, model2d, model3d, throwPower, ancient)
this.defaults[identifier] = pokeball
return pokeball
@@ -54,22 +54,20 @@ object CatchRateModifiers {
/**
* Used by [PokeBalls.LOVE_BALL].
* Boosts the catch rate if the Pokémon is of the same species and opposite gender
* Boosts the catch rate 2.5× if any of the player's active Pokémon is of the opposite gender,
* or 8× if that Pokémon is also of the same species.
*/
val LOVE = BattleModifier { _, playerPokemon, pokemon ->
if (
pokemon.gender != Gender.GENDERLESS
&& playerPokemon.mapNotNull { it.battlePokemon?.originalPokemon }
.any {
it.gender != Gender.GENDERLESS &&
it.species.name.equals(pokemon.species.name, true) &&
it.gender != pokemon.gender
}
) {
if (playerPokemon.any { it.battlePokemon?.originalPokemon?.species?.resourceIdentifier == pokemon.species.resourceIdentifier }) 8F else 2.5F
if (pokemon.gender == Gender.GENDERLESS) {
return@BattleModifier 1F
}
else {
1F
val oppositeGender = playerPokemon
.mapNotNull { it.battlePokemon?.originalPokemon }
.filter { it.gender != Gender.GENDERLESS && it.gender != pokemon.gender }
when {
oppositeGender.any { it.species.resourceIdentifier == pokemon.species.resourceIdentifier } -> 8F
oppositeGender.isNotEmpty() -> 2.5F
else -> 1F
}
}
@@ -81,7 +79,7 @@ object CatchRateModifiers {
* 1× otherwise.
*/
val MOON_PHASES: CatchRateModifier = WorldStateModifier { _, entity ->
if (entity.level().gameTime in 12000..24000)
if (entity.level().dayTime % 24000 < 12000)
return@WorldStateModifier 1F
when (entity.level().moonPhase) {
2, 6 -> 1.5F
@@ -42,7 +42,7 @@ class PokedexManager(
}
// Java interop isn't great lol
@Deprecated("Use encounter(PokedexEntityData) instead")
@Deprecated("Use obtain(Pokemon) instead")
fun catch(pokemon: Pokemon) {
obtain(pokemon)
}
@@ -54,8 +54,8 @@ enum class Stats(override val identifier: ResourceLocation, override val display
"hp" -> HP
"atk", "attack" -> ATTACK // Hyper Cutter states the full stat name "Attack"
"def", "defense", "defence" -> DEFENCE // Big Pecks states the full stat name "Defense"
"spa" -> SPECIAL_ATTACK
"spd" -> SPECIAL_DEFENCE
"spa", "special_attack" -> SPECIAL_ATTACK
"spd", "special_defence", "special_defense" -> SPECIAL_DEFENCE
"spe", "speed" -> SPEED
"evasion" -> EVASION
else -> ACCURACY
@@ -71,7 +71,7 @@ class FishingSpawnCause(
}
fun alterSize(pokemonEntity: PokemonEntity, effect: SpawnBait.Effect) {
pokemonEntity.pokemon.scaleModifier *= effect.value.toFloat() / 1000.0f
pokemonEntity.pokemon.scaleModifier += effect.value.toFloat() / 1000.0f
}
fun saveDropsReroll(pokemonEntity: PokemonEntity, effect: SpawnBait.Effect) {
@@ -17,10 +17,10 @@ import com.cobblemon.mod.common.api.storage.factory.PokemonStoreFactory
import com.cobblemon.mod.common.pokemon.Pokemon
import com.cobblemon.mod.common.util.DataKeys
import com.google.gson.JsonObject
import java.util.UUID
import net.minecraft.core.RegistryAccess
import net.minecraft.nbt.CompoundTag
import net.minecraft.server.level.ServerPlayer
import java.util.UUID
/**
* The base class for all stores of [Pokemon]. A store specifies the kind of coordinate it needs to be given
@@ -77,7 +77,6 @@ abstract class PokemonStore<T : StorePosition> : Iterable<Pokemon> {
remove(pokemon)
val position = getFirstAvailablePosition() ?: return false // Couldn't fit, shrug emoji
set(position, pokemon)
Cobblemon.playerDataManager.getTMData(uuid)?.syncTMsFromPokemon(pokemon)
return true
}
@@ -8,6 +8,7 @@
package com.cobblemon.mod.common.block
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.api.tags.CobblemonBlockTags
import com.cobblemon.mod.common.block.TypeGemClusterBlock.Companion.SHOULD_GROW
@@ -33,6 +34,9 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
const val MIN_DISTANCE_BETWEEN_GEMS = 1
const val CONTINUATION_CHANCE = 0.8f
// Upper safety check to prevent infinite loops
const val MAX_FORCE_GROW_ATTEMPTS = 64
val BLOCK_TO_CLUSTER: Map<ResourceLocation, Block> by lazy {
mapOf(
ResourceLocation.parse("cobblemon:normal_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_NORMAL,
@@ -112,13 +116,16 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
fun forceGrow(level: WorldGenLevel, pos: BlockPos, random: RandomSource, percentage: Float) {
val desiredLength = MAX_CONNECTED_GEMS * percentage
while (true) {
val growInfo = grow(level, pos, random, true)
val grown = growInfo.first
val clusterSize = growInfo.second
if (!grown || clusterSize >= desiredLength) break
repeat(MAX_FORCE_GROW_ATTEMPTS) {
val (grown, clusterSize) = grow(level, pos, random, true)
if (!grown || clusterSize >= desiredLength) return
}
Cobblemon.LOGGER.warn(
"Forced type gem growth at {} stopped after {} attempts without reaching its target size; keeping the partial formation.",
pos,
MAX_FORCE_GROW_ATTEMPTS
)
}
private fun grow(
@@ -130,7 +137,7 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
val connectedGems = getConnectedGemBlocks(level, pos) // maybe we can store this and access it for better performance? check for changes in list rather than checking each time grow is called? idk
val gemCount = connectedGems.size
val overLimit = gemCount >= MAX_CONNECTED_GEMS
if (overLimit) {
// if there is no open air pockets to grow any new clusters then exit early
if (!hasBreathingRoom(level, connectedGems)) {
@@ -165,6 +172,11 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
level.setBlock(targetPos, placeState, UPDATE_ALL)
// During world gen, the region silently discards writes into neighboring chunks that are already fully generated.
// Through ImposterProtoChunk with writes set to disabled. Checks if the block is still air after the write and skips if so as it can't be filled.
// Preventing infinite loops.
if (!level.getBlockState(targetPos).`is`(clusterBlock)) continue
if (forced) {
forceAdvanceClusterGrowth(level, targetPos, random)
}
@@ -210,4 +222,4 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
}
override fun isRandomlyTicking(state: BlockState): Boolean = true
}
}
@@ -21,7 +21,10 @@ object SetActiveTMPacketHandler : ServerNetworkPacketHandler<SetActiveTMPacket>
val menu = player.containerMenu as? TMMachineMenu ?: return
val tmData = Cobblemon.playerDataManager.getTMData(player)
if (packet.tm != null && (!packet.tm.isPassivelyObtained() && packet.tm.id !in tmData.learnedTMs)) {
if (packet.tm != null
&& !Cobblemon.config.unlockAllMoveDexMovesByDefault
&& !packet.tm.isPassivelyObtained()
&& packet.tm.id !in tmData.learnedTMs) {
return // Hacker smh
}
@@ -40,7 +40,8 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent<T, PlayerModel<T>>) : RenderLayer<T, PlayerModel<T>>(renderLayerParent) {
class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent<T, PlayerModel<T>>) :
RenderLayer<T, PlayerModel<T>>(renderLayerParent) {
val context = RenderContext().also {
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.WORLD)
@@ -68,19 +69,62 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
// It's unclear why Minecraft's providing a partial ticks based on 60FPS regardless of the real FPS.
// Whatever - the delta manager works correctly.
val realPartialTicks = Minecraft.getInstance().timer.realtimeDeltaTicks
this.render(matrixStack, buffer, packedLight, livingEntity, limbSwing, limbSwingAmount, realPartialTicks, ageInTicks, netHeadYaw, headPitch, true)
this.render(matrixStack, buffer, packedLight, livingEntity, limbSwing, limbSwingAmount, realPartialTicks, ageInTicks, netHeadYaw, headPitch, false)
this.render(
matrixStack,
buffer,
packedLight,
livingEntity,
limbSwing,
limbSwingAmount,
realPartialTicks,
ageInTicks,
netHeadYaw,
headPitch,
true
)
this.render(
matrixStack,
buffer,
packedLight,
livingEntity,
limbSwing,
limbSwingAmount,
realPartialTicks,
ageInTicks,
netHeadYaw,
headPitch,
false
)
}
fun configureState(state: FloatingState, model: PosableModel, leftShoulder: Boolean, shoulderData: ShoulderData): FloatingState {
fun configureState(
state: FloatingState,
model: PosableModel,
leftShoulder: Boolean,
shoulderData: ShoulderData
): FloatingState {
state.currentModel = model
state.setPoseToFirstSuitable(if (leftShoulder) PoseType.SHOULDER_LEFT else PoseType.SHOULDER_RIGHT)
state.runtime.environment.query.addFunction("is_holding_item") { return@addFunction DoubleValue(shoulderData.shownItem.let {
!it.isEmpty && !it.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS) && !it.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)
}) }
state.runtime.environment.query.addFunction("is_wearing_hat") { return@addFunction DoubleValue(shoulderData.shownItem.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS)) }
state.runtime.environment.query.addFunction("is_wearing_face") { return@addFunction DoubleValue(shoulderData.shownItem.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)) }
state.runtime.environment.query.addFunction("is_holding_item") {
return@addFunction DoubleValue(shoulderData.shownItem.let {
!it.isEmpty && !it.`is`(CobblemonItemTags.WEARABLE_HAT_ITEMS) && !it.`is`(CobblemonItemTags.WEARABLE_FACE_ITEMS)
})
}
state.runtime.environment.query.addFunction("is_wearing_hat") {
return@addFunction DoubleValue(
shoulderData.shownItem.`is`(
CobblemonItemTags.WEARABLE_HAT_ITEMS
)
)
}
state.runtime.environment.query.addFunction("is_wearing_face") {
return@addFunction DoubleValue(
shoulderData.shownItem.`is`(
CobblemonItemTags.WEARABLE_FACE_ITEMS
)
)
}
return state
}
@@ -100,12 +144,12 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
) {
val compoundTag = if (pLeftShoulder) livingEntity.shoulderEntityLeft else livingEntity.shoulderEntityRight
if (compoundTag.isPokemonEntity()) {
livingEntity.level().profiler.push("shoulder_render_".plus(if(pLeftShoulder) "left" else "right"))
livingEntity.level().profiler.push("shoulder_render_".plus(if (pLeftShoulder) "left" else "right"))
val cache = playerCache.getOrPut(livingEntity.uuid) { ShoulderCache() }
val shoulderData = shoulderDataFrom(compoundTag)
if (pLeftShoulder) cache.lastKnownLeft = shoulderData else cache.lastKnownRight = shoulderData
if (shoulderData == null){
if (shoulderData == null) {
// Nothing to do
return
}
@@ -137,11 +181,11 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
matrixStack.scale(scale, scale, scale)
matrixStack.translate(0f, 1.5f, 0f)
state = if (pLeftShoulder && shoulderData != lastRenderedLeft) {
state = if (pLeftShoulder && !shoulderData.matches(lastRenderedLeft)) {
leftState = configureState(state, model, true, shoulderData)
lastRenderedLeft = shoulderData
leftState
} else if (!pLeftShoulder && shoulderData != lastRenderedRight) {
} else if (!pLeftShoulder && !shoulderData.matches(lastRenderedRight)) {
rightState = configureState(state, model, false, shoulderData)
lastRenderedRight = shoulderData
rightState
@@ -151,7 +195,14 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
state.updatePartialTicks(partialTicks)
context.put(RenderContext.POSABLE_STATE, state)
state.currentModel = model
val vertexConsumer = buffer.getBuffer(RenderType.entityCutout(VaryingModelRepository.getTexture(shoulderData.species.resourceIdentifier, state)))
val vertexConsumer = buffer.getBuffer(
RenderType.entityCutout(
VaryingModelRepository.getTexture(
shoulderData.species.resourceIdentifier,
state
)
)
)
val i = LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0f)
model.applyAnimations(
@@ -164,7 +215,11 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
ageInTicks = livingEntity.tickCount.toFloat()
)
model.render(context, matrixStack, vertexConsumer, packedLight, i, -0x1)
model.withLayerContext(buffer, state, VaryingModelRepository.getLayers(shoulderData.species.resourceIdentifier, state)) {
model.withLayerContext(
buffer,
state,
VaryingModelRepository.getLayers(shoulderData.species.resourceIdentifier, state)
) {
model.render(context, matrixStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
}
@@ -179,8 +234,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
model.setDefault()
matrixStack.popPose()
livingEntity.level().profiler.pop()
}
else {
} else {
val entry = playerCache.getOrPut(livingEntity.uuid) { ShoulderCache() }
if (pLeftShoulder) entry.lastKnownLeft = null else entry.lastKnownRight = null
}
@@ -191,14 +245,21 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
var lastKnownRight: ShoulderData? = null
)
data class ShoulderData(
class ShoulderData(
val uuid: UUID,
val species: Species,
val form: FormData,
val aspects: Set<String>,
val scaleModifier: Float,
val shownItem: ItemStack
)
val shownItem: ItemStack,
) {
fun matches(other: ShoulderData?): Boolean = other != null
&& uuid == other.uuid
&& species == other.species
&& form == other.form
&& aspects == other.aspects
&& shownItem.item == other.shownItem.item
}
companion object {
@@ -25,7 +25,8 @@ object PokedexHandler : EventHandler {
}
fun onPokemonGained(event: PokemonGainedEvent) {
Cobblemon.playerDataManager.getPokedexData(event.playerId).catch(event.pokemon)
Cobblemon.playerDataManager.getPokedexData(event.playerId).obtain(event.pokemon)
Cobblemon.playerDataManager.getTMData(event.playerId).syncTMsFromPokemon(event.pokemon)
}
fun onPokemonSeen(event: PokemonSeenEvent) {
@@ -34,7 +35,7 @@ object PokedexHandler : EventHandler {
fun onPokemonAspectsChanged(event: PokemonAspectsChangedEvent) {
if (event.ownerId != null) {
Cobblemon.playerDataManager.getPokedexData(event.ownerId).catch(event.pokemon)
Cobblemon.playerDataManager.getPokedexData(event.ownerId).obtain(event.pokemon)
}
}
@@ -32,6 +32,11 @@ object TMMachineTeachMoveHandler : ServerNetworkPacketHandler<TMMachineTeachMove
val menu = player.containerMenu as? TMMachineMenu ?: return
val inventory = menu.inventory ?: return
// This is checked on the client, but a modified client could still try to teach an illegal move.
if (moveTemplate !in pokemon.form.moves.tmLearnableMoves()) {
return
}
if (ItemStack.isSameItemSameComponents(packet.heldStack, menu.carried) &&
moveTemplate == TMMoveComponent.getTMMove(packet.heldStack) &&
packet.heldStack.count == menu.carried.count &&
@@ -53,4 +58,4 @@ object TMMachineTeachMoveHandler : ServerNetworkPacketHandler<TMMachineTeachMove
player.playNotifySound(CobblemonSounds.MOVE_LEARN, SoundSource.MASTER, 1.0F, 1.0F)
}
}
}
}
@@ -18,6 +18,11 @@ import net.minecraft.server.level.ServerPlayer
object SaveHabitatBlockSettingsHandler : ServerNetworkPacketHandler<SaveHabitatBlockSettingsPacket> {
override fun handle(packet: SaveHabitatBlockSettingsPacket, server: MinecraftServer, player: ServerPlayer) {
if (!player.isCreative) {
// mf does not have permission
return
}
val world = player.serverLevel()
val blockEntity = world.getBlockEntity(packet.blockPos) as? HabitatBlockEntity ?: return // it's broken
val pre = SaveHabitatBlockSettingsEvent.Pre(
@@ -28,11 +33,6 @@ object SaveHabitatBlockSettingsHandler : ServerNetworkPacketHandler<SaveHabitatB
settings = packet.settings
)
if (!player.isCreative) {
// mf does not have permission
return
}
CobblemonEvents.HABITAT_SETTINGS_SAVED_PRE.postThen(pre) {
blockEntity.applySettings(habitatSettingsDTO = packet.settings)
val post = SaveHabitatBlockSettingsEvent.Post(
@@ -391,15 +391,19 @@ open class Pokemon : ShowdownIdentifiable {
*/
var friendship = this.form.baseFriendship
private set(value) {
val earned = this.friendshipEarned
this.friendshipEarned = false
if (!this.isPossibleFriendship(value)) {
return
}
FRIENDSHIP_UPDATED.post(FriendshipUpdatedEvent(this, value)) {
FRIENDSHIP_UPDATED.post(FriendshipUpdatedEvent(this, value, earned)) {
field = it.newFriendship
onChange(FriendshipUpdatePacket({ this }, it.newFriendship))
}
}
private var friendshipEarned = false
var currentFullness = 0
set(value) {
val clamped = value.coerceIn(0, getMaxFullness())
@@ -595,7 +599,7 @@ open class Pokemon : ShowdownIdentifiable {
var scaleModifier: Float = 1F
set(value) {
if (field != value) {
field = value
field = value.coerceAtLeast(0.05F)
onChange(ScaleModifierUpdatePacket({ this }, value))
}
}
@@ -1601,6 +1605,7 @@ open class Pokemon : ShowdownIdentifiable {
val sanitizedAmount = if (coerceSafe) amount.absoluteValue.coerceAtMost(Cobblemon.config.maxPokemonFriendship - this.friendship) else amount.absoluteValue
val newValue = this.friendship + sanitizedAmount
if (this.isPossibleFriendship(newValue)) {
this.friendshipEarned = true
this.friendship = newValue
}
return this.friendship == newValue
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.pokemon.requirements
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -17,10 +18,13 @@ class StatCompareRequirement : Requirement {
const val ADAPTER_VARIANT = "stat_compare"
}
val highStat = Stats.ATTACK.name
val lowStat = Stats.DEFENCE.name
val highStat = Stats.ATTACK.identifier.path
val lowStat = Stats.DEFENCE.identifier.path
override fun check(pokemon: Pokemon): Boolean {
return pokemon.getStat(Stats.getStat(highStat)) > pokemon.getStat(Stats.getStat(lowStat))
val high = Stats.getStat(highStat)
val low = Stats.getStat(lowStat)
if (high.type != Stat.Type.PERMANENT || low.type != Stat.Type.PERMANENT) return false
return pokemon.getStat(high) > pokemon.getStat(low)
}
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.pokemon.requirements
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.api.pokemon.stats.Stat
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.pokemon.Pokemon
@@ -17,10 +18,13 @@ class StatEqualRequirement : Requirement {
const val ADAPTER_VARIANT = "stat_equal"
}
val statOne = Stats.ATTACK.name
val statTwo = Stats.DEFENCE.name
val statOne = Stats.ATTACK.identifier.path
val statTwo = Stats.DEFENCE.identifier.path
override fun check(pokemon: Pokemon): Boolean {
return pokemon.getStat(Stats.getStat(statOne)) == pokemon.getStat(Stats.getStat(statTwo))
val one = Stats.getStat(statOne)
val two = Stats.getStat(statTwo)
if (one.type != Stat.Type.PERMANENT || two.type != Stat.Type.PERMANENT) return false
return pokemon.getStat(one) == pokemon.getStat(two)
}
}
@@ -8,16 +8,11 @@
package com.cobblemon.mod.common.world.feature
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.CobblemonBlocks.TYPE_GEM_CORE
import com.cobblemon.mod.common.CobblemonBlocks.typeGemBlocks
import com.cobblemon.mod.common.CobblemonBlocks.typeGemClusters
import com.cobblemon.mod.common.block.TypeGemClusterBlock
import com.cobblemon.mod.common.block.TypeGemCoreBlock
import com.cobblemon.mod.common.util.random
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.resources.ResourceLocation
import net.minecraft.tags.BlockTags
import net.minecraft.world.level.WorldGenLevel
import net.minecraft.world.level.block.Block.UPDATE_ALL
@@ -47,9 +42,12 @@ class TypeGemFeature : Feature<BlockStateConfiguration>(BlockStateConfiguration.
val gemState = gemBlock.defaultBlockState()
val coreState = TYPE_GEM_CORE.defaultBlockState()
// Place core and initial gem
// Place the gem first then make sure it placed before placing the core.
worldGenLevel.setBlock(origin, coreState, UPDATE_ALL)
if (!worldGenLevel.getBlockState(chosenPos).`is`(gemBlock)) {
return false
}
worldGenLevel.setBlock(origin, coreState, UPDATE_ALL)
worldGenLevel.setBlock(chosenPos, gemState, UPDATE_ALL)
// Trigger forced growth with clusters
val coreBlock = coreState.block as TypeGemCoreBlock
@@ -72,4 +70,4 @@ class TypeGemFeature : Feature<BlockStateConfiguration>(BlockStateConfiguration.
return airBlocks
}
}
}
@@ -592,7 +592,7 @@
},
"sound_effects": {
"0.0": {
"effect": "pokemon.raticate_alolan.alola.cry"
"effect": "pokemon.raticate_alolan.cry"
}
}
},
@@ -1155,14 +1155,6 @@
"position": [0, 0.5, 0]
}
},
"sound_effects": {
"0.0417": {
"effect": "animation.plumage_wing_flap_1"
},
"0.5417": {
"effect": "animation.plumage_wing_flap_3"
}
},
"timeline": {
"0.0417": "q.has_entity ? { q.sound('animation.plumage.wing_flap.small'); };",
"0.5417": "q.has_entity ? { q.sound('animation.plumage.wing_flap.small'); };"
@@ -1967,14 +1967,6 @@
"position": [0, 0, -1]
}
},
"sound_effects": {
"0.0417": {
"effect": "animation.plumage_wing_flap_medium_8"
},
"1.375": {
"effect": "animation.plumage_wing_flap_medium_2"
}
},
"timeline": {
"0.0417": "q.has_entity ? { q.sound('animation.plumage.wing_flap.medium'); };",
"1.375": "q.has_entity ? { q.sound('animation.plumage.wing_flap.medium'); };"
@@ -2228,20 +2220,6 @@
"position": [0, 0, 2]
}
},
"sound_effects": {
"0.7083": {
"effect": "animation.plumage_wing_flap_medium_2"
},
"1.6667": {
"effect": "animation.plumage_wing_flap_medium_8"
},
"2.7083": {
"effect": "animation.plumage_wing_flap_medium_2"
},
"3.6667": {
"effect": "animation.plumage_wing_flap_medium_8"
}
},
"timeline": {
"0.7083": "q.has_entity ? { q.sound('animation.plumage.wing_flap.medium'); };",
"1.6667": "q.has_entity ? { q.sound('animation.plumage.wing_flap.medium'); };",
@@ -2544,20 +2544,6 @@
"rotation": [7.5, 0, "math.sin(q.anim_time*90-90)*3"]
}
},
"sound_effects": {
"0.7083": {
"effect": "animation.plumage_wing_flap_medium_2"
},
"1.6667": {
"effect": "animation.plumage_wing_flap_medium_8"
},
"2.7083": {
"effect": "animation.plumage_wing_flap_medium_2"
},
"3.6667": {
"effect": "animation.plumage_wing_flap_medium_8"
}
},
"timeline": {
"0.7083": "q.has_entity ? { q.sound('animation.plumage.wing_flap.medium'); };",
"1.6667": "q.has_entity ? { q.sound('animation.plumage.wing_flap.medium'); };",
@@ -5,8 +5,8 @@
"loop": true,
"bones": {
"body": {
"rotation": [35, 0, 0],
"position": [0, -1, 0]
"rotation": ["35+math.sin(q.anim_time*90*8-0)*2", 0, "0-math.sin(q.anim_time*90*4-60)*1"],
"position": ["-0+math.sin(q.anim_time*90*4-30)*0.5", "-1-math.sin(q.anim_time*90*8-60)*1", 0]
},
"neck": {
"rotation": [2.5, 0, 0]
@@ -18,16 +18,16 @@
"rotation": [-20, 0, 0]
},
"tail": {
"rotation": [-42.5, 0, 0]
"rotation": ["-42.5+math.sin(q.anim_time*90*8-30)*2", 0, "0-math.sin(q.anim_time*90*4-90)*1"]
},
"tail2": {
"rotation": [-55, 0, 0]
"rotation": ["-55+math.sin(q.anim_time*90*8-60)*0.5", 0, "0-math.sin(q.anim_time*90*8-120)*1"]
},
"tail3": {
"rotation": [-25, 0, 0]
"rotation": ["-25+math.sin(q.anim_time*90*8-90)*1", 0, 0]
},
"tail4": {
"rotation": [-32.5, 0, 0]
"rotation": ["-32.5+math.sin(q.anim_time*90*8-120)*1", 0, 0]
},
"apple_bottom": {
"rotation": [75, 0, 0]
@@ -36,19 +36,19 @@
"rotation": [0, 30, 0]
},
"arm_left": {
"rotation": [-7.5, -50, 17.5]
"rotation": ["-7.5+math.sin(q.anim_time*90*8+60)*-15", "-0+math.sin(q.anim_time*90*8+60)*-50", 17.5]
},
"elbow": {
"rotation": [0, -15, -32.5]
"rotation": [0, -15, "-32.5-math.sin(q.anim_time*90*8+30)*15"]
},
"head": {
"rotation": [-17.5, 0, 0]
"rotation": ["-17.5+math.sin(q.anim_time*90*8-60)*2", 0, "0-math.sin(q.anim_time*90*4-30)*1"]
},
"eye_left": {
"rotation": [-5, 42.5, 17.5]
"rotation": [-5, 42.5, "17.5-math.sin(q.anim_time*90*8-90)*1"]
},
"eye_left2": {
"rotation": [0, 0, -17.5]
"rotation": [0, 0, "-17.5-math.sin(q.anim_time*90*8-120)*1"]
},
"hat": {
"rotation": [10, 0, 0]
@@ -66,10 +66,10 @@
"rotation": [-25, 0, 0]
},
"eye_right": {
"rotation": [-5, -42.5, -17.5]
"rotation": [-5, -42.5, "-17.5+math.sin(q.anim_time*90*8-90)*1"]
},
"eye_right2": {
"rotation": [0, 0, 17.5]
"rotation": [0, 0, "17.5+math.sin(q.anim_time*90*8-120)*1"]
},
"finger_middle_left2": {
"rotation": [0, 10, 0]
@@ -84,10 +84,10 @@
"rotation": [-7.5, 0, 0]
},
"arm_right": {
"rotation": [-7.5, 50, -17.5]
"rotation": ["-7.5+math.sin(q.anim_time*90*8+60)*-15", "0-math.sin(q.anim_time*90*8+60)*-50", -17.5]
},
"elbow2": {
"rotation": [0, 15, 32.5]
"rotation": [0, 15, "32.5+math.sin(q.anim_time*90*8+30)*15"]
},
"finger_top_right": {
"rotation": [7.5, 0, 0]
@@ -118,6 +118,12 @@
},
"apple_left3": {
"rotation": [0, 35, 0]
},
"horn": {
"rotation": ["-0+math.sin(q.anim_time*90*8-120)*1", 0, 0]
},
"horn2": {
"rotation": ["-0+math.sin(q.anim_time*90*8-180)*1", 0, 0]
}
}
},
@@ -127,25 +133,37 @@
"eyelid_left": {
"position": {
"0.0": [0.03, 0, 0],
"0.1667": {"pre": [0.03, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0.03, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_left2": {
"position": {
"0.0": [0.03, 0, 0],
"0.1667": {"pre": [0.03, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [0.03, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_right": {
"position": {
"0.0": [-0.03, 0, 0],
"0.1667": {"pre": [-0.03, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [-0.03, 0, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_right2": {
"position": {
"0.0": [-0.03, 0, 0],
"0.1667": {"pre": [-0.03, 0, 0], "post": [0, 0, 0]}
"0.1667": {
"pre": [-0.03, 0, 0],
"post": [0, 0, 0]
}
}
}
}
@@ -207,9 +225,63 @@
}
},
"animation.flapple.cry": {
"animation_length": 1.2,
"animation_length": 1,
"bones": {
"jaw": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.3333": {
"post": [47.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [47.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.8333": {
"post": [10.75, 0, 0],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"head_ai": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.1667": {
"post": [5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.2917": {
"post": [-15, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5833": {
"post": [-19, 0, 0],
"lerp_mode": "catmullrom"
},
"0.8333": {
"post": [-2, 0, 0],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
}
},
"sound_effects": {
"0.04": {
"0.2083": {
"effect": "pokemon.flapple.cry"
}
}
@@ -5,34 +5,81 @@
"loop": true,
"bones": {
"right_ear_eye": {
"rotation": [0, 0, -47.5]
"rotation": [0, 0, "-45+math.sin(q.anim_time*90*1-180)*-7"]
},
"right_ear": {
"rotation": [0, 12.5, 17.5]
"rotation": [0, 15, "15+math.sin(q.anim_time*90*1-210)*-5"]
},
"left_ear_eye": {
"rotation": [0, 0, 45]
"rotation": [0, 0, "45-math.sin(q.anim_time*90*1-180)*-7"]
},
"left_ear": {
"rotation": [0, -15, -15]
"rotation": [0, -15, "-15-math.sin(q.anim_time*90*1-210)*-5"]
},
"left_leaf": {
"rotation": [0, 0, -22.5]
"rotation": [0, 0, "-22.5+math.sin(q.anim_time*90*1-150)*-10"]
},
"left_leaf_bend": {
"rotation": [0, 0, -12.5]
"rotation": [0, 0, "-12.5+math.sin(q.anim_time*90*1-210)*-10"]
},
"right_leaf": {
"rotation": [0, 0, 22.5]
"rotation": [0, 0, "22.5-math.sin(q.anim_time*90*1-150)*-10"]
},
"right_leaf_bend": {
"rotation": [0, 0, 12.5]
"rotation": [0, 0, "12.5-math.sin(q.anim_time*90*1-210)*-10"]
},
"tail2": {
"rotation": [7.5, 0, 0]
"rotation": ["7.5+math.sin(q.anim_time*90*1-120)*-5", "-0+math.sin(q.anim_time*90*0.5-180)*15", 0]
},
"tail3": {
"rotation": [10, 0, 0]
"rotation": ["10+math.sin(q.anim_time*90*1-180)*-7.5", "-0+math.sin(q.anim_time*90*0.5-240)*15", 0]
},
"torso": {
"rotation": ["-0+math.sin(q.anim_time*90*1-60)*1", 0, "0-math.sin(q.anim_time*90*0.5-90)*1"],
"position": [0, "0-math.sin(q.anim_time*90*1-90)*-0.2", 0]
},
"neck": {
"rotation": ["-1+math.sin(q.anim_time*90*1-120)*1", 0, 0]
},
"head": {
"rotation": ["-0+math.sin(q.anim_time*90*1-150)*1.5", 0, "0-math.sin(q.anim_time*90*1-180)*1"]
},
"jaw": {
"rotation": ["5+math.sin(q.anim_time*90*1-60)*-5", 0, 0]
},
"left_front_leg": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*2", 0, 0],
"position": [0, "0-math.sin(q.anim_time*90*1-90)*0.02", "0-math.sin(q.anim_time*90*1-90)*0.11"]
},
"left_front_paw": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*-2", 0, 0]
},
"right_front_leg": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*2", 0, 0],
"position": [0, "0-math.sin(q.anim_time*90*1-90)*0.02", "0-math.sin(q.anim_time*90*1-90)*0.11"]
},
"right_front_paw": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*-2", 0, 0]
},
"right_leg": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*-2", 0, 0],
"position": [0, "0-math.sin(q.anim_time*90*1-90)*0.01", "0-math.sin(q.anim_time*90*1-90)*-0.15"]
},
"right_paw": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*2", 0, 0]
},
"left_leg": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*-2", 0, 0],
"position": [0, "0-math.sin(q.anim_time*90*1-90)*0.01", "0-math.sin(q.anim_time*90*1-90)*-0.15"]
},
"left_paw": {
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*2", 0, 0]
},
"tail": {
"rotation": ["-0+math.sin(q.anim_time*90*1-60)*-5", "-0+math.sin(q.anim_time*90*0.5-120)*15", 0]
},
"pie": {
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*-1", 0, 0]
}
}
},
@@ -41,22 +88,22 @@
"bones": {
"right_eye": {
"position": {
"0.0": [0, 0, 0.25],
"0.1667": {"pre": [0, 0, 0.25], "post": [0, 0, 0]}
"0.0": [0.25, 0, 0],
"0.1667": {"pre": [0.25, 0, 0], "post": [0, 0, 0]}
},
"scale": {
"0.0": [1, 1, 0.5],
"0.1667": {"pre": [1, 1, 0.5], "post": [1, 1, 1]}
"0.0": [0.5, 1, 1],
"0.1667": {"pre": [0.5, 1, 1], "post": [1, 1, 1]}
}
},
"left_eye": {
"position": {
"0.0": [0, 0, 0.25],
"0.1667": {"pre": [0, 0, 0.25], "post": [0, 0, 0]}
"0.0": [-0.25, 0, 0],
"0.1667": {"pre": [-0.25, 0, 0], "post": [0, 0, 0]}
},
"scale": {
"0.0": [1, 1, 0.5],
"0.1667": {"pre": [1, 1, 0.5], "post": [1, 1, 1]}
"0.0": [0.5, 1, 1],
"0.1667": {"pre": [0.5, 1, 1], "post": [1, 1, 1]}
}
}
}
@@ -98,7 +145,7 @@
"rotation": [0, 35, 0],
"position": [0, 4, 0]
},
"body": {
"torso": {
"rotation": [10.1577, -2.55868, -7.05239]
},
"neck": {
@@ -150,9 +197,237 @@
}
},
"animation.appletun.cry": {
"animation_length": 1.2,
"animation_length": 3,
"bones": {
"neck": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [-1.53, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [-10, 0, 0],
"lerp_mode": "catmullrom"
},
"1.9167": {
"post": [-13.5, 0, 0],
"lerp_mode": "catmullrom"
},
"2.25": {
"post": [-3.22, 0, 0],
"lerp_mode": "catmullrom"
},
"2.5": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"head": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [-1.94, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [-15, 0, 0],
"lerp_mode": "catmullrom"
},
"1.7083": {
"post": [-20, 0, 0],
"lerp_mode": "catmullrom"
},
"2.25": {
"post": [-3.07, 0, 0],
"lerp_mode": "catmullrom"
},
"2.5": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"jaw": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [57.5, 0, 0],
"lerp_mode": "catmullrom"
},
"1.3333": {
"post": [25, 0, 0],
"lerp_mode": "catmullrom"
},
"2.0": {
"post": [25, 0, 0],
"lerp_mode": "catmullrom"
},
"2.5": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"left_leaf": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [0, 0, -5.59],
"lerp_mode": "catmullrom"
},
"0.5417": {
"post": [0, 0, -25],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [0, 0, 6],
"lerp_mode": "catmullrom"
},
"0.9583": {
"post": [0, 0, -25],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [0, 0, 3],
"lerp_mode": "catmullrom"
},
"1.875": {
"post": [0, 0, -2.25],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"left_leaf_bend": {
"rotation": {
"0.125": {
"pre": [0, 0, 0],
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [0, 0, -5.59],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [0, 0, -25],
"lerp_mode": "catmullrom"
},
"0.875": {
"post": [0, 0, 6],
"lerp_mode": "catmullrom"
},
"1.0833": {
"post": [0, 0, -25],
"lerp_mode": "catmullrom"
},
"1.2917": {
"post": [0, 0, 3],
"lerp_mode": "catmullrom"
},
"2.0": {
"post": [0, 0, -2.25],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"right_leaf": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [0, 0, 5.59],
"lerp_mode": "catmullrom"
},
"0.5417": {
"post": [0, 0, 25],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [0, 0, -6],
"lerp_mode": "catmullrom"
},
"0.9583": {
"post": [0, 0, 25],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [0, 0, -3],
"lerp_mode": "catmullrom"
},
"1.875": {
"post": [0, 0, 2.25],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"right_leaf_bend": {
"rotation": {
"0.125": {
"pre": [0, 0, 0],
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [0, 0, 5.59],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [0, 0, 25],
"lerp_mode": "catmullrom"
},
"0.875": {
"post": [0, 0, -6],
"lerp_mode": "catmullrom"
},
"1.0833": {
"post": [0, 0, 25],
"lerp_mode": "catmullrom"
},
"1.2917": {
"post": [0, 0, -3],
"lerp_mode": "catmullrom"
},
"2.0": {
"post": [0, 0, 2.25],
"lerp_mode": "catmullrom"
},
"2.5833": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
}
},
"sound_effects": {
"0.04": {
"0.0": {
"effect": "pokemon.appletun.cry"
}
}
@@ -5,25 +5,43 @@
"loop": true,
"bones": {
"eye_left": {
"rotation": [5, 0, 12.5]
"rotation": ["5+math.sin(q.anim_time*90*2-90)*2", 0, 12.5]
},
"eye_right": {
"rotation": [7.5, 0, -15]
"rotation": ["5+math.sin(q.anim_time*90*2-90)*2", 0, -12.5]
},
"eye_left2": {
"rotation": [2.5, 0, 0]
"rotation": ["2.5+math.sin(q.anim_time*90*2-120)*0.5", 0, 0]
},
"stem": {
"rotation": [-2.5, 0, 0]
"rotation": ["-2.5+math.sin(q.anim_time*90*2-120)*1", 0, 0]
},
"stem_end": {
"rotation": [-5, 0, 0]
"rotation": ["-5+math.sin(q.anim_time*90*2-180)*4", 0, 0]
},
"stem_bend": {
"rotation": [-5, 0, 0]
"rotation": ["-5+math.sin(q.anim_time*90*2-150)*2", 0, 0]
},
"tail": {
"rotation": [0, 12.5, 0]
"rotation": ["-0+math.sin(q.anim_time*90*2-60)*-1", "12.5+math.sin(q.anim_time*90*1-120)*1", 0]
},
"apple_top": {
"rotation": ["-0+math.sin(q.anim_time*90*2-60)*0.25", 0, 0]
},
"eye_right2": {
"rotation": ["2.5+math.sin(q.anim_time*90*2-120)*0.5", 0, 0]
},
"tail2": {
"rotation": ["-0+math.sin(q.anim_time*90*2-90)*1", 0, 0]
},
"tail_leaves": {
"rotation": [0, "-0+math.sin(q.anim_time*90*1-30)*3", 0]
},
"bottom": {
"scale": ["1-math.sin(q.anim_time*90*2)*-0.01", 1, "1-math.sin(q.anim_time*90*2)*-0.01"]
},
"apple": {
"rotation": ["-0+math.sin(q.anim_time*90*2-30)*0.5", 0, "0-math.sin(q.anim_time*90*1-60)*0.5"]
}
}
},
@@ -33,40 +51,186 @@
"pupil_left": {
"scale": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [1, 1, 1]}
"0.1667": {
"pre": [0, 0, 0],
"post": [1, 1, 1]
}
}
},
"pupil_right": {
"scale": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [1, 1, 1]}
"0.1667": {
"pre": [0, 0, 0],
"post": [1, 1, 1]
}
}
},
"eye_right_closed": {
"position": {
"0.0": [0, 0, -0.02],
"0.1667": {"pre": [0, 0, -0.02], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
},
"eye_right_closed2": {
"position": {
"0.0": [0, 0, -0.02],
"0.1667": {"pre": [0, 0, -0.02], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
},
"eye_left_closed2": {
"position": {
"0.0": [0, 0, -0.02],
"0.1667": {"pre": [0, 0, -0.02], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
},
"eye_left_closed": {
"position": {
"0.0": [0, 0, -0.02],
"0.1667": {"pre": [0, 0, -0.02], "post": [0, 0, 0]}
"0.1667": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
}
}
},
"animation.dipplin.cry": {
"animation_length": 1.5,
"bones": {
"pupil_left": {
"scale": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [1, 1, 1]
}
}
},
"pupil_right": {
"scale": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [1, 1, 1]
}
}
},
"tail": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.1667": {
"post": ["2.5-math.sin(q.anim_time*90*50-180)*-0.5", 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [-2.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [-2.5, 0, 0],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"eye_right_closed": {
"position": {
"0.0": [0, 0, -0.02],
"0.25": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
},
"eye_right_closed2": {
"position": {
"0.0": [0, 0, -0.02],
"0.25": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
},
"eye_left_closed2": {
"position": {
"0.0": [0, 0, -0.02],
"0.25": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
},
"eye_left_closed": {
"position": {
"0.0": [0, 0, -0.02],
"0.25": {
"pre": [0, 0, -0.02],
"post": [0, 0, 0]
}
}
},
"apple": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.1667": {
"post": ["-2.5+math.sin(q.anim_time*90*50-180)*-0.5", 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": [2.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [2.5, 0, 0],
"lerp_mode": "catmullrom"
},
"1.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
}
},
"sound_effects": {
"0.0": {
"effect": "pokemon.dipplin.cry"
}
}
}
}
}
@@ -4,41 +4,50 @@
"animation.hydrapple.ground_idle": {
"loop": true,
"bones": {
"bottom": {
"scale": ["1-math.sin(q.anim_time*90*2)*-0.01", 1, "1-math.sin(q.anim_time*90*2)*-0.01"]
},
"apple_top": {
"rotation": ["-0+math.sin(q.anim_time*90*2-30)*0.5", 0, "0-math.sin(q.anim_time*90*1-60)*0.5"]
},
"main_head_neck_base": {
"rotation": [-7.5, 0, 0]
"rotation": ["-7.5+math.sin(q.anim_time*90*2-30)*0.5", 0, "0-math.sin(q.anim_time*90*1-60)*1"]
},
"main_head_neck_base_bend": {
"rotation": [-19.95491, 3.04775, 8.13208]
"rotation": ["-19.954911595+math.sin(q.anim_time*90*2-60)*0.5", 3.04775, "8.132083803-math.sin(q.anim_time*90*1-90)*0.5"]
},
"main_head_neck_mid": {
"rotation": [-10, 0, 0]
"rotation": ["-10+math.sin(q.anim_time*90*2-90)*0.5", 0, "0-math.sin(q.anim_time*90*1-120)*1"]
},
"main_head_neck_mid_bend": {
"rotation": [29.40842, 6.21271, -10.86815]
"rotation": ["29.408423889+math.sin(q.anim_time*90*2-120)*1", 6.21271, "-10.868150118-math.sin(q.anim_time*90*1-150)*0.5"]
},
"main_head_neck_end": {
"rotation": [27.5, 0, 0]
"rotation": ["27.5+math.sin(q.anim_time*90*2-150)*1", 0, "0-math.sin(q.anim_time*90*1-180)*1"]
},
"main_head_neck_end_bend": {
"rotation": [35, 0, 0]
"rotation": ["35+math.sin(q.anim_time*90*2-180)*1", 0, "0-math.sin(q.anim_time*90*1-210)*1"]
},
"main_head_neck_tip": {
"rotation": [42.39121, -3.37562, 3.69066]
"rotation": ["42.391212146+math.sin(q.anim_time*90*2-210)*1", -3.37562, "3.690660194-math.sin(q.anim_time*90*1-240)*1"]
},
"main_head_head": {
"rotation": [0, 2.5, -2.5]
"rotation": ["-0+math.sin(q.anim_time*90*2-210)*-2", "2.5+math.sin(q.anim_time*90*1-60)*1.5", "-2.5-math.sin(q.anim_time*90*1-300)*1"]
},
"main_head_eye_left": {
"rotation": [18.53366, -34.044, -64.8734]
"rotation": ["18.533664677+math.sin(q.anim_time*90*2-30)*1", -34.044, -64.8734]
},
"main_head_eye_left_bend": {
"rotation": [-22.5, 0, 0]
"rotation": ["-22.5+math.sin(q.anim_time*90*2-60)*1", 0, 0]
},
"main_head_eye_right": {
"rotation": [18.53366, 34.044, 64.8734]
"rotation": ["18.533664677+math.sin(q.anim_time*90*2-30)*1", 34.044, 64.8734]
},
"main_head_eye_right_bend": {
"rotation": [-22.5, 0, 0]
"rotation": ["-22.5+math.sin(q.anim_time*90*2-60)*1", 0, 0]
},
"main_head_tip": {
"position": [0, 0, -0.75]
},
"front_right_head_neck_base": {
"scale": 0
@@ -53,10 +62,10 @@
"scale": 0
},
"tail_right_base": {
"rotation": [-7.5, 10, 0]
"rotation": ["-7.5+math.sin(q.anim_time*90*2-60)*-1", "10+math.sin(q.anim_time*90*1-120)*1", 0]
},
"tail_right_bend": {
"rotation": [-37.5, 0, 0]
"rotation": ["-37.5+math.sin(q.anim_time*90*2-90)*1", 0, 0]
},
"tail_right_end": {
"rotation": [32.5, 0, 0]
@@ -64,17 +73,115 @@
"tail_right_tip": {
"rotation": [15, 0, 0]
},
"tail_leaves_right": {
"rotation": [0, "-0+math.sin(q.anim_time*90*1-30)*3", 0]
},
"tail_left_base": {
"rotation": [-7.5, -10, 0]
"rotation": ["-7.5+math.sin(q.anim_time*90*2-60)*-1", "-10-math.sin(q.anim_time*90*1-120)*1", 0]
},
"tail_left_bend": {
"rotation": [-37.5, 0, 0]
"rotation": ["-37.5+math.sin(q.anim_time*90*2-90)*1", 0, 0]
},
"tail_left_end": {
"rotation": [32.5, 0, 0]
},
"tail_left_tip": {
"rotation": [15, 0, 0]
},
"tail_leaves_left": {
"rotation": [0, "0-math.sin(q.anim_time*90*1-30)*3", 0]
}
}
},
"animation.hydrapple.battle_idle": {
"loop": true,
"bones": {
"bottom": {
"scale": ["1-math.sin(q.anim_time*90*2)*-0.01", 1, "1-math.sin(q.anim_time*90*2)*-0.01"]
},
"apple_top": {
"rotation": ["-0+math.sin(q.anim_time*90*2-30)*0.75", 0, "0-math.sin(q.anim_time*90*1-60)*0.75"]
},
"main_head_neck_base": {
"rotation": ["-7.5+math.sin(q.anim_time*90*2-30)*1", 0, "0-math.sin(q.anim_time*90*1-60)*1"]
},
"main_head_neck_base_bend": {
"rotation": ["-32.4549+math.sin(q.anim_time*90*2-60)*1", 3.04775, "8.1321-math.sin(q.anim_time*90*1-90)*2"]
},
"main_head_neck_mid": {
"rotation": ["-20+math.sin(q.anim_time*90*2-90)*1", 0, "-math.sin(q.anim_time*90*1-120)*2"]
},
"main_head_neck_mid_bend": {
"rotation": ["34.4084+math.sin(q.anim_time*90*2-120)*2", 6.21271, "-10.8682-math.sin(q.anim_time*90*1-150)*2"]
},
"main_head_neck_end": {
"rotation": ["35+math.sin(q.anim_time*90*2-150)*2", 0, "-math.sin(q.anim_time*90*1-180)*2"]
},
"main_head_neck_end_bend": {
"rotation": ["40+math.sin(q.anim_time*90*2-180)*2", 0, "-math.sin(q.anim_time*90*1-210)*2"]
},
"main_head_neck_tip": {
"rotation": ["47.3912+math.sin(q.anim_time*90*2-210)*2", -3.37562, "3.6907-math.sin(q.anim_time*90*1-240)*2"]
},
"main_head_head": {
"rotation": ["7.5+math.sin(q.anim_time*90*2-210)*-4", "2.5+math.sin(q.anim_time*90*1-60)*3", "-2.5-math.sin(q.anim_time*90*1-300)*2"]
},
"main_head_eye_left": {
"rotation": ["18.533664677+math.sin(q.anim_time*90*2-30)*2", -34.044, -64.8734]
},
"main_head_eye_left_bend": {
"rotation": ["-22.5+math.sin(q.anim_time*90*2-60)*2", 0, 0]
},
"main_head_eye_right": {
"rotation": ["18.533664677+math.sin(q.anim_time*90*2-30)*2", 34.044, 64.8734]
},
"main_head_eye_right_bend": {
"rotation": ["-22.5+math.sin(q.anim_time*90*2-60)*2", 0, 0]
},
"main_head_tip": {
"position": [0, 0, -0.75]
},
"front_right_head_neck_base": {
"scale": 0
},
"front_left_head_neck_base": {
"scale": 0
},
"back_left_head_neck_base": {
"scale": 0
},
"back_right_head_neck_base": {
"scale": 0
},
"tail_right_base": {
"rotation": ["-7.5+math.sin(q.anim_time*90*2-60)*-1", "10+math.sin(q.anim_time*90*1-120)*1", 0]
},
"tail_right_bend": {
"rotation": ["-37.5+math.sin(q.anim_time*90*2-90)*1", 0, 0]
},
"tail_right_end": {
"rotation": [32.5, 0, 0]
},
"tail_right_tip": {
"rotation": [15, 0, 0]
},
"tail_leaves_right": {
"rotation": [0, "-0+math.sin(q.anim_time*90*1-30)*3", 0]
},
"tail_left_base": {
"rotation": ["-7.5+math.sin(q.anim_time*90*2-60)*-1", "-10-math.sin(q.anim_time*90*1-120)*1", 0]
},
"tail_left_bend": {
"rotation": ["-37.5+math.sin(q.anim_time*90*2-90)*1", 0, 0]
},
"tail_left_end": {
"rotation": [32.5, 0, 0]
},
"tail_left_tip": {
"rotation": [15, 0, 0]
},
"tail_leaves_left": {
"rotation": [0, "0-math.sin(q.anim_time*90*1-30)*3", 0]
}
}
},
@@ -521,9 +628,333 @@
}
},
"animation.hydrapple.cry": {
"animation_length": 1.2,
"animation_length": 2.1667,
"bones": {
"main_head_neck_base": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.0833": {
"post": [1.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.3333": {
"post": [-2, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5833": {
"post": [1, 0, 0],
"lerp_mode": "catmullrom"
},
"0.7917": {
"post": [1, 0, 0],
"lerp_mode": "catmullrom"
},
"1.0833": {
"post": [-1, 0, 0],
"lerp_mode": "catmullrom"
},
"1.4583": {
"post": [-5, 0, 0],
"lerp_mode": "catmullrom"
},
"1.7083": {
"post": [-1.25, 0, 0],
"lerp_mode": "catmullrom"
},
"2.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"main_head_neck_base_bend": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.1667": {
"post": [1.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.4167": {
"post": [-2, 0, 0],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [1, 0, 0],
"lerp_mode": "catmullrom"
},
"0.875": {
"post": [1, 0, 0],
"lerp_mode": "catmullrom"
},
"1.1667": {
"post": [-1, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5833": {
"post": [-2, 0, 0],
"lerp_mode": "catmullrom"
},
"1.875": {
"post": [-1.25, 0, 0],
"lerp_mode": "catmullrom"
},
"2.125": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"main_head_head": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.125": {
"post": [7.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.3333": {
"post": ["-15+math.sin(q.anim_time*90*50-180)*-1", 0, 0],
"lerp_mode": "catmullrom"
},
"0.625": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.8333": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.125": {
"post": [-8, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5": {
"post": ["-12+math.sin(q.anim_time*90*50-180)*-1", 0, 0],
"lerp_mode": "catmullrom"
},
"1.75": {
"post": [-3.25, 0, 0],
"lerp_mode": "catmullrom"
},
"2.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"main_head_eye_left_closed": {
"position": {
"0.0": [0, 0, -0.03],
"0.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
},
"0.8333": {
"pre": [0, 0, 0],
"post": [0, 0, -0.03]
},
"1.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
}
}
},
"main_head_eye_left_bend_closed": {
"position": {
"0.0": [0, 0, -0.03],
"0.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
},
"0.8333": {
"pre": [0, 0, 0],
"post": [0, 0, -0.03]
},
"1.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
}
}
},
"main_head_eye_right_closed": {
"position": {
"0.0": [0, 0, -0.03],
"0.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
},
"0.8333": {
"pre": [0, 0, 0],
"post": [0, 0, -0.03]
},
"1.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
}
}
},
"main_head_eye_right_bend_closed": {
"position": {
"0.0": [0, 0, -0.03],
"0.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
},
"0.8333": {
"pre": [0, 0, 0],
"post": [0, 0, -0.03]
},
"1.1667": {
"pre": [0, 0, -0.03],
"post": [0, 0, 0]
}
}
},
"main_head_jaw": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": [40, 0, 0],
"lerp_mode": "catmullrom"
},
"0.7917": {
"post": [10, 0, 0],
"lerp_mode": "catmullrom"
},
"1.25": {
"post": [10, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5": {
"post": [40, 0, 0],
"lerp_mode": "catmullrom"
},
"1.9167": {
"post": [4.3, 0, 0],
"lerp_mode": "catmullrom"
},
"2.0833": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"main_head_tongue": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.5": {
"post": ["-17.5+math.sin(q.anim_time*90*50-210)*-2", 0, 0],
"lerp_mode": "catmullrom"
},
"0.7083": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.2083": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5833": {
"post": [-12.5, 0, 0],
"lerp_mode": "catmullrom"
},
"2.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"main_head_tongue_bend": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.1667": {
"post": [1.43, 0, 0],
"lerp_mode": "catmullrom"
},
"0.375": {
"post": ["-12.5+math.sin(q.anim_time*90*50-240)*-2", 0, 0],
"lerp_mode": "catmullrom"
},
"0.7083": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"1.2917": {
"post": [-2.71, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5": {
"post": ["-15+math.sin(q.anim_time*90*50-240)*-2", 0, 0],
"lerp_mode": "catmullrom"
},
"1.9583": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"main_head_tip": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.125": {
"post": [12.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.4167": {
"post": [2.5, 0, 0],
"lerp_mode": "catmullrom"
},
"0.75": {
"post": [10, 0, 0],
"lerp_mode": "catmullrom"
},
"1.2917": {
"post": [22.5, 0, 0],
"lerp_mode": "catmullrom"
},
"1.5417": {
"post": [-5, 0, 0],
"lerp_mode": "catmullrom"
},
"1.8333": {
"post": [35, 0, 0],
"lerp_mode": "catmullrom"
},
"2.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
},
"position": {
"0.0": [0, 0, 0],
"0.25": [0, 0, 0.75],
"1.8333": [0, 0, 0.75],
"2.0": [0, 0, 0]
}
}
},
"sound_effects": {
"0.04": {
"0.0417": {
"effect": "pokemon.hydrapple.cry"
}
}
@@ -226,6 +226,14 @@
{"origin": [3.51, 36.5, -2], "size": [0, 2, 2], "uv": [0, -2]}
]
},
{
"name": "locator_eye_left",
"parent": "eye_left",
"pivot": [3.51, 37.5, -1],
"locators": {
"eye2": [3.51, 37.5, -1]
}
},
{
"name": "pupil_left",
"parent": "eye_left",
@@ -234,6 +242,14 @@
{"origin": [3.52, 37.5, -2], "size": [0, 1, 1], "uv": [8, -1]}
]
},
{
"name": "locator_eye_right",
"parent": "pupil_left",
"pivot": [-3.51, 37.5, -1],
"locators": {
"eye1": [-3.51, 37.5, -1]
}
},
{
"name": "eyelid_left",
"parent": "eye_left",
@@ -18,14 +18,19 @@
{
"name": "body",
"parent": "appletun",
"pivot": [0, 9.25, 0],
"pivot": [0, 9.25, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 4.25, 0],
"cubes": [
{"origin": [-7.5, 1.35, -7.75], "size": [15, 5, 15], "uv": [0, 31]}
]
},
{
"name": "neck",
"parent": "body",
"parent": "torso",
"pivot": [0, 1.5, -7.75],
"cubes": [
{"origin": [-2.5, 1.5, -10.75], "size": [5, 4, 3], "uv": [43, 62]}
@@ -138,93 +143,9 @@
{"origin": [-1.5, 1.5, -17.75], "size": [3, 1, 2], "uv": [54, 39]}
]
},
{
"name": "left_front_leg",
"parent": "body",
"pivot": [8.75, 5.5, -3.5],
"rotation": [-7.5, 0, 0],
"cubes": [
{"origin": [7, 1.25, -5.5], "size": [3, 5, 4], "uv": [0, 31]}
]
},
{
"name": "left_front_paw",
"parent": "left_front_leg",
"pivot": [8, 1.75, -2.25],
"rotation": [7.5, 0, 0],
"cubes": [
{"origin": [7, 0.25, -5], "size": [2, 2, 3], "uv": [10, 71]}
]
},
{
"name": "left_front_paw_bend",
"parent": "left_front_paw",
"pivot": [8, 2.25, -5],
"cubes": [
{"origin": [7, 0.25, -7], "size": [2, 2, 2], "inflate": 0.01, "uv": [65, 62]}
]
},
{
"name": "right_front_leg",
"parent": "body",
"pivot": [-8.75, 5.5, -3.5],
"rotation": [-7.5, 0, 0],
"cubes": [
{"origin": [-10, 1.25, -5.5], "size": [3, 5, 4], "uv": [0, 8]}
]
},
{
"name": "right_front_paw",
"parent": "right_front_leg",
"pivot": [-8, 1.75, -2.25],
"rotation": [7.5, 0, 0],
"cubes": [
{"origin": [-9, 0.25, -5], "size": [2, 2, 3], "uv": [0, 71]}
]
},
{
"name": "right_front_paw_bend",
"parent": "right_front_paw",
"pivot": [-8, 2.25, -5],
"cubes": [
{"origin": [-9, 0.25, -7], "size": [2, 2, 2], "inflate": 0.01, "uv": [48, 42]}
]
},
{
"name": "right_leg",
"parent": "body",
"pivot": [-7.25, 5.25, 5.75],
"cubes": [
{"origin": [-10, 1, 2.25], "size": [4, 6, 6], "uv": [20, 59]}
]
},
{
"name": "right_paw",
"parent": "right_leg",
"pivot": [-8, 1, 5.75],
"cubes": [
{"origin": [-9.5, 0, 3], "size": [3, 2, 4], "uv": [58, 66]}
]
},
{
"name": "left_leg",
"parent": "body",
"pivot": [7.25, 5.25, 5.75],
"cubes": [
{"origin": [6, 1, 2.25], "size": [4, 6, 6], "uv": [0, 59]}
]
},
{
"name": "left_paw",
"parent": "left_leg",
"pivot": [8, 1, 5.75],
"cubes": [
{"origin": [6.5, 0, 3], "size": [3, 2, 4], "uv": [0, 40]}
]
},
{
"name": "tail",
"parent": "body",
"parent": "torso",
"pivot": [0, 2.75, 7.25],
"cubes": [
{"origin": [-2.5, 1.25, 7.25], "size": [5, 5, 3], "uv": [0, 0]}
@@ -248,7 +169,7 @@
},
{
"name": "pie",
"parent": "body",
"parent": "torso",
"pivot": [0, 6.25, 0],
"cubes": [
{"origin": [-9, 6.25, -9], "size": [18, 13, 18], "uv": [0, 0]}
@@ -325,6 +246,90 @@
"cubes": [
{"origin": [-8.5, 15, 0], "size": [22, 5, 3], "pivot": [2.5, 18.25, 1.5], "rotation": [0, 0, -2.5], "uv": [50, 51]}
]
},
{
"name": "left_front_leg",
"parent": "body",
"pivot": [8.75, 5.5, -3.5],
"rotation": [-7.5, 0, 0],
"cubes": [
{"origin": [7, 1.25, -5.5], "size": [3, 5, 4], "uv": [0, 31]}
]
},
{
"name": "left_front_paw",
"parent": "left_front_leg",
"pivot": [8, 1.75, -2.25],
"rotation": [7.5, 0, 0],
"cubes": [
{"origin": [7, 0.25, -5], "size": [2, 2, 3], "uv": [10, 71]}
]
},
{
"name": "left_front_paw_bend",
"parent": "left_front_paw",
"pivot": [8, 0.25, -5],
"cubes": [
{"origin": [7, 0.25, -7], "size": [2, 2, 2], "inflate": 0.01, "uv": [65, 62]}
]
},
{
"name": "right_front_leg",
"parent": "body",
"pivot": [-8.75, 5.5, -3.5],
"rotation": [-7.5, 0, 0],
"cubes": [
{"origin": [-10, 1.25, -5.5], "size": [3, 5, 4], "uv": [0, 8]}
]
},
{
"name": "right_front_paw",
"parent": "right_front_leg",
"pivot": [-8, 1.75, -2.25],
"rotation": [7.5, 0, 0],
"cubes": [
{"origin": [-9, 0.25, -5], "size": [2, 2, 3], "uv": [0, 71]}
]
},
{
"name": "right_front_paw_bend",
"parent": "right_front_paw",
"pivot": [-8, 0.25, -5],
"cubes": [
{"origin": [-9, 0.25, -7], "size": [2, 2, 2], "inflate": 0.01, "uv": [48, 42]}
]
},
{
"name": "right_leg",
"parent": "body",
"pivot": [-7.25, 5.25, 5.75],
"cubes": [
{"origin": [-10, 1, 2.25], "size": [4, 6, 6], "uv": [20, 59]}
]
},
{
"name": "right_paw",
"parent": "right_leg",
"pivot": [-8, 1, 5.75],
"cubes": [
{"origin": [-9.5, 0, 3], "size": [3, 2, 4], "uv": [58, 66]}
]
},
{
"name": "left_leg",
"parent": "body",
"pivot": [7.25, 5.25, 5.75],
"cubes": [
{"origin": [6, 1, 2.25], "size": [4, 6, 6], "uv": [0, 59]}
]
},
{
"name": "left_paw",
"parent": "left_leg",
"pivot": [8, 1, 5.75],
"cubes": [
{"origin": [6.5, 0, 3], "size": [3, 2, 4], "uv": [0, 40]}
]
}
]
}
@@ -18,17 +18,20 @@
{
"name": "body",
"parent": "dipplin",
"pivot": [0, 3, 0],
"pivot": [0, 3, 0]
},
{
"name": "apple",
"parent": "body",
"pivot": [0, 2, 0],
"cubes": [
{"origin": [-4, 2, -4], "size": [8, 6, 8], "uv": [0, 10]},
{"origin": [-3, 2.5, 4], "size": [2, 2, 0], "inflate": 0.01, "uv": [0, 42]},
{"origin": [-3, 0.01, -3], "size": [6, 2, 6], "uv": [24, 4]},
{"origin": [-5, 0, -5], "size": [10, 0, 10], "uv": [0, 0]}
{"origin": [-3, 2.5, 4], "size": [2, 2, 0], "inflate": 0.01, "uv": [0, 42]}
]
},
{
"name": "apple_top",
"parent": "body",
"parent": "apple",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-4, 5, -4.5], "size": [8, 1, 0], "uv": [24, 13]},
@@ -45,7 +48,7 @@
},
{
"name": "worminside",
"parent": "body",
"parent": "apple",
"pivot": [0, 6.25, 0.75]
},
{
@@ -235,6 +238,15 @@
{"origin": [0.5, -1.5, 5.75], "size": [1, 0, 2], "pivot": [1.5, -1.5, 5.75], "rotation": [0, -32.5, 0], "uv": [6, 0]},
{"origin": [1.5, -1.5, 5.75], "size": [1, 0, 2], "pivot": [1.5, -1.5, 5.75], "rotation": [0, 35, 0], "uv": [4, 0]}
]
},
{
"name": "bottom",
"parent": "body",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-3, 0.01, -3], "size": [6, 2, 6], "uv": [24, 4]},
{"origin": [-5, 0, -5], "size": [10, 0, 10], "uv": [0, 0]}
]
}
]
}
@@ -325,7 +325,12 @@
"name": "head",
"parent": "torso2",
"pivot": [0, 40, 3],
"rotation": [47.5, 0, 0],
"rotation": [47.5, 0, 0]
},
{
"name": "head_ai",
"parent": "head",
"pivot": [0, 40, 0],
"cubes": [
{"origin": [-2.5, 41, 0.99], "size": [5, 3, 1], "uv": [0, 0]},
{"origin": [0.5, 41, 1.98], "size": [2, 3, 2], "inflate": 0.01, "uv": [12, 0]},
@@ -334,7 +339,7 @@
},
{
"name": "locator_item",
"parent": "head",
"parent": "head_ai",
"pivot": [-0.25, 42.75, 3.5],
"rotation": [0, -135, 90],
"locators": {
@@ -343,7 +348,7 @@
},
{
"name": "head_wheel",
"parent": "head",
"parent": "head_ai",
"pivot": [0, 40.25, 2],
"cubes": [
{"origin": [-0.5, 38.75, 1.85], "size": [1, 2, 2], "inflate": -0.15, "uv": [23, 14]}
@@ -351,7 +356,7 @@
},
{
"name": "head2",
"parent": "head",
"parent": "head_ai",
"pivot": [0, 41, 2],
"cubes": [
{"origin": [-2.5, 41, -1], "size": [5, 3, 2], "uv": [24, 0]},
@@ -621,7 +626,7 @@
]
},
{
"name": "locator_seat_1",
"name": "seat_1_locator",
"parent": "torso_back",
"pivot": [0, 11, 14],
"locators": {
@@ -5,6 +5,7 @@
"profileTranslation": [0.0, 0.35, 0],
"rootBone": "diglett",
"animations": {
"faint": "q.bedrock_primary('diglett', 'faint', q.curve('one'))",
"cry": "q.bedrock_stateful('diglett', 'cry')",
"recoil": "q.bedrock_stateful('diglett', 'recoil')",
"physical": "q.bedrock_primary('diglett', 'physical', q.curve('symmetrical'))"
@@ -5,6 +5,7 @@
"profileTranslation": [0.0, 0.29, 0],
"rootBone": "dugtrio",
"animations": {
"faint": "q.bedrock_primary('dugtrio', 'faint', q.curve('one'))",
"cry": "q.bedrock_stateful('dugtrio', 'cry')",
"recoil": "q.bedrock_stateful('dugtrio', 'recoil')",
"physical": "q.bedrock_primary('dugtrio', 'physical', q.curve('symmetrical'))"
@@ -16,8 +16,7 @@
"seat_1_reverse": [0, 0.4, 0]
},
"animations": {
"cry": "q.bedrock_stateful('mantine', 'cry')",
"recoil": "q.bedrock_stateful('mantine', 'recoil')"
"cry": "q.bedrock_stateful('mantine', 'cry')"
},
"poses": {
"jump": {
@@ -41,16 +41,10 @@
],
"animations": [
"q.look('head')",
"q.bedrock('sableye', 'ground_idle')"
"q.bedrock('sableye', 'shoulder_left')"
],
"quirks": [
"q.bedrock_quirk('sableye', 'blink')"
],
"transformedParts": [
{
"part": "body",
"position": [5, 0, 0]
}
]
},
"shoulder_right": {
@@ -60,16 +54,10 @@
],
"animations": [
"q.look('head')",
"q.bedrock('sableye', 'ground_idle')"
"q.bedrock('sableye', 'shoulder_right')"
],
"quirks": [
"q.bedrock_quirk('sableye', 'blink')"
],
"transformedParts": [
{
"part": "body",
"position": [-5, 0, 0]
}
]
}
}
@@ -13,7 +13,9 @@
"isBattle": true,
"animations": [
"q.look('head')",
"q.bedrock('lucario', 'battle_idle')"
"q.bedrock('lucario', 'battle_idle')",
"q.bedrock('lucario', 'battle_idle_aura_left')",
"q.bedrock('lucario', 'battle_idle_aura_right')"
],
"quirks": ["q.bedrock_quirk('lucario', 'blink')", "q.bedrock_quirk('lucario', 'battle_quirk')"]
},
@@ -5,8 +5,7 @@
"profileTranslation": [-0.01, 0.52, 0],
"rootBone": "mantyke",
"animations": {
"cry": "q.bedrock_stateful('mantyke', 'cry')",
"recoil": "q.bedrock_stateful('mantyke', 'recoil')"
"cry": "q.bedrock_stateful('mantyke', 'cry')"
},
"poses": {
"standing": {
@@ -16,9 +16,8 @@
"PORTRAIT",
"PROFILE"
],
"isBattle": true,
"animations": [
"q.look('head')",
"q.look('head_ai', 1, 1, 25, -25, 40, -40)",
"q.bedrock('lycanroc_dusk', 'ground_idle')"
]
},
@@ -28,7 +27,7 @@
"SWIM"
],
"animations": [
"q.look('head')",
"q.look('head_ai', 1, 1, 25, -25, 40, -40)",
"q.bedrock('lycanroc_dusk', 'ground_idle')",
"q.quadruped_walk(1, 1, 'leg_front_left', 'leg_front_right', 'leg_back_left', 'leg_back_right')"
]
@@ -16,9 +16,8 @@
"PORTRAIT",
"PROFILE"
],
"isBattle": true,
"animations": [
"q.look('head')",
"q.look('head_ai', 1, 1, 25, -25, 40, -40)",
"q.bedrock('lycanroc_midday', 'ground_idle')"
]
},
@@ -28,7 +27,7 @@
"SWIM"
],
"animations": [
"q.look('head')",
"q.look('head_ai', 1, 1, 25, -25, 40, -40)",
"q.bedrock('lycanroc_midday', 'ground_idle')",
"q.quadruped_walk(1, 1, 'leg_front_left', 'leg_front_right', 'leg_back_left', 'leg_back_right')"
]
@@ -16,9 +16,8 @@
"PORTRAIT",
"PROFILE"
],
"isBattle": true,
"animations": [
"q.look('head')",
"q.look('head_ai')",
"q.bedrock('lycanroc_midnight', 'ground_idle')"
]
},
@@ -28,7 +27,7 @@
"SWIM"
],
"animations": [
"q.look('head')",
"q.look('head_ai')",
"q.bedrock('lycanroc_midnight', 'ground_idle')",
"q.biped_walk(1, 1, 'leg_left', 'leg_right')"
]
@@ -65,6 +65,17 @@
"quirks": [
"q.bedrock_quirk('flapple', 'blink')"
]
},
"sleep": {
"poseTypes": [
"SLEEP"
],
"animations": [
"q.bedrock('flapple', 'closed_test')"
],
"quirks": [
],
"namedAnimations": {"cry": "q.bedrock_stateful('dummy', 'cry')"}
}
}
}
@@ -4,6 +4,9 @@
"profileScale": 0.68,
"profileTranslation": [0.00, 0.63, 0],
"rootBone": "appletun",
"animations": {
"cry": "q.bedrock_stateful('appletun', 'cry')"
},
"poses": {
"battle-standing": {
"poseTypes": ["STAND"],
@@ -100,6 +100,13 @@
],
"transformTicks": 5,
"transformToTicks": 5
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('duraludon', 'sleep')"]
}
}
}
@@ -14,7 +14,6 @@
],
"animations": {
"cry": "q.bedrock_stateful('quaxly', 'cry')",
"recoil": "q.bedrock_stateful('quaxly', 'recoil')",
"faint": "q.bedrock_primary('quaxly', 'faint', q.curve('one'))"
},
"poses": {
@@ -18,8 +18,7 @@
"poseTypes": ["WALK"],
"animations": [
"q.look('head')",
"q.bedrock('kingambit', 'ground_idle')",
"q.biped_walk(1, 1, 'leg_left', 'leg_right')"
"q.bedrock('kingambit', 'ground_idle')"
],
"quirks": ["q.bedrock_quirk('kingambit', 'blink')"]
}
@@ -4,6 +4,9 @@
"profileScale": 0.88,
"profileTranslation": [0.00, 0.39, 0],
"rootBone": "dipplin",
"animations": {
"cry": "q.bedrock_stateful('dipplin', 'cry')"
},
"poses": {
"battle-standing": {
"poseTypes": ["STAND"],
@@ -24,6 +24,7 @@
"isBattle": false,
"condition": "!q.in_air",
"animations": [
"q.look('head_ai', 1, 1, 12.5, -12.5, 15, -15)",
"q.bedrock('archaludon', 'ground_idle')",
{
"condition": "q.is_ridden && q.has_entity",
@@ -42,6 +43,7 @@
"isBattle": true,
"condition": "!q.in_air",
"animations": [
"q.look('head_ai', 1, 1, 12.5, -12.5, 15, -15)",
"q.bedrock('archaludon', 'battle_idle')"
],
"namedAnimations": {
@@ -58,6 +60,7 @@
],
"condition": "!q.in_air && !q.is_sprinting",
"animations": [
"q.look('head_ai', 1, 1, 12.5, -12.5, 15, -15)",
"q.bedrock('archaludon', 'ground_walk')",
{
"condition": "q.is_ridden && q.has_entity",
@@ -75,6 +78,7 @@
],
"condition": "!q.in_air && q.is_sprinting",
"animations": [
"q.look('head_ai', 1, 1, 12.5, -12.5, 15, -15)",
"q.bedrock('archaludon', 'ground_run')",
{
"condition": "q.is_ridden && q.has_entity",
@@ -89,6 +93,7 @@
"poseTypes": ["STAND", "WALK"],
"condition": "q.in_air",
"animations": [
"q.look('head_ai', 1, 1, 12.5, -12.5, 15, -15)",
"q.bedrock('archaludon', 'ride_jump')",
{
"condition": "q.is_ridden",
@@ -100,6 +105,13 @@
],
"transformTicks": 5,
"transformToTicks": 5
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('archaludon', 'sleep')"]
}
}
}
@@ -15,7 +15,7 @@
"q.look('main_head_neck_end_bend', 1, 1, 5, -5, 15, -15)",
"q.look('main_head_neck_tip', 1, 1, 5, -5, 15, -15)",
"q.look('head_ai', 1, -1, 15, -15, 15, -15)",
"q.bedrock('hydrapple', 'ground_idle')"
"q.bedrock('hydrapple', 'battle_idle')"
],
"quirks": [
"q.bedrock_quirk('hydrapple', 'blink')"
@@ -25,6 +25,30 @@
"emissive": true
}
]
},
{
"aspects": [
"color-lime",
"hisuian"
],
"layers": [
{
"name": "lime",
"texture": "cobblemon:textures/pokemon/0101_electrode/electrode_watermelon_blank.png"
}
]
},
{
"aspects": [
"color-green",
"hisuian"
],
"layers": [
{
"name": "green",
"texture": "cobblemon:textures/pokemon/0101_electrode/electrode_watermelon_blank.png"
}
]
}
]
}
@@ -2878,6 +2878,7 @@
"cobblemon.battle.activate.disguise": "Its disguise served it as a decoy!",
"cobblemon.battle.activate.electricterrain": "%1$s surrounds itself with electrified terrain!",
"cobblemon.battle.activate.endure": "%1$s endured the hit!",
"cobblemon.battle.activate.ficklebeam": "%1$s is going all out for this attack!",
"cobblemon.battle.activate.firespin": "%1$s became trapped in the fiery vortex!",
"cobblemon.battle.activate.focusband": "%1$s hung on using its Focus Band!",
"cobblemon.battle.activate.forewarn": "%2$s's %3$s was revealed!",
@@ -5957,8 +5957,8 @@
"item.cobblemon.galarica_nuts": "ガラナツのナッツ",
"cobblemon.pokerod.apply": "右クリックでエサを付ける",
"item.cobblemon.npc_editor": "NPCのトレーナーカード",
"item.cobblemon.link_cable.tooltip": "なにかしらのつながりを感じさせる 不思議なエネルギーを秘めているヒモ。ポケモン交換で進化するポケモンを進化させる。",
"item.cobblemon.dragon_scale.tooltip": "硬くて 丈夫な ウロコ。シードラに持たせてポケモン交換すると キングドラに進化する。",
"item.cobblemon.link_cable.tooltip": "なにかしらのつながりを感じさせる 不思議なエネルギーを秘めているヒモ。 ポケモン交換で進化するポケモンを進化させる。",
"item.cobblemon.dragon_scale.tooltip": "硬くて 丈夫な ウロコ。 シードラに持たせてポケモン交換すると キングドラに進化する。",
"item.cobblemon.kings_rock.tooltip_1": "持たせると 攻撃して ダメージを 与えたときに 相手を ひるませることが ある。",
"item.cobblemon.metal_coat.tooltip_1": "特殊な金属の 膜。 持たせると はがねタイプの 技の威力が 上がる。",
"item.cobblemon.metal_coat.tooltip_2": "イワーク・ストライクに持たせてポケモン交換すると それぞれハガネール・ハッサムに進化する。",
@@ -5968,45 +5968,45 @@
"item.cobblemon.deep_sea_scale.tooltip_2": "パールルに持たせてポケモン交換すると サクラビスに進化する。",
"item.cobblemon.deep_sea_tooth.tooltip_1": "パールルに 持たせると 特攻が あがる キバ。",
"item.cobblemon.deep_sea_tooth.tooltip_2": "パールルに持たせてポケモン交換すると ハンテールに進化する。",
"item.cobblemon.electirizer.tooltip": "とてつもない 電気の エネルギーが 蓄えられている 箱。エレブーに持たせてポケモン交換すると エレキブルに進化する。",
"item.cobblemon.electirizer.tooltip": "とてつもない 電気の エネルギーが 蓄えられている 箱。 エレブーに持たせてポケモン交換すると エレキブルに進化する。",
"item.cobblemon.magmarizer.tooltip": "とてつもない マグマの エネルギーが 蓄えられている 箱。 ブーバーに持たせてポケモン交換すると ブーバーンに進化する。",
"item.cobblemon.oval_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 たまのように まるい。",
"item.cobblemon.reaper_cloth.tooltip": "おそろしく 強い霊力が こめられている 布。サマヨールに持たせてポケモン交換すると ヨノワールに進化する。",
"item.cobblemon.sachet.tooltip": "ちょっと きつめの 香りをだす 香料を 詰めた 袋。シュシュプに持たせてポケモン交換すると フレフワンに進化する。",
"item.cobblemon.strawberry_sweet.tooltip": "いちごの形をした アメ細工。マホミルに使うと いちごのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.berry_sweet.tooltip": "ベリーの形をした アメ細工。マホミルに使うと ベリーのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.clover_sweet.tooltip": "よつばの形をした アメ細工。マホミルに使うと よつばのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.star_sweet.tooltip": "スターの形をした アメ細工。マホミルに使うと スターのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.sweet_apple.tooltip": "とにかく 甘い 不思議なりんご。カジッチュに使うと タルップルに進化する。",
"item.cobblemon.cracked_pot.tooltip": "割れている 不思議なポット。がんさくフォルムのヤバチャに使うと ポットデスに進化する。",
"item.cobblemon.chipped_pot.tooltip": "欠けている 不思議なポット。しんさくフォルムのヤバチャに使うと ポットデスに進化する。",
"item.cobblemon.tart_apple.tooltip": "とにかく 酸っぱい 不思議なりんご。カジッチュに使うと アップリューに進化する。",
"item.cobblemon.reaper_cloth.tooltip": "おそろしく 強い霊力が こめられている 布。 サマヨールに持たせてポケモン交換すると ヨノワールに進化する。",
"item.cobblemon.sachet.tooltip": "ちょっと きつめの 香りをだす 香料を 詰めた 袋。 シュシュプに持たせてポケモン交換すると フレフワンに進化する。",
"item.cobblemon.strawberry_sweet.tooltip": "いちごの形をした アメ細工。 マホミルに使うと いちごのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.berry_sweet.tooltip": "ベリーの形をした アメ細工。 マホミルに使うと ベリーのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.clover_sweet.tooltip": "よつばの形をした アメ細工。 マホミルに使うと よつばのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.star_sweet.tooltip": "スターの形をした アメ細工。 マホミルに使うと スターのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.sweet_apple.tooltip": "とにかく 甘い 不思議なりんご。 カジッチュに使うと タルップルに進化する。",
"item.cobblemon.cracked_pot.tooltip": "割れている 不思議なポット。 がんさくフォルムのヤバチャに使うと ポットデスに進化する。",
"item.cobblemon.chipped_pot.tooltip": "欠けている 不思議なポット。 しんさくフォルムのヤバチャに使うと ポットデスに進化する。",
"item.cobblemon.tart_apple.tooltip": "とにかく 酸っぱい 不思議なりんご。 カジッチュに使うと アップリューに進化する。",
"item.cobblemon.galarica_wreath.tooltip": "ガラナツのナッツを 編み込んだ 冠。 ガラルのすがたのヤドンに使うと ヤドキングに進化する。",
"item.cobblemon.black_augurite.tooltip": "割ると鋭い切れ味を持つ ガラスに似た性質の黒い石。ストライクに使うと バサギリに進化する。",
"item.cobblemon.peat_block.tooltip": "泥のような石炭のかたまり。満月の夜に リングマに使うと ガチグマに進化する。",
"item.cobblemon.dawn_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。ひとみのように まばゆい。",
"item.cobblemon.black_augurite.tooltip": "割ると鋭い切れ味を持つ ガラスに似た性質の黒い石。 ストライクに使うと バサギリに進化する。",
"item.cobblemon.peat_block.tooltip": "泥のような石炭のかたまり。 満月の夜に リングマに使うと ガチグマに進化する。",
"item.cobblemon.dawn_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 ひとみのように まばゆい。",
"item.cobblemon.dusk_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。やみのように 暗い。",
"item.cobblemon.fire_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。だいだい色を している。",
"item.cobblemon.ice_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。雪の模様が ある。",
"item.cobblemon.leaf_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。葉っぱの模様が ある。",
"item.cobblemon.shiny_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。ひかりのように まぶしい。",
"item.cobblemon.thunder_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。稲妻の模様が ある。",
"item.cobblemon.water_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。澄んだ水色を している。",
"item.cobblemon.fire_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 だいだい色を している。",
"item.cobblemon.ice_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 雪の模様が ある。",
"item.cobblemon.leaf_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 葉っぱの模様が ある。",
"item.cobblemon.shiny_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 ひかりのように まぶしい。",
"item.cobblemon.thunder_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 稲妻の模様が ある。",
"item.cobblemon.water_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 澄んだ水色を している。",
"item.cobblemon.exp_candy_xs.tooltip": "エネルギーの つまった アメ。 与えると ポケモン 1匹の 経験値が 100 増える。",
"item.cobblemon.exp_candy_m.tooltip": "エネルギーの つまった アメ。 与えると ポケモン 1匹の 経験値が 3000 増える。",
"item.cobblemon.exp_candy_l.tooltip": "ネルギーの つまった アメ。 与えると ポケモン 1匹の 経験値が 10000 増える。",
"item.cobblemon.iron.tooltip": "ポケモンの 栄養ドリンク。ポケモン 1匹の 防御の 基礎ポイントを 10 あげる。",
"item.cobblemon.carbos.tooltip": "ポケモンの 栄養ドリンク。ポケモン 1匹の 素早さの 基礎ポイントを 10 あげる。",
"item.cobblemon.calcium.tooltip": "ポケモンの 栄養ドリンク。ポケモン 1匹の 特攻の 基礎ポイントを 10 あげる。",
"item.cobblemon.protein.tooltip": "ポケモンの 栄養ドリンク。ポケモン 1匹の 攻撃の 基礎ポイントを 10 あげる。",
"item.cobblemon.potion.tooltip": "スプレー式の キズぐすり。ポケモン 1匹の HPを 60だけ 回復する。",
"item.cobblemon.super_potion.tooltip": "スプレー式の キズぐすり。ポケモン 1匹の HPを 100だけ 回復する。",
"item.cobblemon.max_potion.tooltip": "スプレー式の キズぐすり。ポケモン 1匹の HPを すべて 回復する。",
"item.cobblemon.full_restore.tooltip": "スプレー式の キズぐすり。ポケモン 1匹の HPと 状態異常を すべて 回復する。",
"item.cobblemon.iron.tooltip": "ポケモンの 栄養ドリンク。 ポケモン 1匹の 防御の 基礎ポイントを 10 あげる。",
"item.cobblemon.carbos.tooltip": "ポケモンの 栄養ドリンク。 ポケモン 1匹の 素早さの 基礎ポイントを 10 あげる。",
"item.cobblemon.calcium.tooltip": "ポケモンの 栄養ドリンク。 ポケモン 1匹の 特攻の 基礎ポイントを 10 あげる。",
"item.cobblemon.protein.tooltip": "ポケモンの 栄養ドリンク。 ポケモン 1匹の 攻撃の 基礎ポイントを 10 あげる。",
"item.cobblemon.potion.tooltip": "スプレー式の キズぐすり。 ポケモン 1匹の HPを 60だけ 回復する。",
"item.cobblemon.super_potion.tooltip": "スプレー式の キズぐすり。 ポケモン 1匹の HPを 100だけ 回復する。",
"item.cobblemon.max_potion.tooltip": "スプレー式の キズぐすり。 ポケモン 1匹の HPを すべて 回復する。",
"item.cobblemon.full_restore.tooltip": "スプレー式の キズぐすり。 ポケモン 1匹の HPと 状態異常を すべて 回復する。",
"item.cobblemon.health_feather.tooltip": "ポケモンに 使う 道具。 ポケモン 1匹の HPの 基礎ポイントを ちょっと あげる。",
"item.cobblemon.muscle_feather.tooltip": "ポケモンに 使う 道具。 ポケモン 1匹の 攻撃の 基礎ポイントを ちょっと あげる。",
"item.cobblemon.genius_feather.tooltip": "ポケモンに 使う 道具。 ポケモン 1匹の 特攻の 基礎ポイントを ちょっと あげる。",
"item.cobblemon.clever_feather.tooltip": "ポケモンに 使う 道具。ポケモン 1匹の 特防の 基礎ポイントを ちょっと あげる。",
"item.cobblemon.clever_feather.tooltip": "ポケモンに 使う 道具。 ポケモン 1匹の 特防の 基礎ポイントを ちょっと あげる。",
"item.cobblemon.ability_capsule.tooltip": "2種類の特性を 持つ ポケモンに 使うと 今とは違う 特性に 変えられる カプセル。",
"item.cobblemon.adamant_mint.tooltip": "ポケモンに 香りを かがせると 攻撃が 上がりやすく なるが 特攻は 上がりにくくなる ミント。",
"item.cobblemon.brave_mint.tooltip": "ポケモンに 香りを かがせると 攻撃が 上がりやすく なるが 素早さは 上がりにくくなる ミント。",
@@ -6023,7 +6023,7 @@
"item.cobblemon.absorb_bulb.tooltip_2": "使うとなくなる。",
"item.cobblemon.air_balloon.tooltip_2": "攻撃を 受けると 割れてしまう。",
"item.cobblemon.assault_vest.tooltip": "攻撃的になる チョッキ。 持たせると 特防が あがるが 変化技を だせなくなる。",
"item.cobblemon.malicious_armor.tooltip": "呪いの感情が 秘められている 不思議なヨロイ。カルボウに使うと ソウブレイズに進化させる。",
"item.cobblemon.malicious_armor.tooltip": "呪いの感情が 秘められている 不思議なヨロイ。 カルボウに使うと ソウブレイズに進化させる。",
"item.cobblemon.black_belt.tooltip": "気が ひきしまる 帯。 持たせると かくとうタイプの 技の威力が あがる。",
"item.cobblemon.black_glasses.tooltip": "怪しく見える メガネ。 持たせると あくタイプの 技の威力が あがる。",
"item.cobblemon.blunder_policy.tooltip_2": "使うとなくなる。",
@@ -6031,7 +6031,7 @@
"item.cobblemon.eject_button.tooltip_2": "使うとなくなる。",
"item.cobblemon.eject_pack.tooltip_2": "使うとなくなる。",
"item.cobblemon.blunder_policy.tooltip_1": "命中率に よって 技が はずれたとき 素早さが ぐーんと 上がる。",
"item.cobblemon.charcoal_stick.tooltip": "少し大きな棒型の木炭。持たせると ほのおタイプの 技の威力が あがる。",
"item.cobblemon.charcoal_stick.tooltip": "少し大きな棒型の木炭。 持たせると ほのおタイプの 技の威力が あがる。",
"item.cobblemon.choice_band.tooltip": "ちょっと こだわった ハチマキ。 持たせると 攻撃は あがるが 同じ技しか だせなくなる。",
"item.cobblemon.choice_specs.tooltip": "ちょっと こだわった メガネ。 持たせると 特攻は あがるが 同じ技しか だせなくなる。",
"item.cobblemon.cleanse_tag.tooltip": "効果なし",
@@ -6052,47 +6052,47 @@
"item.cobblemon.grass_gem.tooltip_2": "使うとなくなる。",
"item.cobblemon.dragon_gem.tooltip_2": "使うとなくなる。",
"item.cobblemon.ghost_gem.tooltip_2": "使うとなくなる。",
"item.cobblemon.whipped_dream.tooltip": "ふんわり ふわふわに 泡立てた ほんのり 甘い クリーム。ペロッパフに持たせてポケモン交換すると ペロリームに進化する。",
"item.cobblemon.sun_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。太陽のように 赤い。",
"item.cobblemon.prism_scale.tooltip": "にじ色に 輝く 不思議なウロコ。ヒンバスに持たせてポケモン交換すると ミロカロスに進化する。",
"item.cobblemon.love_sweet.tooltip": "ハートの形をした アメ細工。マホミルに使うと ハートのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.flower_sweet.tooltip": "おはなの形をした アメ細工。マホミルに使うと おはなのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.whipped_dream.tooltip": "ふんわり ふわふわに 泡立てた ほんのり 甘い クリーム。 ペロッパフに持たせてポケモン交換すると ペロリームに進化する。",
"item.cobblemon.sun_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 太陽のように 赤い。",
"item.cobblemon.prism_scale.tooltip": "にじ色に 輝く 不思議なウロコ。 ヒンバスに持たせてポケモン交換すると ミロカロスに進化する。",
"item.cobblemon.love_sweet.tooltip": "ハートの形をした アメ細工。 マホミルに使うと ハートのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.flower_sweet.tooltip": "おはなの形をした アメ細工。 マホミルに使うと おはなのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.swift_feather.tooltip": "ポケモンに 使う 道具。 ポケモン 1匹の 素早さの 基礎ポイントを ちょっと あげる。",
"item.cobblemon.ability_patch.tooltip": "通常の特性を 持つ ポケモンに 使うと めずらしい 隠れ特性に 変えられる パッチ。",
"item.cobblemon.ability_patch.tooltip": "通常の特性を 持つ ポケモンに 使うと めずらしい 隠れ特性に 変えられる パッチ。 隠れ特性に 使うと 通常の特性に 戻る。",
"item.cobblemon.mild_mint.tooltip": "ポケモンに 香りを かがせると 特攻が 上がりやすく なるが 防御は 上がりにくくなる ミント。",
"item.cobblemon.jolly_mint.tooltip": "ポケモンに 香りを かがせると 素早さが 上がりやすく なるが 特攻は 上がりにくくなる ミント。",
"item.cobblemon.air_balloon.tooltip_1": "ポケモンに 持たせると ポケモンが 宙に 浮く。",
"item.cobblemon.cell_battery.tooltip_1": "持たせて でんきの技の ダメージを 受けると 攻撃が あがる。",
"item.cobblemon.protector.tooltip": "なにかの プロテクター。 とても 硬くて 重い。サイドンに持たせてポケモン交換すると ドサイドンに進化する。",
"item.cobblemon.ribbon_sweet.tooltip": "リボンの形をした アメ細工。マホミルに使うと リボンのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.protector.tooltip": "なにかの プロテクター。 とても 硬くて 重い。 サイドンに持たせてポケモン交換すると ドサイドンに進化する。",
"item.cobblemon.ribbon_sweet.tooltip": "リボンの形をした アメ細工。 マホミルに使うと リボンのアメざいくを身に付けた マホイップになる。",
"item.cobblemon.exp_candy_xl.tooltip": "エネルギーの つまった アメ。 与えると ポケモン 1匹の 経験値が 30000 増える。",
"item.cobblemon.zinc.tooltip": "ポケモンの 栄養ドリンク。 ポケモン 1匹の 特防の 基礎ポイントを 10 あげる。",
"item.cobblemon.resist_feather.tooltip": "ポケモンに 使う 道具。ポケモン 1匹の 防御の 基礎ポイントを ちょっと あげる。",
"item.cobblemon.resist_feather.tooltip": "ポケモンに 使う 道具。 ポケモン 1匹の 防御の 基礎ポイントを ちょっと あげる。",
"item.cobblemon.bold_mint.tooltip": "ポケモンに 香りを かがせると 防御が 上がりやすく なるが 攻撃は 上がりにくくなる ミント。",
"item.cobblemon.covert_cloak.tooltip": "敵の目を あざむく フード付き マント。 持たせると 体を 包み隠し 技の 追加効果を 受けなくなる。",
"item.cobblemon.unremarkable_teacup.tooltip": "割れている 不思議な茶碗。マガイモノのすがたのチャデスに使うと ヤバソチャに進化する。",
"item.cobblemon.unremarkable_teacup.tooltip": "割れている 不思議な茶碗。 マガイモノのすがたのチャデスに使うと ヤバソチャに進化する。",
"item.cobblemon.galarica_cuff.tooltip": "ガラナツのナッツを 編み込んだ ブレスレット。 ガラルのすがたのヤドンに使うと ヤドランに進化する。",
"item.cobblemon.lonely_mint.tooltip": "ポケモンに 香りを かがせると 攻撃が 上がりやすく なるが 防御は 上がりにくくなる ミント。",
"item.cobblemon.normal_gem.tooltip_2": "使うとなくなる。",
"item.cobblemon.auspicious_armor.tooltip": "祝いの感情が 秘められている 不思議なヨロイ。カルボウに使うと グレンアルマに進化させる。",
"item.cobblemon.auspicious_armor.tooltip": "祝いの感情が 秘められている 不思議なヨロイ。 カルボウに使うと グレンアルマに進化させる。",
"item.cobblemon.kings_rock.tooltip_2": "ヤドン・ニョロゾに持たせてポケモン交換すると それぞれヤドラン・ニョロトノに進化する。",
"item.cobblemon.masterpiece_teacup.tooltip": "欠けている 不思議な茶碗。タカイモノのすがたのチャデスに使うと ヤバソチャに進化する。",
"item.cobblemon.moon_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。夜空のように 黒い。",
"item.cobblemon.rare_candy.tooltip": "エネルギーの つまった アメ。あたえると ポケモン 1匹の レベルが 1だけ あがる。",
"item.cobblemon.hyper_potion.tooltip": "スプレー式の キズぐすり。ポケモン 1匹の HPを 150だけ 回復する。",
"item.cobblemon.masterpiece_teacup.tooltip": "欠けている 不思議な茶碗。 タカイモノのすがたのチャデスに使うと ヤバソチャに進化する。",
"item.cobblemon.moon_stone.tooltip": "ある特定の ポケモンを 進化させる 不思議な石。 夜空のように 黒い。",
"item.cobblemon.rare_candy.tooltip": "エネルギーの つまった アメ。 あたえると ポケモン 1匹の レベルが 1だけ あがる。",
"item.cobblemon.hyper_potion.tooltip": "スプレー式の キズぐすり。 ポケモン 1匹の HPを 150だけ 回復する。",
"item.cobblemon.naughty_mint.tooltip": "ポケモンに 香りを かがせると 攻撃が 上がりやすく なるが 特防は 上がりにくくなる ミント。",
"item.cobblemon.relaxed_mint.tooltip": "ポケモンに 香りを かがせると 防御が 上がりやすく なるが 素早さは 上がりにくくなる ミント。",
"item.cobblemon.timid_mint.tooltip": "ポケモンに 香りを かがせると 素早さが 上がりやすく なるが 攻撃は 上がりにくくなる ミント。",
"item.cobblemon.serious_mint.tooltip": "ポケモンに 香りを かがせると 攻撃 防御 素早さ 特防 特攻が 万遍なく 育つ ミント。",
"item.cobblemon.red_card.tooltip_2": "使うとなくなる。",
"item.cobblemon.black_sludge.tooltip": "持たせると どくタイプの ポケモンは 少しずつ HPを 回復する。それ以外は HPが 減ってしまう。",
"item.cobblemon.black_sludge.tooltip": "持たせると どくタイプの ポケモンは 少しずつ HPを 回復する。 それ以外は HPが 減ってしまう。",
"item.cobblemon.exp_candy_s.tooltip": "エネルギーの つまった アメ。 与えると ポケモン 1匹の 経験値が 800 増える。",
"item.cobblemon.hp_up.tooltip": "ポケモンの 栄養ドリンク。ポケモン 1匹の HPの 基礎ポイントを 10 あげる。",
"item.cobblemon.hp_up.tooltip": "ポケモンの 栄養ドリンク。 ポケモン 1匹の HPの 基礎ポイントを 10 あげる。",
"item.cobblemon.calm_mint.tooltip": "ポケモンに 香りを かがせると 特防が 上がりやすく なるが 攻撃は 上がりにくくなる ミント。",
"item.cobblemon.careful_mint.tooltip": "ポケモンに 香りを かがせると 特防が 上がりやすく なるが 特攻は 上がりにくくなる ミント。",
"item.cobblemon.hasty_mint.tooltip": "ポケモンに 香りを かがせると 素早さが 上がりやすく なるが 防御は 上がりにくくなる ミント。",
"item.cobblemon.white_herb.tooltip_2": "使うとなくなる。",
"item.cobblemon.binding_band.tooltip": "締めつける技を 補助する バンド。持たせると 締めつける技の 威力が 強くなる。",
"item.cobblemon.binding_band.tooltip": "締めつける技を 補助する バンド。 持たせると 締めつける技の 威力が 強くなる。",
"item.cobblemon.choice_scarf.tooltip": "ちょっと こだわった スカーフ。 持たせると 素早さは あがるが 同じ技しか だせなくなる。",
"item.cobblemon.electric_seed.tooltip": "ポケモンに 持たせると エレキフィールドのときに 使って 防御が あがる。",
"item.cobblemon.exp_share.tooltip": "持たせた ポケモンは 戦闘に でなくても 経験値を わけてもらえる 便利な 装置。",
@@ -6104,60 +6104,60 @@
"item.cobblemon.grassy_seed.tooltip": "ポケモンに 持たせると グラスフィールドのときに 使って 防御が あがる。",
"item.cobblemon.hard_stone.tooltip": "絶対に 割れない石。 持たせると いわタイプの 技の威力が あがる。",
"item.cobblemon.heavy_duty_boots.tooltip": "足場に しかけられた 罠などの影響を 受けなくなる。",
"item.cobblemon.iron_ball.tooltip": "持たせると 素早さが さがる。ひこうタイプや ふゆうポケモンは じめん技が 当たってしまう。",
"item.cobblemon.iron_ball.tooltip": "持たせると 素早さが さがる。 ひこうタイプや ふゆうポケモンは じめん技が 当たってしまう。",
"item.cobblemon.light_ball.tooltip": "ピカチュウに 持たせると 攻撃と 特攻が あがる 不思議な玉。",
"item.cobblemon.loaded_dice.tooltip": "いい目しか 出ない サイコロ。持たせて 連続技を 使うと 多めに 技を 出すことが できる。",
"item.cobblemon.lucky_egg.tooltip": "しあわせが つまった タマゴ。持たせたポケモンは もらえる 経験値が 少し増える。",
"item.cobblemon.magnet.tooltip": "強力な 磁石。持たせると でんきタイプの 技の威力が あがる。",
"item.cobblemon.miracle_seed.tooltip": "生命が宿る タネ。持たせると くさタイプの 技の威力が あがる。",
"item.cobblemon.muscle_band.tooltip": "ちからが わいてくる ハチマキ。持たせると 物理技の 威力が 少し あがる。",
"item.cobblemon.never_melt_ice.tooltip": "熱を よせつけない 氷。持たせると こおりタイプの 技の威力が あがる。",
"item.cobblemon.poison_barb.tooltip": "どくのある ちいさな ハリ。持たせると どくタイプの 技の威力が あがる。",
"item.cobblemon.punching_glove.tooltip": "こぶしを 保護する グローブ。持たせると パンチ技の 威力が あがり 相手に 接触しない パンチに なる。",
"item.cobblemon.quick_claw.tooltip": "軽くて 鋭い ツメ。持たせると 相手より 先に 行動できることが ある。",
"item.cobblemon.loaded_dice.tooltip": "いい目しか 出ない サイコロ。 持たせて 連続技を 使うと 多めに 技を 出すことが できる。",
"item.cobblemon.lucky_egg.tooltip": "しあわせが つまった タマゴ。 持たせたポケモンは もらえる 経験値が 少し増える。",
"item.cobblemon.magnet.tooltip": "強力な 磁石。 持たせると でんきタイプの 技の威力が あがる。",
"item.cobblemon.miracle_seed.tooltip": "生命が宿る タネ。 持たせると くさタイプの 技の威力が あがる。",
"item.cobblemon.muscle_band.tooltip": "ちからが わいてくる ハチマキ。 持たせると 物理技の 威力が 少し あがる。",
"item.cobblemon.never_melt_ice.tooltip": "熱を よせつけない 氷。 持たせると こおりタイプの 技の威力が あがる。",
"item.cobblemon.poison_barb.tooltip": "どくのある ちいさな ハリ。 持たせると どくタイプの 技の威力が あがる。",
"item.cobblemon.punching_glove.tooltip": "こぶしを 保護する グローブ。 持たせると パンチ技の 威力が あがり 相手に 接触しない パンチに なる。",
"item.cobblemon.quick_claw.tooltip": "軽くて 鋭い ツメ。 持たせると 相手より 先に 行動できることが ある。",
"item.cobblemon.razor_fang.tooltip_1": "鋭く とがった キバ。持たせると ダメージを 与えたとき ひるませることが ある。",
"item.cobblemon.razor_fang.tooltip_2": "グライガーに持たせて夜にレベルアップさせると、グライオンに進化する。",
"item.cobblemon.razor_fang.tooltip_2": "グライガーに 持たせると、 夜にグライオンに進化する。",
"item.cobblemon.red_card.tooltip_1": "不思議な ちからのある カード。 持たせると ダメージを 与えてきた 相手を 控えに 退場させることが できる。",
"item.cobblemon.rocky_helmet.tooltip": "ポケモンに 持たせると 自分に さわった相手に ダメージを 与える。",
"item.cobblemon.room_service.tooltip_1": "ポケモンに 持たせると トリックルームのときに 使って 素早さが 下がる。",
"item.cobblemon.scope_lens.tooltip": "弱点が みえる レンズ。持たせた ポケモンの技が 急所に 当たりやすくなる。",
"item.cobblemon.sharp_beak.tooltip": "長く とがった くちばし。持たせると ひこうタイプの 技の威力が あがる。",
"item.cobblemon.shed_shell.tooltip": "丈夫で 硬い ぬけがら。持たせた ポケモンは 控えの ポケモンと 必ず いれかわれる。",
"item.cobblemon.silk_scarf.tooltip": "はだざわりの よい スカーフ。持たせると ノーマルタイプの 技の 威力が あがる。",
"item.cobblemon.silver_powder.tooltip": "銀色に 輝く 粉。持たせると むしタイプの 技の威力が あがる。",
"item.cobblemon.soothe_bell.tooltip": "心地よい 音色の鈴。持たせたポケモンは 心が 安らぎ なかよく なりやすくなる。",
"item.cobblemon.spell_tag.tooltip": "怪しくて 不気味な お札。持たせると ゴーストタイプの 技の威力が あがる。",
"item.cobblemon.sticky_barb.tooltip": "持たせると 毎ターン ダメージを 受ける。自分に ふれてきた 相手に くっつくことも ある。",
"item.cobblemon.scope_lens.tooltip": "弱点が みえる レンズ。 持たせた ポケモンの技が 急所に 当たりやすくなる。",
"item.cobblemon.sharp_beak.tooltip": "長く とがった くちばし。 持たせると ひこうタイプの 技の威力が あがる。",
"item.cobblemon.shed_shell.tooltip": "丈夫で 硬い ぬけがら。 持たせた ポケモンは 控えの ポケモンと 必ず いれかわれる。",
"item.cobblemon.silk_scarf.tooltip": "はだざわりの よい スカーフ。 持たせると ノーマルタイプの 技の 威力が あがる。",
"item.cobblemon.silver_powder.tooltip": "銀色に 輝く 粉。 持たせると むしタイプの 技の威力が あがる。",
"item.cobblemon.soothe_bell.tooltip": "心地よい 音色の鈴。 持たせたポケモンは 心が 安らぎ なかよく なりやすくなる。",
"item.cobblemon.spell_tag.tooltip": "怪しくて 不気味な お札。 持たせると ゴーストタイプの 技の威力が あがる。",
"item.cobblemon.sticky_barb.tooltip": "持たせると 毎ターン ダメージを 受ける。 自分に ふれてきた 相手に くっつくことも ある。",
"item.cobblemon.terrain_extender.tooltip": "持たせたポケモンが 技や 特性で フィールドを 張ったとき いつもよりも 長く 残る。",
"item.cobblemon.throat_spray.tooltip_1": "音に 関する 技を 使うと 特攻が 上がる。",
"item.cobblemon.twisted_spoon.tooltip": "念力を こめた スプーン。持たせると エスパータイプの 技の威力が あがる。",
"item.cobblemon.twisted_spoon.tooltip": "念力を こめた スプーン。 持たせると エスパータイプの 技の威力が あがる。",
"item.cobblemon.utility_umbrella.tooltip": "持たせた ポケモンは 雨と 日差しが強いときの 影響を 受けなくなる。",
"item.cobblemon.weakness_policy.tooltip_1": "弱点を つかれたとき 攻撃と 特攻が それぞれ ぐーんと あがる。",
"item.cobblemon.wide_lens.tooltip": "ものが 大きく見える レンズ。持たせると 技の命中率が 少し あがる。",
"item.cobblemon.wide_lens.tooltip": "ものが 大きく見える レンズ。 持たせると 技の命中率が 少し あがる。",
"item.cobblemon.wise_glasses.tooltip": "ぶあつい レンズの ついた メガネ。 持たせると 特殊技の 威力が 少し あがる。",
"item.cobblemon.mental_herb.tooltip_1": "持たせたポケモンが 自由に 技を だせなくなったときに 1度だけ 回復する。",
"item.cobblemon.misty_seed.tooltip": "ポケモンに 持たせると ミストフィールドのときに 使って 特防が あがる。",
"item.cobblemon.power_herb.tooltip_1": "持たせたポケモンは 1度だけ 1ターン目に ちからを ためる技を すぐに 使うことが できる。",
"item.cobblemon.bright_powder.tooltip": "キラキラ 光る粉。 持たせると 光が 相手を 惑わして 技が 10% 命中しにくくなる。",
"item.cobblemon.metal_powder.tooltip": "メタモンに 持たせると 50% 防御が あがる 不思議な粉。とても こまかくて 硬い。",
"item.cobblemon.quick_powder.tooltip": "メタモンに 持たせると 素早さが あがる 不思議な粉。とても こまかくて 硬い。",
"item.cobblemon.destiny_knot.tooltip": "細くて 長い 真っ赤な糸。持たせると メロメロに なったとき 相手も メロメロに できる。",
"item.cobblemon.metal_powder.tooltip": "メタモンに 持たせると 50% 防御が あがる 不思議な粉。 とても こまかくて 硬い。",
"item.cobblemon.quick_powder.tooltip": "メタモンに 持たせると 素早さが あがる 不思議な粉。 とても こまかくて 硬い。",
"item.cobblemon.destiny_knot.tooltip": "細くて 長い 真っ赤な糸。 持たせると メロメロに なったとき 相手も メロメロに できる。",
"item.cobblemon.power_anklet.tooltip": "持たせると 戦闘中の 素早さが さがるが ふつうよりも ポケモンの 素早さの基礎ポイントが 8 多く 育つ。",
"item.cobblemon.power_band.tooltip": "持たせると 戦闘中の 素早さが さがるが ふつうよりも ポケモンの 特防の基礎ポイントが 8 多く 育つ。",
"item.cobblemon.power_bracer.tooltip": "持たせると 戦闘中の 素早さが さがるが ふつうよりも ポケモンの 攻撃の基礎ポイントが 8 多く 育つ。",
"item.cobblemon.power_lens.tooltip": "持たせると 戦闘中の 素早さが さがるが ふつうよりも ポケモンの 特攻の基礎ポイントが 8 多く 育つ。",
"item.cobblemon.power_weight.tooltip": "持たせると 戦闘中の 素早さが さがるが ふつうよりも ポケモンの HPの基礎ポイントが 8 多く 育つ。",
"item.cobblemon.psychic_seed.tooltip": "ポケモンに 持たせると サイコフィールドのときに 使って 特防が あがる。",
"item.cobblemon.flame_orb.tooltip": "触ると 熱をだす 不思議な玉。持たせると 戦闘中に やけどの状態に なる。",
"item.cobblemon.flame_orb.tooltip": "触ると 熱をだす 不思議な玉。 持たせると 戦闘中に やけどの状態に なる。",
"item.cobblemon.smoke_ball.tooltip": "効果なし",
"item.cobblemon.toxic_orb.tooltip": "触ると 毒をだす 不思議な玉。持たせると 戦闘中に 猛毒の状態に なる。",
"item.cobblemon.toxic_orb.tooltip": "触ると 毒をだす 不思議な玉。 持たせると 戦闘中に 猛毒の状態に なる。",
"item.cobblemon.life_orb.tooltip": "持たせると 攻撃するたびに HPが 少し 減ってしまうが 技の威力が あがる。",
"item.cobblemon.damp_rock.tooltip": "持たせた ポケモンが 天気を あめにすると いつもより あめの時間が 長くなる。",
"item.cobblemon.heat_rock.tooltip": "持たせた ポケモンが 日差しを 強くすると いつもより はれの時間が 長くなる。",
"item.cobblemon.smooth_rock.tooltip": "持たせたポケモンが すなあらしを 起こすと いつもより すなあらしの時間が 長くなる。",
"item.cobblemon.icy_rock.tooltip": "持たせたポケモンが 天気を ゆき または あられにすると いつもより 時間が 長くなる。",
"item.cobblemon.medicinal_leek.tooltip_1": "クスリチャの調合に必要となる。世界の各地に自生しており 旅の供とも呼ばれる。",
"item.cobblemon.medicinal_leek.tooltip_2": "カモネギや カモネギ(ガラルのすがた)、ネギガナイトに 持たせると 急所に当てる確率が 2段階 あがる。",
"item.cobblemon.medicinal_leek.tooltip_1": "クスリチャの調合に必要となる。 世界の各地に自生しており 旅の供とも呼ばれる。",
"item.cobblemon.medicinal_leek.tooltip_2": "カモネギや カモネギ(ガラルのすがた)、 ネギガナイトに 持たせると 急所に当てる確率が 2段階 あがる。",
"item.cobblemon.revival_herb.tooltip": "とても にがい 薬草。 ひんしの ポケモン 1匹の HPを 4分の1 回復するが なかよし度は 下がる。",
"item.cobblemon.berry_juice.tooltip": "きのみ 100%の ジュース。 ポケモンに 使ったり 持たせたりすると HPを 20だけ 回復する。",
"item.cobblemon.remedy.tooltip": "キズぐすりと同じで ポケモン1匹のHPが60回復するが 苦く なかよし度がさがる。",
@@ -6165,7 +6165,7 @@
"item.cobblemon.superb_remedy.tooltip": "すごいキズぐすりと同じで ポケモン1匹のHPが150回復するが 苦く なかよし度がさがる。",
"item.cobblemon.revive.tooltip": "ひんしになった ポケモン 1匹を 元気に したうえで HPを 半分まで 回復する。",
"item.cobblemon.max_revive.tooltip": "ひんしになった ポケモン 1匹を 元気に したうえで HPを すべて 回復する。",
"item.cobblemon.pp_up.tooltip": "ポケモンが 覚えている 技のうち 1つの PPの 最大値を 20% あげる。上げられるのは 60%まで。",
"item.cobblemon.pp_up.tooltip": "ポケモンが 覚えている 技のうち 1つの PPの 最大値を 20% あげる。 上げられるのは 60%まで。",
"item.cobblemon.pp_max.tooltip": "ポケモンが 覚えている 技のうち 1つの PPの 最大値を +60%分まで 一気に 上げる。",
"item.cobblemon.full_heal.tooltip": "スプレー式の 薬。 ポケモン 1匹の 状態の 異常を すべて 回復する。",
"item.cobblemon.antidote.tooltip": "スプレー式の 薬。 ポケモン 1匹の どくの 状態を 回復する。",
@@ -6228,33 +6228,33 @@
"cobblemon.trade.decline.sender": "%1$sはあなたの交換リクエストを拒否しました。",
"cobblemon.trade.decline.receiver": "あなたは %1$s の交換リクエストを拒否しました。",
"cobblemon.trade.error.insufficient_pokemon.other": "%1$sは交換するポケモンを持っていない!",
"item.cobblemon.metronome.tooltip": "持たせると 同じ技を 連続で 使ったとき 威力が あがる。やめると 威力は もどる。",
"item.cobblemon.razor_claw.tooltip_1": "鋭く とがった ツメ。持たせると 技が 急所に 当たりやすくなる。",
"item.cobblemon.metronome.tooltip": "持たせると 同じ技を 連続で 使ったとき 威力が あがる。 やめると 威力は もどる。",
"item.cobblemon.razor_claw.tooltip_1": "鋭く とがった ツメ。 持たせると 技が 急所に 当たりやすくなる。",
"item.cobblemon.ring_target.tooltip": "持っている ポケモンは タイプの相性で 無効だった 技が 相性に関係なく 当たるように なってしまう。",
"item.cobblemon.zoom_lens.tooltip": "持たせたポケモンが 相手よりも 行動するのが 遅いとき 技が 命中しやすくなる。",
"item.cobblemon.power_belt.tooltip": "持たせると 戦闘中の 素早さが さがるが ふつうよりも ポケモンの 防御の基礎ポイントが 8 多く 育つ。",
"item.cobblemon.max_ether.tooltip": "ポケモンが 覚えている 技のうち 1つのPPを すべて 回復する。",
"item.cobblemon.rock_gem.tooltip_1": "いわのタイプの ジュエル。 持たせると 1度だけ いわの 技の威力が 強まる。",
"item.cobblemon.soft_sand.tooltip": "さわると サラサラする砂。持たせると じめんタイプの 技の威力が あがる。",
"item.cobblemon.soft_sand.tooltip": "さわると サラサラする砂。 持たせると じめんタイプの 技の威力が あがる。",
"cobblemon.command.pc.invalid-box": "ボックス番号 %1$s が最大ボックス数 %2$s を超えています。",
"cobblemon.trade.expired.receiver": "%1$s からの交換リクエストがタイムアウトしました。",
"item.cobblemon.leftovers.tooltip": "持たせると ポケモンの HPが 戦闘のあいだ 少しずつ 回復する。",
"item.cobblemon.mystic_water.tooltip": "しずくの形の 宝石。持たせると みずタイプの 技の威力が あがる。",
"item.cobblemon.mystic_water.tooltip": "しずくの形の 宝石。 持たせると みずタイプの 技の威力が あがる。",
"item.cobblemon.shell_helmet": "カラっぽのシェルメット",
"item.cobblemon.fighting_gem.tooltip_1": "かくとうのタイプの ジュエル。 持たせると 1度だけ かくとうの 技の威力が 強まる。",
"item.cobblemon.energy_root.tooltip": "とても にがい ねっこ。ポケモン 1匹の HPを 80回復するが なかよし度は 下がる。",
"item.cobblemon.energy_root.tooltip": "とても にがい ねっこ。 ポケモン 1匹の HPを 80回復するが なかよし度は 下がる。",
"item.cobblemon.heal_powder.tooltip": "とても にがい 粉薬。 ポケモン 1匹の 状態の 異常を すべて 回復するが なかよし度は 下がる。",
"cobblemon.trade.error.insufficient_pokemon.self": "交換するポケモンがいません!",
"item.cobblemon.light_clay.tooltip": "持たせたポケモンが ひかりのかべや リフレクターを 使ったとき いつもよりも 長く 残る。",
"item.cobblemon.protective_pads.tooltip": "攻撃する 相手に さわって 受ける 効果を 受けないように する。",
"item.cobblemon.razor_claw.tooltip_2": "ニューラに持たせて夜にレベルアップさせるとマニューラ、ニューラ(ヒスイのすがた)に持たせて昼にレベルアップさせるとオオニューラに進化する。",
"item.cobblemon.razor_claw.tooltip_2": "ニューラに持たせると 夜にマニューラ、 ニューラ(ヒスイのすがた)に持たせると 昼にオオニューラに進化する。",
"item.cobblemon.mirror_herb.tooltip_1": "持たせたポケモンは 1度だけ 相手の 能力が あがったとき まねして 同じように 能力を 上げる。",
"item.cobblemon.white_herb.tooltip_1": "持たせた ポケモンの能力が さがったとき 1度だけ 元の状態に 戻す。",
"item.cobblemon.normal_gem.tooltip_1": "ノーマルのタイプの ジュエル。 持たせると 1度だけ ノーマルの 技の威力が 強まる。",
"cobblemon.trade.accept.receiver": "あなたは %1$s の交換リクエストを受け入れました!",
"item.cobblemon.safety_goggles.tooltip": "天候の ダメージだけでなく 粉を だす 技の 効果も 防げる ゴーグル。",
"item.cobblemon.shell_bell.tooltip": "持たせた ポケモンが 攻撃して 相手に ダメージを あたえたとき HPを 少し 回復できる。",
"item.cobblemon.shell_helmet.tooltip": "とあるポケモンが身に付けていた殻。カブルモに使うと シュバルゴに進化する。",
"item.cobblemon.shell_helmet.tooltip": "とあるポケモンが身に付けていた殻。 カブルモに使うと シュバルゴに進化する。",
"cobblemon.trade.expired.sender": "%1$s との交換リクエストがタイムアウトしました。",
"item.cobblemon.ground_gem.tooltip_1": "じめんのタイプの ジュエル。 持たせると 1度だけ じめんの 技の威力が 強まる。",
"item.cobblemon.x_attack.tooltip": "戦闘中の ポケモンの 攻撃を 2段階 あげる 道具。 ひっこめると 元に 戻る。",
@@ -6271,7 +6271,7 @@
"cobblemon.ui.wallpapers": "壁紙",
"cobblemon.ui.interact.ride": "ライド",
"cobblemon.ui.interact.give.cosmetic_item": "衣装アイテムの変更",
"item.cobblemon.syrupy_apple.tooltip": "とにかく 蜜入りの 不思議なりんご。カジッチュに使うと カミッチュに進化する。",
"item.cobblemon.syrupy_apple.tooltip": "とにかく 蜜入りの 不思議なりんご。 カジッチュに使うと カミッチュに進化する。",
"cobblemon.fishing.no_bite": "釣れないなぁ……",
"cobblemon.ui.interact.request_already_expired": "そのリクエストはすでに期限切れです!",
"cobblemon.ui.pokedex.info.form.alola": "アローラのすがた",
@@ -6627,37 +6627,37 @@
"item.cobblemon.saccharine_chest_boat": "チェスト付きのあまったるいボート",
"item.cobblemon.metal_alloy": "ふくごうきんぞく",
"item.cobblemon.scroll_of_darkness": "あくのかけじく",
"item.cobblemon.scroll_of_darkness.tooltip": "あくの極意が 書かれている 不思議なかけじく。ダクマに使うと いちげきのかたの ウーラオスに進化する。",
"item.cobblemon.scroll_of_darkness.tooltip": "あくの極意が 書かれている 不思議なかけじく。 ダクマに使うと いちげきのかたの ウーラオスに進化する。",
"item.cobblemon.scroll_of_waters": "みずのかけじく",
"item.cobblemon.fried_rice": "いそべやき",
"item.cobblemon.muscle_mochi": "きんりょくのもち",
"item.cobblemon.muscle_mochi.tooltip": "きのみが ねりこまれた もち。ポケモン 1匹の 攻撃の 基礎ポイントを 4 あげる。",
"item.cobblemon.muscle_mochi.tooltip": "きのみが ねりこまれた もち。 ポケモン 1匹の 攻撃の 基礎ポイントを 4 あげる。",
"item.cobblemon.resist_mochi": "ていこうのもち",
"item.cobblemon.resist_mochi.tooltip": "きのみが ねりこまれた もち。ポケモン 1匹の 防御の 基礎ポイントを 4 あげる。",
"item.cobblemon.genius_mochi.tooltip": "きのみが ねりこまれた もち。ポケモン 1匹の 特攻の 基礎ポイントを 4 あげる。",
"item.cobblemon.resist_mochi.tooltip": "きのみが ねりこまれた もち。 ポケモン 1匹の 防御の 基礎ポイントを 4 あげる。",
"item.cobblemon.genius_mochi.tooltip": "きのみが ねりこまれた もち。 ポケモン 1匹の 特攻の 基礎ポイントを 4 あげる。",
"item.cobblemon.clever_mochi": "せいしんのもち",
"item.cobblemon.swift_mochi": "しゅんぱつのもち",
"cobblemon.species.genesect-electric.desc": "電気エネルギーが 充填された カセットを 装着した 姿。 エネルギー弾を 発射する。",
"cobblemon.species.genesect-fire.desc": "炎エネルギーが 充填された カセットを 装着した 姿。 鋭い 鋼のツメを 持つ。",
"item.cobblemon.fresh_start_mochi.tooltip": "きのみが ねりこまれた もち。ポケモンの 基礎ポイントが すべて なくなってしまう。",
"item.cobblemon.fresh_start_mochi.tooltip": "きのみが ねりこまれた もち。 ポケモンの 基礎ポイントが すべて なくなってしまう。",
"block.cobblemon.potted_saccharine_sapling": "あまったるい苗木入り植木鉢",
"item.cobblemon.saccharine_boat": "あまったるいボート",
"item.cobblemon.scroll_of_waters.tooltip": "みずの極意が 書かれている 不思議なかけじく。ダクマに使うと れんげきのかたの ウーラオスに進化する。",
"item.cobblemon.scroll_of_waters.tooltip": "みずの極意が 書かれている 不思議なかけじく。 ダクマに使うと れんげきのかたの ウーラオスに進化する。",
"item.cobblemon.potato_mochi": "イモモチ",
"item.cobblemon.fresh_start_mochi": "まっさらもち",
"item.cobblemon.swift_mochi.tooltip": "きのみが ねりこまれた もち。ポケモン 1匹の 素早さの 基礎ポイントを 4 あげる。",
"item.cobblemon.swift_mochi.tooltip": "きのみが ねりこまれた もち。 ポケモン 1匹の 素早さの 基礎ポイントを 4 あげる。",
"cobblemon.species.meloetta-pirouette.desc": "長く 忘れられていた 歌を 取り戻した メロエッタは 魅惑の ステップで 誰しも 虜にする。",
"cobblemon.species.greninja-bond.desc": "忍者のように 神出鬼没。 素早い 動きで 翻弄しつつ 水の 手裏剣で 切り裂く。",
"item.cobblemon.saccharine_sapling": "あまったるい苗木",
"item.cobblemon.candied_apple": "りんごアメ",
"item.cobblemon.moomoo_milk": "モーモーミルク",
"cobblemon.species.genesect-ice.desc": "氷エネルギーが 充填された カセットを 装着した 姿。 慈悲の 心は 持っていない。",
"item.cobblemon.metal_alloy.tooltip": "いくつもの層が 重なっている 不思議な金属。ジュラルドンに使うと ブリジュラスに進化する。",
"item.cobblemon.metal_alloy.tooltip": "いくつもの層が 重なっている 不思議な金属。 ジュラルドンに使うと ブリジュラスに進化する。",
"item.cobblemon.genius_mochi": "ちりょくのもち",
"cobblemon.species.genesect-water.desc": "水エネルギーが 充填された カセットを 装着した 姿。 飛行形態で 空を飛ぶ。",
"item.cobblemon.health_mochi": "たいりょくのもち",
"item.cobblemon.health_mochi.tooltip": "きのみが ねりこまれた もち。ポケモン 1匹の HPの 基礎ポイントを 4 あげる。",
"item.cobblemon.clever_mochi.tooltip": "きのみが ねりこまれた もち。ポケモン 1匹の 特防の 基礎ポイントを 4 あげる。",
"item.cobblemon.health_mochi.tooltip": "きのみが ねりこまれた もち。 ポケモン 1匹の HPの 基礎ポイントを 4 あげる。",
"item.cobblemon.clever_mochi.tooltip": "きのみが ねりこまれた もち。 ポケモン 1匹の 特防の 基礎ポイントを 4 あげる。",
"cobblemon.species.greninja-ash.desc": "トレーナーとの キズナが 極限まで 高まったときに 見られる ゲッコウガの すがた。",
"cobblemon.ui.pokedex.info.form.greninja-ash": "サトシゲッコウガ",
"cobblemon.species.castform-sunny.desc": "暑い 日差しを 浴びていると この姿に 変わる。 火照った 身体を 触ると パサパサするぞ。",
@@ -67,7 +67,7 @@
"item.cobblemon.apricorn_chest_boat": "Bote de Azinheira com Baú",
"item.cobblemon.link_cable": "Cabo de Ligação",
"item.cobblemon.dragon_scale": "Escama de Dragão",
"item.cobblemon.kings_rock": "Pedra Rei",
"item.cobblemon.kings_rock": "Pedra do Rei",
"item.cobblemon.metal_coat": "Revestimento Metálico",
"item.cobblemon.upgrade": "Melhorador",
"item.cobblemon.dubious_disc": "Disco Dúbio",
@@ -134,15 +134,15 @@
"item.cobblemon.ability_capsule": "Cápsula de Habilidade",
"item.cobblemon.ability_patch": "Adesivo de Habilidade",
"item.cobblemon.red_mint_leaf": "Folha de Hortelã Vermelha",
"item.cobblemon.red_mint_leaf.tooltip": "Capaz de influenciar o atributo de ataque de um Pokémon",
"item.cobblemon.red_mint_leaf.tooltip": "Capaz de influenciar o atributo de Ataque de um Pokémon",
"item.cobblemon.blue_mint_leaf": "Folha de Hortelã Azul",
"item.cobblemon.blue_mint_leaf.tooltip": "Capaz de influenciar o atributo de Defesa de um Pokémon",
"item.cobblemon.cyan_mint_leaf": "Folha de Hortelã Ciano",
"item.cobblemon.cyan_mint_leaf.tooltip": "Capaz de influenciar o atributo de Ataque Especial de um Pokémon",
"item.cobblemon.pink_mint_leaf": "Folha de Hortelã Rosa",
"item.cobblemon.pink_mint_leaf.tooltip": "Capaz de influenciar o atributo de defesa especial de um Pokémon",
"item.cobblemon.pink_mint_leaf.tooltip": "Capaz de influenciar o atributo de Defesa Especial de um Pokémon",
"item.cobblemon.green_mint_leaf": "Folha de Hortelã Verde",
"item.cobblemon.green_mint_leaf.tooltip": "Capaz de influenciar o atributo de velocidade de um Pokémon",
"item.cobblemon.green_mint_leaf.tooltip": "Capaz de influenciar o atributo de Velocidade de um Pokémon",
"item.cobblemon.white_mint_leaf": "Folha de Hortelã Branca",
"item.cobblemon.white_mint_leaf.tooltip": "Capaz de neutralizar a natureza de um Pokémon",
"item.cobblemon.lonely_mint": "Hortelã Solitária",
@@ -708,7 +708,7 @@
"item.cobblemon.magost_berry": "Baga Magost",
"item.cobblemon.magost_berry.tooltip": "Não pode ser comido durante batalhas",
"item.cobblemon.maranga_berry": "Baga Maranga",
"item.cobblemon.maranga_berry.tooltip": "Aumenta a Defesa Especial do portador em 1 estágio após ser atingido por um ataque especial",
"item.cobblemon.maranga_berry.tooltip": "Aumenta a Defesa Especial do portador em 1 estágio após ser atingido por um movimento especial",
"item.cobblemon.micle_berry": "Baga Micle",
"item.cobblemon.micle_berry.tooltip": "O próximo movimento do portador tem 1.2x de precisão quando estiver com 1/4 ou menos do PV máximo",
"item.cobblemon.nanab_berry": "Baga Nanab",
@@ -3338,7 +3338,7 @@
"cobblemon.species.mudsdale.desc": "Ele pode percorrer estradas montanhosas sem descanso por três dias e três noites, enquanto arrasta uma carga de 10 toneladas.",
"cobblemon.species.goomy.desc": "Ele é coberto por uma membrana viscosa que faz com que qualquer soco ou chute deslize sem causar danos.",
"cobblemon.species.goodra.desc": "Ele ataca com chifres retráteis. Desfere um soco equivalente à força de cem boxeadores profissionais.",
"cobblemon.species.pumpkaboo.desc": "Diz-se que ela transporta espíritos errantes para o lugar onde pertencem, para que possam seguir em frente.",
"cobblemon.species.pumpkaboo.desc": "Recentemente foi descoberto que as diferentes variedades de Pumpkaboo não vairam apenas no tamanho mas também no tamanho das almas que eles coletam.",
"cobblemon.species.volcanion.desc": "Ele expele seu vapor interno dos braços em suas costas. Ele tem poder suficiente para explodir uma montanha.",
"cobblemon.species.bergmite.desc": "Usando ar de -150 graus Fahrenheit, eles congela os oponentes sólidos. Eles vivem em rebanhos acima da linha de neve nas montanhas.",
"cobblemon.species.zygarde.name": "Zygarde",
@@ -3438,7 +3438,7 @@
"cobblemon.species.trevenant.desc": "Usando suas raízes como sistema nervoso, ele controla as árvores da floresta. É gentil com os Pokémon que residem em seu corpo.",
"cobblemon.species.pumpkaboo.name": "Pumpkaboo",
"cobblemon.species.gourgeist.name": "Gourgeist",
"cobblemon.species.gourgeist.desc": "Ele envolve sua presa em seus braços peludos. Canta alegremente enquanto observa o sofrimento de sua presa.",
"cobblemon.species.gourgeist.desc": "Cantando com suas vozes sinistras, vagam pelas estradas das cidades em noites de lua cheia. Qualquer um que escuta sua canção é amaldiçoado.",
"cobblemon.species.bergmite.name": "Bergmite",
"cobblemon.species.avalugg.name": "Avalugg",
"cobblemon.species.avalugg.desc": "Usando ar de -150 graus Fahrenheit, eles congela os oponentes sólidos. Eles vivem em rebanhos acima da linha de neve nas montanhas.",
@@ -3513,7 +3513,7 @@
"cobblemon.species.pyukumuku.name": "Pyukumuku",
"cobblemon.species.pyukumuku.desc": "Seu corpo inteiro é coberto por sua própria gosma. Se você acidentalmente pisar em uma, você escorregará, e ela ficará brava e te baterá!",
"cobblemon.species.typenull.name": "Tipo: Nulo",
"cobblemon.species.silvally.desc": "Através do vínculo que formou com seu Treinador, sua vontade foi fortalecida e ele foi capaz de destruir sua máscara de controle.",
"cobblemon.species.silvally.desc": "Um forte vínculo de confiança entre este Pokémon e seu Treinador despertou a força escondida dentro de Silvally. Pode mudar seu tipo à vontade.",
"cobblemon.species.togedemaru.name": "Togedemaru",
"cobblemon.species.nihilego.name": "Nihilego",
"cobblemon.species.silvally.name": "Silvally",
@@ -3792,7 +3792,7 @@
"cobblemon.species.zacian.desc": "Conhecido como um herói lendário, este Pokémon absorve partículas de metal, transformando-as em uma arma que usa para batalhar.",
"cobblemon.species.zamazenta.name": "Zamazenta",
"cobblemon.species.eternatus.name": "Eternatus",
"cobblemon.species.eternatus.desc": "O núcleo em seu peito absorve a energia que emana das terras da região de Galar. Essa energia é o que permite que Eternatus permaneça ativo.",
"cobblemon.species.eternatus.desc": "Estava dentro de um meteorito que caiu há 20.000 anos. Parece haver uma conexão entre esse Pokémon e o fenômeno Dynamax.",
"cobblemon.species.kubfu.name": "Kubfu",
"cobblemon.species.urshifu.name": "Urshifu",
"cobblemon.species.urshifu.desc": "Esta forma de Urshifu acredita firmemente no nocaute com um golpe. Sua estratégia é saltar para perto dos inimigos e desferir um golpe devastador com o punho firme.",
@@ -3927,7 +3927,7 @@
"cobblemon.species.veluza.desc": "Quando Veluza descarta carne desnecessária, sua mente se torna afiada e seu poder psíquico aumenta. A carne sobrante tem um sabor suave, mas delicioso.",
"cobblemon.species.milcery.desc": "Este Pokémon nasceu de partículas de cheiro doce no ar. Seu corpo é feito de creme.",
"cobblemon.species.falinks.desc": "Cinco deles são soldados, e um é o chefe. As ordens do chefe são absolutas.",
"cobblemon.species.zamazenta.desc": "No passado, ele trabalhou em conjunto com um rei do povo para salvar a região de Galar. Ele absorve metal e o usa em batalha.",
"cobblemon.species.zamazenta.desc": "Esse Pokémon dormiu por eras em sua forma de estátua. Dormiu por tanto tempo que as pessoas equeceram que uma vez existiu.",
"cobblemon.species.spectrier.desc": "Ele sonda os arredores com todos os seus sentidos, exceto um — não usa a visão. Dizem que os chutes do Spectrier separam a alma do corpo.",
"cobblemon.species.sneasler.desc": "Devido ao veneno virulento e à descomunal destreza física de Sneasler, nenhuma outra espécie poderia vencê-lo nas terras altas congeladas. Preferindo a solidão, esta espécie não forma matilhas.",
"cobblemon.species.pawmi.desc": "Ele tem bolsas elétricas subdesenvolvidas em suas bochechas. Essas bolsas podem produzir eletricidade somente se Pawmi as esfregar furiosamente com as almofadas de suas patas dianteiras.",
@@ -5224,27 +5224,27 @@
"cobblemon.move.gmaxvoltcrash": "Trovoada G-Max",
"entity.cobblemon.poke_bobber": "Pokéboia",
"entity.cobblemon.boat": "Barco",
"cobblemon.ui.pokedex.info.form.venusaur-mega": "Mega",
"cobblemon.ui.pokedex.info.form.venusaur-mega": "Mega Venusaur",
"cobblemon.species.venusaur-mega.desc": "Para sustentar sua flor, que cresceu devido à Mega Evolução, suas costas e pernas ficaram mais fortes.",
"cobblemon.ui.pokedex.info.form.charizard-megay": "Mega Y",
"cobblemon.ui.pokedex.info.form.charizard-megay": "Mega Charizard Y",
"cobblemon.species.raticate-alola.desc": "Ele comanda um ninho de Rattata. Ninhos diferentes não se dão bem, o que gera brigas acirradas por áreas de alimentação.",
"cobblemon.ui.pokedex.info.form.sandshrew-alola": "Aloliano",
"cobblemon.battle.enditem.shucaberry": "A Baga Shuca enfraqueceu o dano de %1$s",
"cobblemon.battle.enditem.payapaberry": "A Baga Payapa enfraqueceu o dano de %1$s",
"cobblemon.ui.pokedex.info.form.muk-alola": "Aloliano",
"cobblemon.ui.pokedex.info.form.gengar-mega": "Mega",
"cobblemon.ui.pokedex.info.form.gengar-mega": "Mega Gengar",
"cobblemon.ui.pokedex.info.form.gengar-gmax": "Gigantamax",
"cobblemon.species.kingler-gmax.desc": "O fluxo de energia Gigantamax fez com que a pinça esquerda deste Pokémon crescesse até um tamanho enorme. Essa garra pode pulverizar qualquer coisa.",
"cobblemon.ui.pokedex.info.form.voltorb-hisui": "Hisuiano",
"cobblemon.species.voltorb-hisui.desc": "Um Pokémon enigmático que se parece com uma Pokébola. Quando excitado, ele descarrega a corrente elétrica armazenada em sua barriga e solta uma gargalhada estrondosa.",
"cobblemon.ui.pokedex.info.form.weezing-galar": "Galariano",
"cobblemon.ui.pokedex.info.form.kangaskhan-mega": "Mega",
"cobblemon.ui.pokedex.info.form.kangaskhan-mega": "Mega Kangaskhan",
"cobblemon.ui.pokedex.info.form.mrmime-galar": "Galariano",
"cobblemon.species.mrmime-galar.desc": "Seu talento é sapateado. Ele também pode manipular temperaturas para criar um piso de gelo, que este Pokémon pode levantar para usar como barreira.",
"cobblemon.ui.pokedex.info.form.lapras-gmax": "Gigantamax",
"cobblemon.ui.pokedex.info.form.aerodactyl-mega": "Mega",
"cobblemon.ui.pokedex.info.form.aerodactyl-mega": "Mega Aerodactyl",
"cobblemon.ui.pokedex.info.form.snorlax-gmax": "Gigantamax",
"cobblemon.ui.pokedex.info.form.mewtwo-megax": "Mega X",
"cobblemon.ui.pokedex.info.form.mewtwo-megax": "Mega Mewtwo X",
"cobblemon.ui.pokedex.info.form.typhlosion-hisui": "Hisuiano",
"cobblemon.move.boomburst": "Rajada Explosiva",
"cobblemon.move.bouncybubble": "Eevaporabolhas",
@@ -5271,7 +5271,7 @@
"cobblemon.ui.pokedex.info.form.gastrodon-east": "Mar do Leste",
"cobblemon.species.lopunny-mega.desc": "A Mega Evolução desperta seus instintos combativos. Ela se livrou de qualquer pelo que atrapalhasse seus ataques.",
"cobblemon.move.electroball": "Bola Elétrica",
"cobblemon.species.gallade-mega.desc": "Ecologia em estudo.",
"cobblemon.species.gallade-mega.desc": "Recebe seu poder do vínculo que tem com seu Treinador. A Mega Evolução o concedeu placas para fatiar inimigos e uma capa para proteger seu corpo.",
"cobblemon.ui.pokedex.info.form.palkia-origin": "Forma de Origem",
"cobblemon.ui.pokedex.info.form.darmanitan-zen": "Modo Zen",
"cobblemon.species.darmanitan-galar.desc": "Em dias de nevasca, ele se resume a onde as pessoas vivem. Ele guarda comida na bola de neve em sua cabeça e a leva para casa para mais tarde.",
@@ -5289,7 +5289,7 @@
"cobblemon.ui.pokedex.info.form.xerneas-active": "Modo Ativo",
"cobblemon.ui.pokedex.info.form.zygarde": "Forma 50%",
"cobblemon.move.ember": "Brasa",
"cobblemon.ui.pokedex.info.form.diancie-mega": "Mega",
"cobblemon.ui.pokedex.info.form.diancie-mega": "Mega Diancie",
"cobblemon.ui.pokedex.info.form.hoopa-unbound": "Hoopa Libertado",
"cobblemon.ui.pokedex.info.form.oricorio-pompom": "Estilo Pom-Pom",
"cobblemon.ui.pokedex.info.form.lycanroc": "Forma do Meio-Dia",
@@ -5351,7 +5351,7 @@
"item.cobblemon.mild_mint.tooltip": "Altera os atributos de um Pokémon para uma natureza Mansa",
"cobblemon.snapshots.warning.description": "Você está usando uma snapshot %s do Cobblemon. Os recursos nesta versão ainda estão em desenvolvimento e podem não ser seguros para usar em seus mundos. Deseja continuar ciente desses riscos?",
"item.cobblemon.npc_editor": "Cartão de Treinador NPC",
"item.cobblemon.link_cable.tooltip": "Evolui Pokémon que exigem troca",
"item.cobblemon.link_cable.tooltip": "Permite a evolução de um Pokémon que requer troca",
"item.cobblemon.dragon_scale.tooltip": "Evolui Seadra para Kingdra quando segurado durante a troca",
"item.cobblemon.kings_rock.tooltip_1": "Quando o portador inflige dano com sucesso, o alvo pode hesitar",
"item.cobblemon.kings_rock.tooltip_2": "Evolui Poliwhirl para Politoed e Slowpoke para Slowking quando segurado durante a troca",
@@ -5505,7 +5505,7 @@
"item.cobblemon.weakness_policy.tooltip_1": "Aumenta o Ataque e o Ataque Especial do portador quando atingido por um movimento supereficaz",
"item.cobblemon.weakness_policy.tooltip_2": "Consumido após o uso",
"item.cobblemon.wide_lens.tooltip": "Aumenta a Precisão do portador",
"item.cobblemon.wise_glasses.tooltip": "Aumenta o poder dos movimentos especiais",
"item.cobblemon.wise_glasses.tooltip": "Aumenta o poder de movimentos Especiais",
"item.cobblemon.mental_herb.tooltip_1": "Cura o portador da paixão e de outros efeitos mentais",
"item.cobblemon.mental_herb.tooltip_2": "Consumido após o uso",
"item.cobblemon.mirror_herb.tooltip_1": "Permite que o portador espelhe os aumentos de atributo do oponente para aumentar seus próprios atributos",
@@ -5513,7 +5513,7 @@
"item.cobblemon.misty_seed.tooltip": "Aumenta a Defesa Especial do portador em terrenos Enevoados",
"item.cobblemon.power_herb.tooltip_1": "Permite que o portador use imediatamente um movimento que normalmente requer a troca de turno para ser carregado",
"item.cobblemon.power_herb.tooltip_2": "Consumido após o uso",
"item.cobblemon.bright_powder.tooltip": "Reduz a Precisão dos movimentos dos pokémon inimigos em 10%",
"item.cobblemon.bright_powder.tooltip": "Reduz a Precisão dos movimentos dos Pokémon inimigos em 10%",
"item.cobblemon.metal_powder.tooltip": "Aumenta a Defesa e a Defesa Especial de um Ditto não transformado em 50%",
"item.cobblemon.quick_powder.tooltip": "Duplica a Velocidade de um Ditto não transformado",
"item.cobblemon.destiny_knot.tooltip": "Se o portador ficar apaixonado, o Pokémon pelo qual o portador está atraído também ficará apaixonado",
@@ -5821,12 +5821,12 @@
"cobblemon.mark.ribbon_contest_super_master_cleverness.title": "%1$s o Gênio Histórico",
"cobblemon.mark.ribbon_contest_super_star_twinkling.title": "%1$s a Estrela Cintilante",
"cobblemon.mark.ribbon_contest_super_star_twinkling.desc": "Uma Fita concedida a um Pokémon que tenha personificado perfeitamente o brilho radiante em Shows de Super Concurso.",
"cobblemon.mark.ribbon_day_alert.title": "%1$s o Outrora Vigilante",
"cobblemon.mark.ribbon_day_alert.title": "%1$s o Vigilante",
"cobblemon.mark.ribbon_day_alert.desc": "Uma Fita para relembrar um evento revigorante que gerou energia vital.",
"cobblemon.mark.ribbon_day_careless": "Fita Descuidada",
"cobblemon.mark.ribbon_day_careless.title": "%1$s o Outrora Imperfeito",
"cobblemon.mark.ribbon_day_careless.title": "%1$s o Imperfeito",
"cobblemon.mark.ribbon_effort": "Fita do Esforço",
"cobblemon.mark.ribbon_effort.title": "%1$s o Outrora Preparado",
"cobblemon.mark.ribbon_effort.title": "%1$s o Preparado",
"cobblemon.mark.ribbon_event.title": "%1$s o Festivo",
"cobblemon.mark.ribbon_event.desc": "Uma Fita concedida por participar de um evento especial.",
"cobblemon.mark.ribbon_event_birthday": "Fita de Aniversário",
@@ -5861,7 +5861,7 @@
"cobblemon.mark.ribbon_syndicate_gorgeous.desc": "Uma fita extraordinariamente linda e extravagante.",
"cobblemon.mark.ribbon_training.title": "%1$s o Posto à Prova",
"cobblemon.mark.mark_alpha": "Marca Alfa",
"cobblemon.mark.mark_alpha.title": "%1$s o Antigo Alfa",
"cobblemon.mark.mark_alpha.title": "%1$s o Alfa",
"cobblemon.mark.mark_itemfinder.title": "%1$s o Caçador de Tesouros",
"cobblemon.mark.mark_itemfinder.desc": "Uma marca para um Pokémon que gosta de pegar coisas.",
"cobblemon.mark.mark_mightiest": "Marca Mais Poderosa",
@@ -5879,8 +5879,8 @@
"cobblemon.mark.mark_revival.title": "%1$s o Ressuscitado",
"cobblemon.mark.mark_revival.desc": "Uma marca para um Pokémon ressuscitado.",
"cobblemon.mark.mark_titan": "Marca do Titã",
"cobblemon.mark.mark_titan.title": "%1$s o Antigo Titã",
"cobblemon.mark.mark_titan.desc": "Uma marca para um Pokémon que era um Titã.",
"cobblemon.mark.mark_titan.title": "%1$s o Titã",
"cobblemon.mark.mark_titan.desc": "Uma marca para um Pokémon que é um Titã.",
"cobblemon.mark.mark_uncommon": "Marca Incomum",
"cobblemon.mark.mark_uncommon.title": "%1$s o Sociável",
"cobblemon.mark.mark_uncommon.desc": "Uma marca para um Pokémon sociável.",
@@ -7499,7 +7499,7 @@
"cobblemon.species.charizard-megax.desc": "O poder avassalador que preenche todo o seu corpo faz com que ele fique preto e crie intensas chamas azuis.",
"cobblemon.species.charizard-megay.desc": "Seu vínculo com seu Treinador é a fonte de seu poder. Ele ostenta velocidade e manobrabilidade maiores que as de um caça a jato.",
"cobblemon.ui.pokedex.info.form.charizard-gmax": "Gigantamax",
"cobblemon.ui.pokedex.info.form.blastoise-mega": "Mega",
"cobblemon.ui.pokedex.info.form.blastoise-mega": "Mega Blastoise",
"cobblemon.species.blastoise-mega.desc": "O canhão em suas costas é tão poderoso quanto um canhão de tanque. Suas pernas e costas robustas permitem que ele resista ao recuo do disparo do canhão.",
"cobblemon.ui.pokedex.info.form.blastoise-gmax": "Gigantamax",
"cobblemon.species.blastoise-gmax.desc": "Ele não é muito bom em tiros de precisão. Ao atacar, ele simplesmente dispara seus 31 canhões repetidamente.",
@@ -7572,12 +7572,12 @@
"cobblemon.species.golem-alola.desc": "Ele atira grandes pedras carregadas de eletricidade. Choques elétricos tremendos são lançados por toda a área de impacto.",
"cobblemon.species.ponyta-galar.desc": "Seu pequeno chifre esconde um poder de cura. Com algumas esfregadas no chifre deste Pokémon, qualquer ferimento leve que você tenha será curado.",
"cobblemon.species.slowpoke-galar.desc": "Embora este Pokémon normalmente fique distraído, sua expressão se intensifica abruptamente de vez em quando. A causa disso parece estar na dieta do Slowpoke.",
"cobblemon.ui.pokedex.info.form.slowbro-mega": "Mega",
"cobblemon.ui.pokedex.info.form.slowbro-mega": "Mega Slowbro",
"cobblemon.species.slowbro-mega.desc": "Depois de ter sido engolido por inteiro por Shellder, Slowbro agora tem uma defesa de ferro. É bem confortável lá dentro também.",
"cobblemon.species.slowbro-galar.desc": "A mordida de Shellder desencadeou uma reação química com as especiarias dentro do corpo de Slowbro, fazendo com que Slowbro se tornasse um Pokémon do tipo Venenoso.",
"cobblemon.species.farfetchd-galar.desc": "Os talos do alho-poró são mais grossos e longos na região de Galar. O Farfetch'd que se adaptou a esses talos assumiu uma forma única.",
"cobblemon.species.farfetchd-galar.desc": "Carregar um alho-poró grande e pesado fortaleceu seu corpo. Em batalha, aposta tudo em um único golpe destrutivo.",
"cobblemon.ui.pokedex.info.form.grimer-alola": "Aloliano",
"cobblemon.species.grimer-alola.desc": "Trazido para Alola para resolver o problema do lixo, Grimer parece gostar de todo e qualquer tipo de lixo.",
"cobblemon.species.grimer-alola.desc": "Os cristais no corpo de Grimer são protuberâncias feitas de toxinas. Se uma se desprender, começa a liberar veneno.",
"cobblemon.species.muk-alola.desc": "O que parecem presas e garras são, na verdade, veneno cristalizado que pode afligir você com um simples toque, então não chegue muito perto.",
"cobblemon.species.gengar-mega.desc": "A Mega Evolução possibilitou que Gengar acessasse outras dimensões. Seu corpo inteiro está repleto de um poder estranho.",
"cobblemon.species.gengar-gmax.desc": "Dizem que sua boca gigantesca não leva ao seu corpo, cheio de energia amaldiçoada, mas diretamente à vida após a morte.",
@@ -7596,10 +7596,10 @@
"cobblemon.move.sludgewave": "Onda de Lama",
"cobblemon.move.reflecttype": "Clonatipo",
"cobblemon.species.pinsir-mega.desc": "Ele voa a velocidades estonteantes, procurando uma abertura para espetar seu oponente com suas pinças gigantes.",
"cobblemon.ui.pokedex.info.form.tauros-paldeacombat": "Raça de Combate (Paldean)",
"cobblemon.ui.pokedex.info.form.tauros-paldeacombat": "Paldeano (Raça de Combate)",
"cobblemon.species.tauros-paldeacombat.desc": "Este Pokémon tem um corpo musculoso e é excelente em combate corpo a corpo. Ele usa seus chifres curtos para atingir os pontos fracos do oponente.",
"cobblemon.species.tauros-paldeablaze.desc": "Quando aquecidos pela energia do fogo, seus chifres podem atingir temperaturas superiores a 1.800 graus Fahrenheit. Aqueles que forem atingidos por eles sofrerão ferimentos e queimaduras.",
"cobblemon.ui.pokedex.info.form.tauros-paldeaaqua": "Raça da Água (Paldean)",
"cobblemon.ui.pokedex.info.form.tauros-paldeaaqua": "Paldeano (Raça da Água)",
"cobblemon.species.tauros-paldeaaqua.desc": "Este Pokémon lança água por buracos nas pontas dos seus chifres — os jatos de alta pressão perfuram os inimigos de Tauros.",
"cobblemon.species.lapras-gmax.desc": "Mais de 5.000 pessoas podem andar em sua estrutura ao mesmo tempo. E é um passeio muito confortável, sem o menor tremor ou balanço.",
"cobblemon.ui.pokedex.info.form.eevee-gmax": "Gigantamax",
@@ -7643,15 +7643,15 @@
"cobblemon.species.unown-y.desc": "Este Pokémon tem o formato de uma escrita antiga. É um mistério o que surgiu primeiro, as escritas antigas ou os vários Unown. Pesquisas sobre este tópico estão em andamento, mas nada se sabe.",
"cobblemon.species.unown-!.desc": "Este punho tem forma como uma escrita antiga. É um mistério qual veio primeiro, os escritos antigos ou os vários Unown. A investigação sobre este tema está em curso, mas nada é conhecido.",
"cobblemon.ui.pokedex.info.form.unown-?": "Forma",
"cobblemon.ui.pokedex.info.form.steelix-mega": "Mega",
"cobblemon.species.steelix-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.steelix-mega": "Mega Steelix",
"cobblemon.species.steelix-mega.desc": "Para se proteger dos ataques de seus oponentes, usa magnetismo para controlar peças que se desprenderam de sua carapaça exterior.",
"cobblemon.species.corsola-galar.desc": "Cuidado com os passos ao vagar por áreas que antes eram cobertas por oceanos. O que parece uma pedra pode ser este Pokémon, e ele vai te amaldiçoar se você chutá-lo.",
"cobblemon.move.sandsearstorm.desc": "O usuário ataca envolvendo os Pokémon oponentes em ventos fortes e areia escaldante. Isso também pode deixá-los com uma queimadura.",
"cobblemon.move.lunarblessing": "Bênção Lunar",
"cobblemon.species.houndoom-mega.desc": "Todo o corpo de Houndoom gera calor quando ele Mega Evolui. Seu temível sopro de fogo transforma seus oponentes em cinzas.",
"cobblemon.move.icespinner": "Girador de Gelo",
"cobblemon.ui.pokedex.info.form.sceptile-mega": "Mega",
"cobblemon.species.sceptile-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.sceptile-mega": "Mega Sceptile",
"cobblemon.species.sceptile-mega.desc": "As sementes em suas costas contém energia da Mega Evolução. O Pokémon detona essas sementes para disparar a ponta de sua cauda.",
"cobblemon.species.linoone-galar.desc": "Ele usa sua longa língua para provocar os oponentes. Quando o oponente fica enfurecido, este Pokémon se lança contra ele, derrubando-o com força.",
"cobblemon.move.ragingbull": "Investida Furiosa",
"cobblemon.move.tidyup": "Arrumar",
@@ -7664,7 +7664,7 @@
"cobblemon.move.gmaxdepletion": "Esgotamento G-Max",
"cobblemon.move.gmaxdrumsolo": "Solo de Tambores G-Max",
"cobblemon.move.gmaxfinale": "Grande Final G-Max",
"cobblemon.species.camerupt-mega.desc": "Ecologia em estudo.",
"cobblemon.species.camerupt-mega.desc": "Quando a fúria deste Pokémon atinge o ponto de ebulição, o enorme vulcão na corcunda em suas costas entra em erupção de forma violenta, lançando lava para o alto.",
"cobblemon.move.gmaxgoldrush": "Corrida do Ouro G-Max",
"cobblemon.move.gmaxgravitas": "Seriedade G-Max",
"cobblemon.move.gmaxmeltdown": "Colapso do G-Max",
@@ -7681,7 +7681,7 @@
"cobblemon.species.absol-mega.desc": "Ele converte a energia da Mega Evolução em uma aura intimidadora. Pessoas medrosas morrem de choque ao vê-lo.",
"cobblemon.species.glalie-mega.desc": "O poder da Mega Evolução era tão forte que esmagou o maxilar de Glalie. Sua incapacidade de comer direito o deixa irritado.",
"cobblemon.species.salamence-mega.desc": "Ele coloca as patas dianteiras dentro da carapaça para se tornar aerodinâmico durante o voo. O salamence voa em alta velocidade sobre todos os tipos de acidentes topográficos.",
"cobblemon.ui.pokedex.info.form.metagross-mega": "Mega",
"cobblemon.ui.pokedex.info.form.metagross-mega": "Mega Metagross",
"cobblemon.species.rayquaza-mega.desc": "Ele voa eternamente pela camada de ozônio, consumindo meteoroides para se sustentar. Os muitos meteoroides em seu corpo fornecem a energia necessária para sua Mega Evolução.",
"cobblemon.ui.pokedex.info.form.meowth-galar": "Galariano",
"cobblemon.species.wormadam-sandy.desc": "Sua pele de terra é razoavelmente dura — pelo menos não tem problema em repelir as bicadas de um Starly.",
@@ -7690,8 +7690,8 @@
"cobblemon.ui.pokedex.info.form.shellos": "Mar do Oeste",
"cobblemon.species.shellos-east.desc": "Cientistas interessados em suas grandes capacidades regenerativas estão atualmente analisando os materiais dos quais suas células são feitas.",
"cobblemon.species.gastrodon-east.desc": "Parente de Shellder e Cloyster, esse habitante do oceano às vezes vem à terra em busca de alimento.",
"cobblemon.ui.pokedex.info.form.abomasnow-mega": "Mega",
"cobblemon.species.abomasnow-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.abomasnow-mega": "Mega Abomasnow",
"cobblemon.species.abomasnow-mega.desc": "Os botões em suas costas geraram sincelos impressionantes que podem iniciar nevascas imensas de -30 graus Celsius.",
"cobblemon.ui.pokedex.info.form.machamp-gmax": "Gigantamax",
"cobblemon.ui.pokedex.info.form.rotom-heat": "Rotom Calor",
"cobblemon.species.rotom-heat.desc": "Este Rotom possui um forno de micro-ondas de convecção que utiliza um motor especial. Ele também tem um talento especial para manipular chamas.",
@@ -7727,13 +7727,13 @@
"cobblemon.ui.pokedex.info.form.arceus-fairy": "Arceus",
"cobblemon.species.arceus-fairy.desc": "Diz a mitologia que este Pokémon nasceu antes mesmo do universo existir.",
"cobblemon.species.samurott-hisui.desc": "De coração duro e hábil com a lâmina, esta forma rara de Samurott é um produto da evolução dos Pokémon na região de Hisui. Seus golpes turbulentos atingem os inimigos como ondas incessantes.",
"cobblemon.species.audino-mega.desc": "Ecologia em estudo.",
"cobblemon.species.audino-mega.desc": "Qualquer um que toque nas antenas secundárias que brotaram da base de sua garganta cairão em um sono profundo.",
"cobblemon.species.basculin-white.desc": "Eles vivem em mares gelados, formando cardumes e compartilhando comida entre si. Quando chega a hora, retornam ao rio onde nasceram.",
"cobblemon.species.darumaka-galar.desc": "Ele viveu em áreas nevadas por tanto tempo que sua bolsa de fogo esfriou e atrofiou. Agora, ele tem um órgão que gera frio.",
"cobblemon.ui.pokedex.info.form.darmanitan": "Modo Padrão",
"cobblemon.species.darmanitan-zen.desc": "Por meio da meditação, ele acalma seu espírito furioso e aprimora seus poderes psíquicos.",
"cobblemon.ui.pokedex.info.form.darmanitan-galar": "Modo Padrão (Galariano)",
"cobblemon.ui.pokedex.info.form.darmanitan-galarzen": "Modo Zen (Galariano)",
"cobblemon.ui.pokedex.info.form.darmanitan-galar": "Galariano (Modo Padrão)",
"cobblemon.ui.pokedex.info.form.darmanitan-galarzen": "Galariano (Modo Zen)",
"cobblemon.species.darmanitan-galarzen.desc": "A raiva reacendeu sua bolsa de chamas atrofiada. Este Pokémon cospe fogo por toda parte enquanto ataca indiscriminadamente.",
"cobblemon.species.zoroark-hisui.desc": "Com sua pelagem branca e desgrenhada, parece a personificação da morte. Despreocupado com sua própria segurança, Zoroark ataca seus inimigos com uma energia amarga tão intensa que dilacera seu próprio corpo.",
"cobblemon.ui.pokedex.info.form.deerling": "Forma de Primavera",
@@ -7790,21 +7790,21 @@
"cobblemon.species.meowstic-f.desc": "As fêmeas são um pouco mais egoístas e agressivas que os machos. Se não conseguirem o que querem, elas vão atormentar você com suas habilidades psíquicas.",
"cobblemon.ui.pokedex.info.form.aegislash": "Forma de Escudo",
"cobblemon.ui.pokedex.info.form.sliggoo-hisui": "Hisuiano",
"cobblemon.species.sliggoo-hisui.desc": "Uma criatura propensa à melancolia. Suspeito que sua carapaça metálica se desenvolveu como resultado da reação do muco em sua pele com o ferro presente na água de Hisui.",
"cobblemon.species.sliggoo-hisui.desc": "O ferro na água que Sliggoo bebe deu a consistência metálica de seu casco. O Pokémon não sai do seu casco em dias ensolarados.",
"cobblemon.species.goodra-hisui.desc": "Capaz de controlar livremente a dureza de sua carapaça metálica. Ele detesta a solidão e é extremamente apegado — ele ficará furioso e enfurecido se aqueles que lhe são mais queridos o abandonarem.",
"cobblemon.ui.pokedex.info.form.pumpkaboo": "Tamanho Médio",
"cobblemon.ui.pokedex.info.form.pumpkaboo-small": "Tamanho Pequeno",
"cobblemon.species.pumpkaboo-small.desc": "Ao levar espíritos para a vida após a morte, os pequenos Pumpkaboo preferem os espíritos de crianças aos de adultos.",
"cobblemon.species.pumpkaboo-large.desc": "Ao levar espíritos para a vida após a morte, os Pumpkaboo grandes preferem os espíritos de adultos aos de crianças.",
"cobblemon.ui.pokedex.info.form.pumpkaboo-super": "Tamanho Enorme",
"cobblemon.species.pumpkaboo-super.desc": "Pumpkaboos gigantescos são muito apegados aos espíritos de pessoas que possuem proporções igualmente superiores.",
"cobblemon.ui.pokedex.info.form.gourgeist": "Tamanho Médio",
"cobblemon.ui.pokedex.info.form.gourgeist-small": "Tamanho Pequeno",
"cobblemon.ui.pokedex.info.form.pumpkaboo": "Variedade Mediana",
"cobblemon.ui.pokedex.info.form.pumpkaboo-small": "Variedade Pequena",
"cobblemon.species.pumpkaboo-small.desc": "Fazendo juz ao tamanho de seu corpo, essa variedade de Pumpkaboo leva os pequenos espíritos de crianças para o pós-vida.",
"cobblemon.species.pumpkaboo-large.desc": "Fazendo juz ao tamanho de seu corpo, essa variedade de Pumpkaboo leva os grandes espíritos de adultos para o pós-vida.",
"cobblemon.ui.pokedex.info.form.pumpkaboo-super": "Variedade Enorme",
"cobblemon.species.pumpkaboo-super.desc": "Fazendo jus ao tamanho de seu corpo, essa variedade de Pumpkaboo leva espíritos enormes para o pós-vida.",
"cobblemon.ui.pokedex.info.form.gourgeist": "Variedade Mediana",
"cobblemon.ui.pokedex.info.form.gourgeist-small": "Variedade Pequena",
"cobblemon.species.gourgeist-small.desc": "Pequenos Gourgeistas fingem ser crianças para enganar adultos. Qualquer um que caia nessa farsa é levado para o além.",
"cobblemon.ui.pokedex.info.form.gourgeist-large": "Tamanho Grande",
"cobblemon.ui.pokedex.info.form.gourgeist-large": "Variedade Grande",
"cobblemon.species.gourgeist-large.desc": "Grandes Gourgeist assumem o disfarce de adultos, pegando nas mãos de crianças para guiá-las para a vida após a morte.",
"cobblemon.ui.pokedex.info.form.gourgeist-super": "Tamanho Enorme",
"cobblemon.species.gourgeist-super.desc": "Gourgeist gigantes não são exigentes. Eles arrastam qualquer um à força para a vida após a morte.",
"cobblemon.ui.pokedex.info.form.gourgeist-super": "Variedade Enorme",
"cobblemon.species.gourgeist-super.desc": "Gourgeist enormes não são meticulosos. Eles arrastam qualquer um à força para a vida após a morte.",
"cobblemon.species.avalugg-hisui.desc": "A armadura de gelo que cobre sua mandíbula inferior supera o aço e pode quebrar pedras com facilidade. Este Pokémon avança por trilhas íngremes nas montanhas, cortando a neve profunda.",
"cobblemon.species.xerneas-active.desc": "Quando os chifres em sua cabeça brilham em sete cores, diz-se que ele compartilha a vida eterna.",
"cobblemon.ui.pokedex.info.form.zygarde-10": "Forma 10%",
@@ -7815,7 +7815,7 @@
"cobblemon.species.zygarde-50c.desc": "Alguns dizem que ele pode se transformar em uma forma ainda mais poderosa ao lutar contra aqueles que ameaçam o ecossistema.",
"cobblemon.ui.pokedex.info.form.zygarde-complete": "Forma Completa",
"cobblemon.species.zygarde-complete.desc": "Nascido quando todas as células de Zygarde foram reunidas, ele usa a força para neutralizar aqueles que prejudicam o ecossistema.",
"cobblemon.species.diancie-mega.desc": "Ecologia em estudo.",
"cobblemon.species.diancie-mega.desc": "Esse Pokémon também é conhecido como a Princesa Rosa Real. O diamante deslumbrante e cintilante em sua testa tem impressionantes 2.000 quilates.",
"cobblemon.ui.pokedex.info.form.hoopa": "Hoopa Confinado",
"cobblemon.species.hoopa-unbound.desc": "Em sua verdadeira forma, ele possui uma quantidade enorme de poder. Lendas sobre sua avareza contam como ele certa vez roubou um castelo inteiro para obter o tesouro escondido nele.",
"cobblemon.species.decidueye-hisui.desc": "O ar armazenado dentro das ráquis das penas de Decidueye isola o Pokémon do frio extremo de Hisui. Esta é uma prova cabal de que a evolução pode ser influenciada pelo ambiente.",
@@ -7834,20 +7834,20 @@
"cobblemon.ui.pokedex.info.form.wishiwashi": "Forma Solo",
"cobblemon.species.wishiwashi-school.desc": "Chamados de \"demônios do mar\" por alguns, quando os Wishiwashi são feridos em batalha e seus números diminuem, eles se tornam uma escola regular.",
"cobblemon.ui.pokedex.info.form.silvally-rock": "Tipo: Pedra",
"cobblemon.species.silvally-rock.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-rock.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Pedra para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-bug": "Tipo: Inseto",
"cobblemon.species.silvally-grass.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-electric.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-grass.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Grama para se assemelhar à memória que tem equipada.",
"cobblemon.species.silvally-electric.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Elétrico para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-psychic": "Tipo: Psíquico",
"cobblemon.species.silvally-psychic.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-psychic.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Psíquico para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-ice": "Tipo: Gelo",
"cobblemon.species.silvally-ice.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-ice.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Gelo para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-dragon": "Tipo: Dragão",
"cobblemon.species.silvally-dragon.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-dragon.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Dragão para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-dark": "Tipo: Escuro",
"cobblemon.species.silvally-dark.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-dark.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Sombrio para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-fairy": "Tipo: Fada",
"cobblemon.species.silvally-fairy.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-fairy.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Fada para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.minior": "Núcleo",
"cobblemon.species.minior-indigo.desc": "Esta é a sua forma quando a casca cai. A cor do seu núcleo depende dos materiais que compunham o alimento que consumia.",
"cobblemon.ui.pokedex.info.form.minior-violet": "Núcleo Violeta",
@@ -7884,7 +7884,7 @@
"cobblemon.ui.pokedex.info.form.rapidash-galar": "Galariano",
"cobblemon.species.hatterene-gmax.desc": "Este Pokémon consegue ler as emoções de criaturas a mais de 48 quilômetros de distância. No minuto em que sente hostilidade, parte para o ataque.",
"cobblemon.ui.pokedex.info.form.hatterene-gmax": "Gigantamax",
"cobblemon.species.grimmsnarl-gmax.desc": "Ao transformar os pelos das pernas, este Pokémon desfere chutes poderosos que podem abrir buracos enormes no terreno de Galar.",
"cobblemon.species.grimmsnarl-gmax.desc": "Energia Gigantamax fez com que mais cabelo surgisse por todo seu corpo. Com a força adquirida, pode saltar por cima do prédio mais alto do mundo.",
"cobblemon.species.alcremie-rubycream.desc": "No momento em que evoluiu, adquiriu um sabor doce e ácido. Isso se deve à forma como suas células se modificaram espontaneamente durante a evolução.",
"cobblemon.species.alcremie-matchacream.desc": "No momento em que evoluiu, adquiriu um sabor aromático. Isso se deve à forma como suas células se modificaram espontaneamente durante a evolução.",
"cobblemon.species.alcremie-mintcream.desc": "No momento em que evoluiu, adquiriu um sabor refrescante. Isso se deve à forma como suas células se transformaram espontaneamente durante a evolução.",
@@ -7906,7 +7906,7 @@
"cobblemon.species.zacian-crowned.desc": "Agora armado com uma arma que usava nos tempos antigos, este Pokémon precisa de apenas um único golpe para derrubar até mesmo Pokémon Gigantamax.",
"cobblemon.ui.pokedex.info.form.zamazenta-crowned": "Escudo Coroado",
"cobblemon.species.zamazenta-crowned.desc": "Sua capacidade de desviar de qualquer ataque o levou a ser conhecido como o Escudo do Mestre Lutador. Era temido e respeitado por todos.",
"cobblemon.species.eternatus-eternamax.desc": "Como resultado da intromissão de Rose, Eternatus absorveu toda a energia da região de Galar. Agora está em um estado de sobrecarga de energia.",
"cobblemon.species.eternatus-eternamax.desc": "Quantidades infinitas de energia são produzidas pelo núcleo aumentado deste Pokémon, distorcendo o espaço-tempo ao seu redor.",
"cobblemon.ui.pokedex.info.form.urshifu": "Estilo de Golpe Único",
"cobblemon.ui.pokedex.info.form.urshifu-rapidstrike": "Estilo de Ataque Rápido",
"cobblemon.species.urshifu-rapidstrike.desc": "Acredita-se que este Pokémon modelou seu estilo de luta no fluxo de um rio — às vezes rápido, às vezes calmo.",
@@ -7915,7 +7915,7 @@
"cobblemon.species.zarude-dada.desc": "Este Zarude deixou sua matilha para criar uma criança humana. O pano com que Zarude envolvia a criança tinha um aroma reconfortante que acalmava o choro da criança.",
"cobblemon.ui.pokedex.info.form.calyrex-ice": "Cavaleiro de Gelo",
"cobblemon.ui.pokedex.info.form.calyrex-shadow": "Cavaleiro das Sombras",
"cobblemon.species.calyrex-shadow.desc": "Diz-se que Calyrex e um Pokémon que se uniu a ele correram por toda a região de Galar para trazer verde às terras devastadas.",
"cobblemon.species.calyrex-shadow.desc": "Reza a lenda de que, ao usar seus poderes para ver todos os eventos do passado e do futuro, esse Pokémon salvou as criaturas de uma floresta do impacto de um meteorito.",
"cobblemon.species.calyrex-ice.desc": "De acordo com a tradição, este Pokémon não demonstrava misericórdia para com aqueles que cruzavam seu caminho, mas ainda assim curava os ferimentos de seus oponentes após a batalha.",
"cobblemon.species.ursaluna-bloodmoon.desc": "Ele cruzou o mar e chegou à costa em uma nova terra. A sobrevivência neste lugar o levou a assumir uma aparência única e a ganhar poderes especiais.",
"cobblemon.ui.pokedex.info.form.enamorus-therian": "Forma Therian",
@@ -8014,13 +8014,13 @@
"cobblemon.ui.pokedex.info.form.unown-t": "Forma",
"cobblemon.ui.pokedex.info.form.unown-u": "Forma",
"cobblemon.ui.pokedex.info.form.unown-v": "Forma",
"cobblemon.ui.pokedex.info.form.blaziken-mega": "Mega",
"cobblemon.species.blaziken-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.medicham-mega": "Mega",
"cobblemon.ui.pokedex.info.form.absol-mega": "Mega",
"cobblemon.ui.pokedex.info.form.blaziken-mega": "Mega Blaziken",
"cobblemon.species.blaziken-mega.desc": "Sangue fervendo corre por todo seu corpo, duplicando a precisão de seus movimentos. Subjuga seus oponentes com um piscar de olhos.",
"cobblemon.ui.pokedex.info.form.medicham-mega": "Mega Medicham",
"cobblemon.ui.pokedex.info.form.absol-mega": "Mega Absol",
"cobblemon.ui.pokedex.info.form.rotom-wash": "Rotom Lavagem",
"cobblemon.ui.pokedex.info.form.darumaka-galar": "Galariano",
"cobblemon.ui.pokedex.info.form.genesect-water": "Genesect",
"cobblemon.ui.pokedex.info.form.genesect-water": "Disco Hídrico",
"cobblemon.ui.pokedex.info.form.flabebe-white": "Flor Branca",
"cobblemon.ui.pokedex.info.form.minior-red": "Núcleo Vermelho",
"cobblemon.ui.pokedex.info.form.alcremie-matchacream": "Creme de Matcha",
@@ -8246,9 +8246,9 @@
"painting.cobblemon.altar.title": "Altar",
"cobblemon.move.leer": "Encarar",
"cobblemon.move.mistball": "Bola de Névoa",
"cobblemon.ui.pokedex.info.form.charizard-megax": "Mega X",
"cobblemon.ui.pokedex.info.form.charizard-megax": "Mega Charizard X",
"cobblemon.ui.pokedex.info.form.butterfree-gmax": "Gigantamax",
"cobblemon.ui.pokedex.info.form.pidgeot-mega": "Mega",
"cobblemon.ui.pokedex.info.form.pidgeot-mega": "Mega Pidgeot",
"cobblemon.ui.pokedex.info.form.rattata-alola": "Aloliano",
"cobblemon.species.rattata-alola.desc": "Noite após noite, eles esgueiram nas casas das pessoas à procura de comida. Um surto maciço delas tornou-se uma questão de preocupação pública.",
"cobblemon.ui.pokedex.info.form.pikachu-original": "Boné original",
@@ -8278,35 +8278,35 @@
"cobblemon.ui.pokedex.info.form.unown-z": "Forma",
"cobblemon.species.unown-z.desc": "Este Pokémon tem o formato de uma escrita antiga. É um mistério o que surgiu primeiro, as escritas antigas ou os vários Unown. Pesquisas sobre este tópico estão em andamento, mas nada se sabe.",
"cobblemon.ui.pokedex.info.form.unown-!": "Forma",
"cobblemon.ui.pokedex.info.form.heracross-mega": "Mega",
"cobblemon.ui.pokedex.info.form.heracross-mega": "Mega Heracross",
"cobblemon.ui.pokedex.info.form.sneasel-hisui": "Hisuiano",
"cobblemon.species.sneasel-hisui.desc": "Suas fortes garras curvadas são ideais para escalar penhascos íngremes. Das pontas dessas garras escorre um veneno que se infiltra nos nervos de qualquer presa capturada por Sneasel.",
"cobblemon.ui.pokedex.info.form.corsola-galar": "Galariano",
"cobblemon.ui.pokedex.info.form.swampert-mega": "Mega",
"cobblemon.species.swampert-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.swampert-mega": "Mega Swampert",
"cobblemon.species.swampert-mega.desc": "Usando os mesmos princípios de uma bomba hidráulica, a água dentro de seu corpo fortalece ainda mais seus músculos já avantajados.",
"cobblemon.ui.pokedex.info.form.zigzagoon-galar": "Galariano",
"cobblemon.ui.pokedex.info.form.linoone-galar": "Galariano",
"cobblemon.species.gardevoir-mega.desc": "Ecologia em estudo.",
"cobblemon.species.gardevoir-mega.desc": "Quando abre a placa avermelhada em seu peito e revela seu coração, seu poder psíquico mais forte é liberado.",
"cobblemon.species.sableye-mega.desc": "Ele bloqueia todo e qualquer ataque com sua pedra preciosa gigante. No entanto, a pedra é um fardo pesado e limita os movimentos do Mega Sableye.",
"cobblemon.species.mawile-mega.desc": "Seus dois pares de mandíbulas se debatem violentamente como se cada um tivesse vontade própria. Um único ranger pode transformar uma pedra em pó.",
"cobblemon.species.medicham-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.manectric-mega": "Mega",
"cobblemon.ui.pokedex.info.form.sharpedo-mega": "Mega",
"cobblemon.ui.pokedex.info.form.altaria-mega": "Mega",
"cobblemon.species.altaria-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.latios-mega": "Mega",
"cobblemon.species.latios-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.rayquaza-mega": "Mega",
"cobblemon.species.medicham-mega.desc": "Graças à Mega Evolução, seu poder mental é ilimitado. Conjura braços imbuidos com malícia para derrotar seus inimigos.",
"cobblemon.ui.pokedex.info.form.manectric-mega": "Mega Manectric",
"cobblemon.ui.pokedex.info.form.sharpedo-mega": "Mega Sharpedo",
"cobblemon.ui.pokedex.info.form.altaria-mega": "Mega Altaria",
"cobblemon.species.altaria-mega.desc": "Sua plumagem é tão suave que a faz parecer sensível ao mais simples toque. Mas na realidade seus fios são fortes o suficente para içar um caminhão.",
"cobblemon.ui.pokedex.info.form.latios-mega": "Mega Latios",
"cobblemon.species.latios-mega.desc": "Voa em velocidades superiores a Mach 4. Está entre a elite dos Pokémon em termos de capacidade de combate aéreo.",
"cobblemon.ui.pokedex.info.form.rayquaza-mega": "Mega Rayquaza",
"cobblemon.ui.pokedex.info.form.wormadam": "Manto de Planta",
"cobblemon.species.cherrim-sunshine.desc": "Após absorver bastante luz solar, Cherrim assume esta forma. Ela é cheia de energia enquanto está assim, e sua vivacidade perdura até o pôr do sol.",
"cobblemon.ui.pokedex.info.form.garchomp-mega": "Mega",
"cobblemon.ui.pokedex.info.form.garchomp-mega": "Mega Garchomp",
"cobblemon.species.garchomp-mega.desc": "Sua disposição está mais cruel do que antes de sua Mega Evolução. Garchomp retalha seus oponentes com as foices em ambos os braços.",
"cobblemon.ui.pokedex.info.form.lucario-mega": "Mega",
"cobblemon.ui.pokedex.info.form.lucario-mega": "Mega Lucario",
"cobblemon.species.lucario-mega.desc": "Banhado em energia explosiva, seus instintos combativos despertaram. Para seus inimigos, ele não tem misericórdia alguma.",
"cobblemon.ui.pokedex.info.form.arceus-ghost": "Arceus",
"cobblemon.species.arceus-ghost.desc": "Diz a mitologia que este Pokémon nasceu antes mesmo do universo existir.",
"cobblemon.ui.pokedex.info.form.arceus-ice": "Arceus",
"cobblemon.ui.pokedex.info.form.audino-mega": "Mega",
"cobblemon.ui.pokedex.info.form.audino-mega": "Mega Audino",
"cobblemon.species.basculin-bluestriped.desc": "Esses Pokémon formam cardumes com outros da mesma cor. O maior inimigo de um cardume de Basculin azuis é um cardume de Basculin vermelhos.",
"cobblemon.ui.pokedex.info.form.basculin-white": "Forma de Lista Branca",
"cobblemon.ui.pokedex.info.form.yamask-galar": "Galariano",
@@ -8322,7 +8322,7 @@
"cobblemon.ui.pokedex.info.form.florges-yellow": "Flor Amarela",
"cobblemon.ui.pokedex.info.form.furfrou": "Forma Natural",
"cobblemon.ui.pokedex.info.form.aegislash-blade": "Forma da Lâmina",
"cobblemon.ui.pokedex.info.form.pumpkaboo-large": "Tamanho Grande",
"cobblemon.ui.pokedex.info.form.pumpkaboo-large": "Variedade Grande",
"cobblemon.ui.pokedex.info.form.silvally-electric": "Tipo: Elétrico",
"cobblemon.ui.pokedex.info.form.minior-blue": "Núcleo Azul",
"cobblemon.species.cramorant-gorging.desc": "Este Cramorant acidentalmente prendeu um Pikachu na garganta. Ele está se engasgando um pouco, mas não está nem um pouco incomodado.",
@@ -8370,9 +8370,9 @@
"cobblemon.move.ragingfury": "Ira Furiosa",
"cobblemon.move.takeheart": "Ânimo Revigorado",
"cobblemon.move.doodle": "Decalque",
"cobblemon.ui.pokedex.info.form.pinsir-mega": "Mega",
"cobblemon.ui.pokedex.info.form.banette-mega": "Mega",
"cobblemon.ui.pokedex.info.form.groudon-primal": "Reversão Primal",
"cobblemon.ui.pokedex.info.form.pinsir-mega": "Mega Pinsir",
"cobblemon.ui.pokedex.info.form.banette-mega": "Mega Banette",
"cobblemon.ui.pokedex.info.form.groudon-primal": "Groudon Primal",
"block.cobblemon.stripped_saccharine_wood": "Madeira de Sacarina Descascada",
"block.cobblemon.hearty_grain_bale": "Fardo de Grãos Saudáveis",
"block.cobblemon.tatami_block": "Tatame",
@@ -8471,32 +8471,32 @@
"cobblemon.mark.ribbon_contest_super_master_beauty.title": "%1$s a Beleza Vintage",
"cobblemon.mark.ribbon_contest_super_master_cleverness.desc": "Uma Fita concedida a um Pokémon que demonstrou perfeitamente a Inteligência em Concursos Pokémon.",
"cobblemon.mark.ribbon_contest_super_master_coolness": "Fita Mestre da Frieza",
"cobblemon.mark.ribbon_contest_super_master_coolness.title": "%1$s a Antiga Estrela",
"cobblemon.mark.ribbon_contest_super_master_coolness.title": "%1$s a Estrela",
"cobblemon.mark.ribbon_contest_super_master_coolness.desc": "Uma Fita concedida a um Pokémon que demonstrou perfeitamente a Frieza em Concursos Pokémon.",
"cobblemon.mark.ribbon_contest_super_master_cuteness": "Fita Mestre da Fofura",
"cobblemon.mark.ribbon_contest_super_master_cuteness.title": "%1$s o Antigo Ídolo",
"cobblemon.mark.ribbon_contest_super_master_cuteness.title": "%1$s o Ídolo",
"cobblemon.mark.ribbon_contest_super_master_cuteness.desc": "Uma Fita concedida a um Pokémon que demonstrou perfeitamente a Fofura em Concursos Pokémon.",
"cobblemon.mark.ribbon_contest_super_master_toughness": "Fita Mestre da Força",
"cobblemon.mark.ribbon_contest_super_master_toughness.title": "%1$s o Antigo Fortão",
"cobblemon.mark.ribbon_contest_super_master_toughness.title": "%1$s o Fortão",
"cobblemon.mark.ribbon_contest_super_master_toughness.desc": "Uma Fita concedida a um Pokémon que demonstrou perfeitamente a Força em Concursos Pokémon.",
"cobblemon.mark.ribbon_contest_super_star": "Fita Estrela do Concurso",
"cobblemon.mark.ribbon_contest_super_star.title": "%1$s a Estrela Brilhante",
"cobblemon.mark.ribbon_contest_super_star.desc": "Uma Fita concedida a um Pokémon que teve um desempenho excelente em todos os tipos de concurso.",
"cobblemon.mark.ribbon_contest_super_star_twinkling": "Fita Estrela Cintilante",
"cobblemon.mark.ribbon_day_downcast": "Fita Abatida",
"cobblemon.mark.ribbon_day_downcast.title": "%1$s o Outrora Abatido",
"cobblemon.mark.ribbon_day_downcast.title": "%1$s o Abatido",
"cobblemon.mark.ribbon_day_downcast.desc": "Uma Fita para relembrar sentimentos de tristeza que adicionaram tempero à vida.",
"cobblemon.mark.ribbon_day_relax": "Fita Relaxante",
"cobblemon.mark.ribbon_day_relax.title": "%1$s o Outrora Descansado",
"cobblemon.mark.ribbon_day_relax.title": "%1$s o Descansado",
"cobblemon.mark.ribbon_day_relax.desc": "Uma Fita para relembrar um evento revigorante que deu um toque especial à vida.",
"cobblemon.mark.ribbon_day_shock": "Fita Chocante",
"cobblemon.mark.ribbon_day_shock.title": "%1$s o Outrora Acovardado",
"cobblemon.mark.ribbon_day_shock.title": "%1$s o Acovardado",
"cobblemon.mark.ribbon_day_shock.desc": "Uma Fita para relembrar um evento arrepiante que tornou a vida mais emocionante.",
"cobblemon.mark.ribbon_day_smile": "Fita do Sorriso",
"cobblemon.mark.ribbon_day_smile.title": "%1$s o Outrora Alegre",
"cobblemon.mark.ribbon_day_smile.title": "%1$s o Alegre",
"cobblemon.mark.ribbon_day_smile.desc": "Uma Fita para lembrar que os sorrisos enriquecem a qualidade de vida.",
"cobblemon.mark.ribbon_day_snooze": "Fita da Soneca",
"cobblemon.mark.ribbon_day_snooze.title": "%1$s o Outrora Sonolento",
"cobblemon.mark.ribbon_day_snooze.title": "%1$s o Sonolento",
"cobblemon.mark.ribbon_day_snooze.desc": "Uma Fita para relembrar um sono profundo que tornou a vida relaxante.",
"cobblemon.mark.ribbon_event_birthday.desc": "Uma Fita que comemora um aniversário.",
"cobblemon.mark.ribbon_event_champion_battle": "Fita de Campeão de Batalha",
@@ -8552,7 +8552,7 @@
"cobblemon.mark.ribbon_once-in-a-lifetime.title": "%1$s o Um em um Milhão",
"cobblemon.mark.ribbon_once-in-a-lifetime.desc": "Uma Fita rara encontrada com pouquíssima frequência em Pokémon.",
"cobblemon.mark.ribbon_partner": "Fita de Parceiro",
"cobblemon.mark.ribbon_partner.desc": "Uma Fita especial concedida a um Pokémon que já foi parceiro de outro grande Treinador.",
"cobblemon.mark.ribbon_partner.desc": "Uma Fita especial concedida a um Pokémon que é parceiro de um grande Treinador.",
"cobblemon.mark.ribbon_record.title": "%1$s o Detentor do Recorde",
"cobblemon.mark.ribbon_record.desc": "Uma Fita concedida por estabelecer um recorde incrível.",
"cobblemon.mark.ribbon_syndicate_royal": "Fita Real",
@@ -8561,7 +8561,7 @@
"cobblemon.mark.ribbon_syndicate_gorgeous_royal.title": "%1$s a Realeza Maravilhosa",
"cobblemon.mark.ribbon_syndicate_gorgeous_royal.desc": "Uma Fita linda e majestosa que é o ápice do fabuloso.",
"cobblemon.mark.ribbon_training": "Fita de Treinamento",
"cobblemon.mark.mark_alpha.desc": "Uma marca para um Pokémon que era um alfa.",
"cobblemon.mark.mark_alpha.desc": "Uma marca para um Pokémon alfa.",
"cobblemon.mark.mark_curry": "Marca de Curry",
"cobblemon.mark.mark_curry.title": "%1$s o Especialista em Curry",
"cobblemon.mark.mark_curry.desc": "Uma marca para um Pokémon conhecedor de curry.",
@@ -8649,14 +8649,14 @@
"cobblemon.move.gmaxmalodor": "Pestilência G-Max",
"cobblemon.move.gmaxvinelash": "Chicotada G-Max",
"cobblemon.move.gmaxvolcalith": "Rocha Vulcânica G-Max",
"cobblemon.ui.pokedex.info.form.beedrill-mega": "Mega",
"cobblemon.ui.pokedex.info.form.beedrill-mega": "Mega Beedrill",
"cobblemon.species.pikachu-original.desc": "Este Pikachu está usando seu boné de Treinador. Como o boné não é do tamanho certo, o ajuste está um pouco folgado.",
"cobblemon.ui.pokedex.info.form.graveler-alola": "Aloliano",
"cobblemon.ui.pokedex.info.form.slowbro-galar": "Galariano",
"cobblemon.ui.pokedex.info.form.tauros-paldeablaze": "Raça da Chama (Paldean)",
"cobblemon.ui.pokedex.info.form.mewtwo-megay": "Mega Y",
"cobblemon.ui.pokedex.info.form.tauros-paldeablaze": "Paldeano (Raça da Chama)",
"cobblemon.ui.pokedex.info.form.mewtwo-megay": "Mega Mewtwo Y",
"cobblemon.species.mewtwo-megay.desc": "Apesar do tamanho reduzido, seu poder mental cresceu fenomenalmente. Com um simples pensamento, ele pode destruir um arranha-céu em pedacinhos.",
"cobblemon.ui.pokedex.info.form.ampharos-mega": "Mega",
"cobblemon.ui.pokedex.info.form.ampharos-mega": "Mega Ampharos",
"cobblemon.species.ampharos-mega.desc": "Grandes quantidades de energia estimularam intensamente as células de Ampharos, aparentemente despertando seu sangue de dragão adormecido.",
"cobblemon.ui.pokedex.info.form.wooper-paldea": "Paldeano",
"cobblemon.ui.pokedex.info.form.slowking-galar": "Galariano",
@@ -8684,44 +8684,44 @@
"cobblemon.species.unown-x.desc": "Este Pokémon tem o formato de uma escrita antiga. É um mistério o que surgiu primeiro, as escritas antigas ou os vários Unown. Pesquisas sobre este tópico estão em andamento, mas nada se sabe.",
"cobblemon.ui.pokedex.info.form.qwilfish-hisui": "Hisuiano",
"cobblemon.species.qwilfish-hisui.desc": "Ele vive próximo à costa, em partes frias do mundo. Seus espinhos venenosos são mais grossos e curtos do que os dos Qwilfish de outras regiões.",
"cobblemon.ui.pokedex.info.form.scizor-mega": "Mega",
"cobblemon.ui.pokedex.info.form.scizor-mega": "Mega Scizor",
"cobblemon.species.scizor-mega.desc": "Ele é melhor em bater em objetos do que em agarrá-los. Quando luta por muito tempo, o peso de suas pinças se torna insuportável.",
"cobblemon.species.heracross-mega.desc": "Um tremendo influxo de energia o desenvolve, mas quando a Mega Evolução termina, Heracross fica incomodado com uma dor terrível nos músculos.",
"cobblemon.ui.pokedex.info.form.houndoom-mega": "Mega",
"cobblemon.ui.pokedex.info.form.tyranitar-mega": "Mega",
"cobblemon.ui.pokedex.info.form.houndoom-mega": "Mega Houndoom",
"cobblemon.ui.pokedex.info.form.tyranitar-mega": "Mega Tyranitar",
"cobblemon.species.tyranitar-mega.desc": "Os efeitos da Mega Evolução o tornam mais feroz do que nunca. Não se sabe se ele consegue ouvir as ordens de seu Treinador.",
"cobblemon.species.zigzagoon-galar.desc": "Sua inquietação o faz correr constantemente. Se vir outro Pokémon, ele irá esbarrar nele de propósito para começar uma briga.",
"cobblemon.ui.pokedex.info.form.gardevoir-mega": "Mega",
"cobblemon.ui.pokedex.info.form.sableye-mega": "Mega",
"cobblemon.ui.pokedex.info.form.mawile-mega": "Mega",
"cobblemon.ui.pokedex.info.form.aggron-mega": "Mega",
"cobblemon.species.aggron-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.gardevoir-mega": "Mega Gardevoir",
"cobblemon.ui.pokedex.info.form.sableye-mega": "Mega Sableye",
"cobblemon.ui.pokedex.info.form.mawile-mega": "Mega Mawile",
"cobblemon.ui.pokedex.info.form.aggron-mega": "Mega Aggron",
"cobblemon.species.aggron-mega.desc": "Energia da Mega Evolução transformou o ferro dentro deste Pokémon em uma armadura de aço que cobre o corpo inteiro de Mega Aggron.",
"cobblemon.species.manectric-mega.desc": "Muita eletricidade se acumulou em seu corpo, irritando Manectric. Sua velocidade explosiva é igual à de um raio.",
"cobblemon.ui.pokedex.info.form.camerupt-mega": "Mega",
"cobblemon.ui.pokedex.info.form.camerupt-mega": "Mega Camerupt",
"cobblemon.ui.pokedex.info.form.castform": "Normal",
"cobblemon.ui.pokedex.info.form.glalie-mega": "Mega",
"cobblemon.ui.pokedex.info.form.salamence-mega": "Mega",
"cobblemon.ui.pokedex.info.form.glalie-mega": "Mega Glalie",
"cobblemon.ui.pokedex.info.form.salamence-mega": "Mega Salamence",
"cobblemon.species.metagross-mega.desc": "Quando sabe que não pode vencer, ele crava as garras das pernas no oponente e inicia a contagem regressiva para uma grande explosão.",
"cobblemon.ui.pokedex.info.form.latias-mega": "Mega",
"cobblemon.species.latias-mega.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.latias-mega": "Mega Latias",
"cobblemon.species.latias-mega.desc": "Tanto sua habilidade de voo quanto seu poder de ataque foram elevados. Dispersa sua plumagem transparente para confundir seus inimigos.",
"cobblemon.species.groudon-primal.desc": "Por meio da Reversão Primordial e com todo o poder da natureza, ele retomará sua verdadeira forma. Pode causar a erupção de magma e expandir a massa terrestre do mundo.",
"cobblemon.ui.pokedex.info.form.kyogre-primal": "Reversão Primal",
"cobblemon.ui.pokedex.info.form.kyogre-primal": "Kyogre Primal",
"cobblemon.species.kyogre-primal.desc": "Por meio da Reversão Primordial e com todo o poder da natureza, ele retomará sua verdadeira forma. Pode invocar tempestades que fazem o nível do mar subir.",
"cobblemon.ui.pokedex.info.form.deoxys": "Forma Normal",
"cobblemon.ui.pokedex.info.form.deoxys-attack": "Forma de Ataque",
"cobblemon.species.deoxys-attack.desc": "Você está certo",
"cobblemon.species.deoxys-attack.desc": "Esse Deoxys assumiu sua forma agressiva. Pode confundir inimigos ao alterar sua aparência.",
"cobblemon.ui.pokedex.info.form.deoxys-defense": "Forma de Defesa",
"cobblemon.species.deoxys-defense.desc": "Ecologia em estudo.",
"cobblemon.species.deoxys-defense.desc": "Quando muda de forma, uma aurora aparece. Absorve ataques ao alterar sua estrutura celular.",
"cobblemon.ui.pokedex.info.form.deoxys-speed": "Forma de Velocidade",
"cobblemon.species.deoxys-speed.desc": "Ecologia em estudo.",
"cobblemon.species.deoxys-speed.desc": "Um Pokémon vírus extraterrestre que mutou depois de ser exposto à um raio laser. Seu corpo é configurado para agilidade e velocidade melhoradas.",
"cobblemon.ui.pokedex.info.form.burmy": "Manto de Planta",
"cobblemon.ui.pokedex.info.form.burmy-sandy": "Manto de Areia",
"cobblemon.species.burmy-sandy.desc": "Ele cria uma capa entrelaçando areia, lama e seda que cuspiu. Essa capa de terra é destruída pelo vento e pela chuva, então o Pokémon se esconde em cavernas e outros lugares semelhantes.",
"cobblemon.ui.pokedex.info.form.burmy-trash": "Manto de Lixo",
"cobblemon.species.burmy-trash.desc": "Quando confrontado pela falta de outros materiais, Burmy criará sua capa usando pó e lixo. A capa parece ser mais confortável do que se poderia imaginar.",
"cobblemon.ui.pokedex.info.form.wormadam-sandy": "Manto de Areia",
"cobblemon.ui.pokedex.info.form.lopunny-mega": "Mega",
"cobblemon.ui.pokedex.info.form.gallade-mega": "Mega",
"cobblemon.ui.pokedex.info.form.lopunny-mega": "Mega Lopunny",
"cobblemon.ui.pokedex.info.form.gallade-mega": "Mega Gallade",
"cobblemon.ui.pokedex.info.form.dialga-origin": "Formato de origem",
"cobblemon.species.dialga-origin.desc": "Uma luz radiante fez com que Dialga assumisse uma forma com uma semelhança impressionante com o Pokémon criador. Dialga agora possui uma força tão colossal que é preciso concluir que esta é sua verdadeira forma.",
"cobblemon.ui.pokedex.info.form.giratina": "Forma Alterada",
@@ -8763,14 +8763,14 @@
"cobblemon.ui.pokedex.info.form.kyurem-black": "Kyurem Negro",
"cobblemon.species.kyurem-black.desc": "Diz-se que este Pokémon luta para proteger o mundo ideal que existirá no futuro para pessoas e Pokémon.",
"cobblemon.ui.pokedex.info.form.meloetta-pirouette": "Forma de Pirueta",
"cobblemon.species.meloetta-pirouette.desc": "Ecologia em estudo.",
"cobblemon.species.genesect-water.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.genesect-electric": "Genesect",
"cobblemon.species.genesect-electric.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.genesect-fire": "Genesect",
"cobblemon.species.genesect-fire.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.genesect-ice": "Genesect",
"cobblemon.species.genesect-ice.desc": "Ecologia em estudo.",
"cobblemon.species.meloetta-pirouette.desc": "Agora que relembrou uma antiga canção esquecida, Meloetta cativa todos com seus movimentos de dança encantadores.",
"cobblemon.species.genesect-water.desc": "Genesect assume sua configuração de voo para planar pelos céus. Sua forma atual é equipada com um cassete carregado de energia aquática.",
"cobblemon.ui.pokedex.info.form.genesect-electric": "Disco Elétrico",
"cobblemon.species.genesect-electric.desc": "Genesect dispara rajadas de projéteis de energia. Sua forma atual é equipada com um cassete carregado de energia elétrica.",
"cobblemon.ui.pokedex.info.form.genesect-fire": "Disco Incendiante",
"cobblemon.species.genesect-fire.desc": "Genesect produz garras de metal afiadas. Sua forma atual é equipada com um cassete carregado de energia de fogo.",
"cobblemon.ui.pokedex.info.form.genesect-ice": "Disco Congelante",
"cobblemon.species.genesect-ice.desc": "Genesect não tem piedade. Sua forma atual é equipada com um cassete carregado de energia gélida.",
"cobblemon.species.greninja-bond.desc": "Ecologia em estudo.",
"cobblemon.species.greninja-ash.desc": "Ecologia em estudo.",
"cobblemon.ui.pokedex.info.form.vivillon-icysnow": "Padrão de Neve Gelada",
@@ -8818,22 +8818,22 @@
"cobblemon.ui.pokedex.info.form.decidueye-hisui": "Hisuiano",
"cobblemon.ui.pokedex.info.form.silvally": "Tipo: Normal",
"cobblemon.ui.pokedex.info.form.silvally-fighting": "Tipo: Lutador",
"cobblemon.species.silvally-fighting.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-fighting.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Lutador para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-flying": "Tipo: Voador",
"cobblemon.species.silvally-flying.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-flying.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Voador para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-poison": "Tipo: Veneno",
"cobblemon.species.silvally-poison.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-poison.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Venenoso para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-ground": "Tipo: Solo",
"cobblemon.species.silvally-ground.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-bug.desc": "Sua capacidade de mudar de tipo desencadeada, ela brilha prata devido à energia que surgiu de dentro.",
"cobblemon.species.silvally-ground.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Terrestre para se assemelhar à memória que tem equipada.",
"cobblemon.species.silvally-bug.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Inseto para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-ghost": "Tipo: Fantasma",
"cobblemon.species.silvally-ghost.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-ghost.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Fantasma para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-steel": "Tipo: Aço",
"cobblemon.species.silvally-steel.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-steel.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Aço para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-fire": "Tipo: Fogo",
"cobblemon.species.silvally-fire.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-fire.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Fogo para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.silvally-water": "Tipo: Água",
"cobblemon.species.silvally-water.desc": "Com sua capacidade de mudar de tipo liberada, ele brilha prateado devido à energia que brota de dentro.",
"cobblemon.species.silvally-water.desc": "Graças aos seus poderes despertados, pode mudar para o tipo Água para se assemelhar à memória que tem equipada.",
"cobblemon.ui.pokedex.info.form.minior-meteor": "Forma de Meteoro",
"cobblemon.species.minior-meteor.desc": "Este Pokémon nasce na camada de ozônio. Ele cai no chão quando a casca externa que envolve seu núcleo fica pesada.",
"cobblemon.ui.pokedex.info.form.minior-orange": "Núcleo Laranja",
@@ -8884,7 +8884,7 @@
"cobblemon.move.overdrive": "Sobrecarga",
"cobblemon.move.thundercage": "Prisão Elétrica",
"cobblemon.move.dragonenergy": "Energia Dracônica",
"cobblemon.ui.pokedex.info.form.gyarados-mega": "Mega",
"cobblemon.ui.pokedex.info.form.gyarados-mega": "Mega Gyarados",
"cobblemon.species.gyarados-mega.desc": "Ele sai da água a velocidades Mach. Até mesmo navios grandes pegos em seu caminho são divididos em dois!",
"tag.item.cobblemon.berries.colour.green": "Bagas Verdes",
"stat.cobblemon.battles_fled": "Fugas em Batalhas Pokémon",
@@ -9016,7 +9016,7 @@
"block.cobblemon.fighting_gem_block": "Bloco de Gema do Lutador",
"block.cobblemon.poison_gem_block": "Bloco de Gema Venenosa",
"block.cobblemon.ground_gem_block": "Bloco de Gema Terrestre",
"block.cobblemon.flying_gem_block": "Bloco de Gema do Voador",
"block.cobblemon.flying_gem_block": "Bloco de Gema Voadora",
"block.cobblemon.psychic_gem_block": "Bloco de Gema Psíquica",
"block.cobblemon.bug_gem_block": "Bloco de Gema do Inseto",
"block.cobblemon.rock_gem_block": "Bloco de Gema da Pedra",
@@ -9031,7 +9031,7 @@
"block.cobblemon.fighting_gem_cluster": "Agregado de Gema do Lutador",
"block.cobblemon.poison_gem_cluster": "Agregado de Gema Venenosa",
"block.cobblemon.ground_gem_cluster": "Agregado de Gema Terrestre",
"block.cobblemon.flying_gem_cluster": "Agregado de Gema do Voador",
"block.cobblemon.flying_gem_cluster": "Agregado de Gema Voadora",
"block.cobblemon.psychic_gem_cluster": "Agregado de Gema Psíquica",
"block.cobblemon.bug_gem_cluster": "Agregado de Gema do Inseto",
"block.cobblemon.rock_gem_cluster": "Agregado de Gema da Pedra",
@@ -9103,7 +9103,7 @@
"cobblemon.ui.edit.habitat.validation.species": "Espécie deve ser um nome de Pokémon válido.",
"cobblemon.ui.edit.habitat.validation.weight": "Peso deve ser maior que 0.",
"cobblemon.ui.edit.habitat.validation.modifiers": "Formato dos modificadores é inválido.",
"cobblemon.ui.edit.habitat.validation.phases_list": "Fases deve usar fases da lua válidas (0-7), e.g. 1-3 ou 1, 3-5, 6.",
"cobblemon.ui.edit.habitat.validation.phases_list": "Fases devem usar um formato válido de números inteiros (0-7), e.g. 1-3 ou 1, 3-5, 6.",
"cobblemon.ui.edit.habitat.validation.min_light": "Luz Mínima deve estar entre 0 e 15.",
"cobblemon.ui.edit.habitat.validation.max_light": "Luz Máxima deve estar entre 0 e 15.",
"cobblemon.ui.moves.learnset.tm.discovered": "Descoberto",
@@ -9182,7 +9182,7 @@
"cobblemon.habitat.warped_fungal_dwelling.name": "Morada Fúngica Distorcida",
"cobblemon.habitat.zen_garden.name": "Jardim Zen",
"cobblemon.subtitle.tm.use": "Máquina Técnica usada",
"cobblemon.subtitle.block.tm_machine.craft": "Máquina de TM grava TM",
"cobblemon.subtitle.block.tm_machine.craft": "Máquina de TM finaliza gravação de TM",
"cobblemon.subtitle.block.tm_machine.off": "Máquina de TM desativa",
"cobblemon.subtitle.block.tm_machine.on": "Máquina de TM ativa",
"cobblemon.subtitle.block.tm_machine.open": "Tampa da Máquina de TM abre",
@@ -9331,5 +9331,87 @@
"cobblemon.config.ui.world_spawning_blocklist": "Permissões de Geração em Mundos",
"cobblemon.config.ui.world_spawning_blocklist.tooltip": "Mundos nos quais desabilitar a geração de Pokémon.",
"advancements.cobblemon.obtain_tm.description": "Encontrar ou gravar um TM",
"advancements.cobblemon.obtain_tm": "Olha esses movimentos!"
"advancements.cobblemon.obtain_tm": "Olha esses movimentos!",
"cobblemon.species.glimmora-mega.desc": "As pétalas de Glimmora — agora maiores e separadas de seu corpo — rodam ao seu redor para servir de proteção ao espalhar fragmentos venenosos.",
"cobblemon.ui.pokedex.info.form.raichu-megax": "Mega Raichu X",
"cobblemon.ui.pokedex.info.form.raichu-megay": "Mega Raichu Y",
"cobblemon.species.raichu-megay.desc": "Dispara rajadas de eletricidade da ponta de sua cauda e dos tufos de pelo pontudos que crescem em suas têmporas. Essa eletricidade tem o formato da letra Y.",
"cobblemon.ui.pokedex.info.form.chimecho-mega": "Mega Chimecho",
"cobblemon.species.chimecho-mega.desc": "Vibra seu corpo inteiro para atacar em todas as direções usando ondas sonoras. Qualquer um que ouça essas vibrações ficam confusos e esquecem quem são.",
"cobblemon.ui.pokedex.info.form.absol-megaz": "Mega Absol Z",
"cobblemon.species.absol-megaz.desc": "Usando pelos moldados no formato de garras afiadas, corta seus oponentes com um único golpe. Faz isso como um ato de bondade para que não sofram além do necessário.",
"cobblemon.ui.pokedex.info.form.staraptor-mega": "Mega Staraptor",
"cobblemon.species.staraptor-mega.desc": "Mega Staraptor está no auge da habilidade de voo. Pode facilmente planar pelos céus enquanto carrega um Steelix pesando mais de 400 kg.",
"cobblemon.ui.pokedex.info.form.garchomp-megaz": "Mega Garchomp Z",
"cobblemon.species.garchomp-megaz.desc": "Garchomp ganhou uma nova forma Mega Evoluída. Voa ao redor de oponentes a velocidades altíssimas e os despedaça com seus esporões sinistros.",
"cobblemon.ui.pokedex.info.form.lucario-megaz": "Mega Lucario Z",
"cobblemon.species.lucario-megaz.desc": "Ao se envolver completamente com sua aura, Mega Lucario Z pode aparar qualquer tipo de ataque, batalhando como se estivesse dançando graciosamente.",
"cobblemon.ui.pokedex.info.form.froslass-mega": "Mega Froslass",
"cobblemon.species.froslass-mega.desc": "Esse Pokémon pode usar vento gelado imbuído com energia fantasmagórica para congelar até mesmo coisas insubstanciais, como chamas ou ar.",
"cobblemon.ui.pokedex.info.form.heatran-mega": "Mega Heatran",
"cobblemon.species.heatran-mega.desc": "É dito que se der o seu máximo, pode aquecer seu corpo a temperaturas acima de 1 milhão de graus Celsius. Esse calor afasta os inimigos.",
"cobblemon.ui.pokedex.info.form.darkrai-mega": "Mega Darkrai",
"cobblemon.species.darkrai-mega.desc": "Seu poder sombrio bloqueia o sol, lançando seus arredores em uma profunda escuridão. Não há escapatória de seu olho maligno.",
"cobblemon.ui.pokedex.info.form.emboar-mega": "Mega Emboar",
"cobblemon.species.emboar-mega.desc": "Brandindo uma chama ardente no meu de uma lança curvada, corajosamente resgata aliados em perigo.",
"cobblemon.ui.pokedex.info.form.excadrill-mega": "Mega Excadrill",
"cobblemon.species.excadrill-mega.desc": "Se esse Pokémon juntar seus braços a sua cabeça em uma única forma e girar a velocidades elevadas, pode destruir qualquer coisa.",
"cobblemon.ui.pokedex.info.form.scolipede-mega": "Mega Scolipede",
"cobblemon.species.scolipede-mega.desc": "Sua peçonha mortal produz um certo brilho. A peçonha afeta a mente de Scolipede, agravando sua crueldade.",
"cobblemon.ui.pokedex.info.form.basculin-whitestriped": "Forma de Listras Brancas",
"cobblemon.species.basculin-whitestriped.desc": "Vivem em mares gelados, formando cardumes e compartilhando alimento entre si. Quando o momento certo chega, retornam ao rio onde nasceram.",
"cobblemon.ui.pokedex.info.form.scrafty-mega": "Mega Scrafty",
"cobblemon.species.scrafty-mega.desc": "A Mega Evolução fez com que a pele trocada de Scrafty se esbranquiçasse, se tornando resistente e maleável. Esse Pokémon está mais abusado do que nunca.",
"cobblemon.ui.pokedex.info.form.eelektross-mega": "Mega Eelektross",
"cobblemon.species.eelektross-mega.desc": "Agora gera 10 vezes mais eletricidade comparado a antes da Mega Evolução. Descarrega essa eletricidade de seus Eelektrik falsos feitos de muco.",
"cobblemon.ui.pokedex.info.form.chandelure-mega": "Mega Chandelure",
"cobblemon.species.chandelure-mega.desc": "Um de seus olhos é uma janela ligando nosso mundo ao pós-vida. Esse Pokémon absorve ódio e o transformador em poder.",
"cobblemon.ui.pokedex.info.form.golurk-mega": "Mega Golurj",
"cobblemon.species.golurk-mega.desc": "A energia dentro de Golurk foi estimulada pela Mega Evolução. Esse Pokémon pode explodir a qualquer momento.",
"cobblemon.ui.pokedex.info.form.chesnaught-mega": "Mega Chesnaught",
"cobblemon.species.chesnaught-mega.desc": "Tem uma armadura fortificada e um desejo de defender a todo custo. Ambos absurdamente fortes.",
"cobblemon.ui.pokedex.info.form.delphox-mega": "Mega Delphox",
"cobblemon.species.delphox-mega.desc": "Porta galhos flamejantes para deslumbrar seus oponentes antes de incinerá-los com uma enorme bola de fogo.",
"cobblemon.species.greninja-mega.desc": "Esse Pokémon gira um shuriken gigante a altas velocidades para fazê-lo flutuar e então se prende a ele de cabeça para baixo para surpreender oponentes desatentos.",
"cobblemon.ui.pokedex.info.form.pyroar-mega": "Mega Pyroar",
"cobblemon.species.pyroar-mega.desc": "Esse Pokémon cospe chamas a temperaturas superiores a 10.000 graus Celsius. Balança sua grandiosa e flamejante juba para proteger seus aliados.",
"cobblemon.ui.pokedex.info.form.floette-mega": "Mega Floette",
"cobblemon.species.floette-mega.desc": "A Flor Eterna absorveu toda a energia da Mega Evolução. A flor agora ataca inimigos por conta própria.",
"cobblemon.ui.pokedex.info.form.meowstic-mega": "Mega Meowstic",
"cobblemon.species.meowstic-mega.desc": "Mega Meowstic pode usar seu poder psíquico para comprimir ou expandir tudo. Sobrecarrega oponentes ao contorcer o tecido do espaço.",
"cobblemon.ui.pokedex.info.form.malamar-mega": "Mega Malamar",
"cobblemon.species.malamar-mega.desc": "Usa suas luzes coloridas para subjugar as personalidades e memórias de outros—e para controlá-los.",
"cobblemon.ui.pokedex.info.form.barbaracle-mega": "Mega Barbaracle",
"cobblemon.species.barbaracle-mega.desc": "Usa seus muitos braços para se divertir com seus oponentes. Isso ocupa muito a cabeça central.",
"cobblemon.ui.pokedex.info.form.dragalge-mega": "Mega Dragalge",
"cobblemon.species.dragalge-mega.desc": "Cospe um líquido capaz de confundir o poder regenerativo das células. O líquido é um veneno mortal para todos além de si mesmo.",
"cobblemon.ui.pokedex.info.form.hawlucha-mega": "Mega Hawlucha",
"cobblemon.species.hawlucha-mega.desc": "A Mega Evolução fortaleceu todos os seus músculos. Hawlucha posa para demonstrar sua força.",
"cobblemon.ui.pokedex.info.form.zygarde-mega": "Mega Zygarde",
"cobblemon.species.zygarde-mega.desc": "Em resposta às emoções das pessoas durante uma crise sem precedentes, Zygarde Mega Evolui e acalma a situação com seu poder inigualável.",
"cobblemon.ui.pokedex.info.form.crabominable-mega": "Mega Crabominable",
"cobblemon.species.crabominable-mega.desc": "Pode pulverizar concreto reforçado com um simples balanço de seus punho, cada um coberto por uma grossa camada de gelo.",
"cobblemon.ui.pokedex.info.form.golisopod-mega": "Mega Golisopod",
"cobblemon.species.golisopod-mega.desc": "Usa quatro de seus braços para atacar ferozmente seus inimigos. Quando os leva à beira da derrota, os finaliza com os braços que manteve escondido.",
"cobblemon.ui.pokedex.info.form.drampa-mega": "Mega Drampa",
"cobblemon.species.drampa-mega.desc": "As células de Drampa foram revigoradas, permitindo que recuperasse sua juventude. Manipula a atmosfera para convocar tempestades.",
"cobblemon.ui.pokedex.info.form.magearna-mega": "Mega Magearna",
"cobblemon.species.magearna-mega.desc": "Essa é Magearna quando um modo oculto é ativado. As emoções de Magearna começou a sentir agora se reprimem enquanto derruba inimigo após inimigo.",
"cobblemon.ui.pokedex.info.form.magearna-originalmega": "Mega Magearna Cor Original",
"cobblemon.species.magearna-originalmega.desc": "Um mecanismo para remover as limitações de Magearna permaneceu oculto dentro de Magearna por 500 anos. Esse mecanismo é ativado por uma Mega Pedra.",
"cobblemon.ui.pokedex.info.form.zeraora-mega": "Mega Zeraora",
"cobblemon.species.zeraora-mega.desc": "Armazena em seu corpo energia equivalente a dez relâmpagos. Quando para de impor limites a si mesmo, se torna um dos Pokémon elétricos mais fortes.",
"cobblemon.ui.pokedex.info.form.falinks-mega": "Mega Falinks",
"cobblemon.species.falinks-mega.desc": "Mega Falinks assumiu a formação de batalha suprema, que só pode ser atingida se os guerreiros e o latão tenham um vínculo inquebrável.",
"cobblemon.ui.pokedex.info.form.scovillain-mega": "Mega Scovillain",
"cobblemon.species.scovillain-mega.desc": "A Mega Evolução elevou a picância desse Pokémon. Balança sua \"gravata\" para golpear seus oponentes.",
"cobblemon.ui.pokedex.info.form.glimmora-mega": "Mega Glimmora",
"cobblemon.ui.pokedex.info.form.tatsugiri-mega": "Mega Tatsugiri Forma Curvada",
"cobblemon.species.tatsugiri-mega.desc": "O cérebro de Tatsugiri foi energizado pela Mega Evolução, tornando-o mais astuto. Pode criar e comandar cópias de si mesmo.",
"cobblemon.ui.pokedex.info.form.tatsugiri-droopymega": "Mega Tatsuguri Forma Molenga",
"cobblemon.species.tatsugiri-droopymega.desc": "Solidifica a energia da Mega Evolução, construindo uma pilha excessiva para lançar como projéteis. Esses projéteis explodem ao primeiro contato.",
"cobblemon.ui.pokedex.info.form.tatsugiri-stretchymega": "Mega Tatsugiri Forma Elástica",
"cobblemon.species.tatsugiri-stretchymega.desc": "Usando a energia da Mega Evolução, cria um prato onde repousar, permitindo com que se mova com mobilidade total até mesmo pelo ar.",
"cobblemon.ui.pokedex.info.form.baxcalibur-mega": "Mega Baxcalibur",
"cobblemon.species.baxcalibur-mega.desc": "A lâmina dorsal de Baxcalibur ficou ainda maior graças à Mega Evolução. Esse Pokémon dispara feixes do cabo localizado em seu peito."
}
@@ -9222,8 +9222,8 @@
"block.cobblemon.normal_gem_block": "一般宝石块",
"block.cobblemon.fire_gem_block": "火之宝石块",
"block.cobblemon.water_gem_block": "水之宝石块",
"block.cobblemon.electric_gem_block": "草之宝石块",
"block.cobblemon.grass_gem_block": "电之宝石块",
"block.cobblemon.electric_gem_block": "电之宝石块",
"block.cobblemon.grass_gem_block": "草之宝石块",
"block.cobblemon.ice_gem_block": "冰之宝石块",
"block.cobblemon.fighting_gem_block": "格斗宝石块",
"block.cobblemon.poison_gem_block": "毒之宝石块",
Binary file not shown.

After

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

@@ -1,5 +1,5 @@
{
"pokemon": ["electrode", "furfrou", "alakazam", "gengar", "jigglypuff", "smeargle"],
"pokemon": ["electrode hisuian=false", "furfrou", "alakazam", "gengar", "jigglypuff", "smeargle"],
"cosmeticItems": [
{
"consumedItem": "minecraft:white_dye",
@@ -1,41 +0,0 @@
{
"name": "cobblemon.habitat.birch_wildlife_scar.name",
"type": "cobblemon:natural",
"spawns": [
{
"species": "cobblemon:geodude",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "35-45",
"weight": 10
},
{
"species": "cobblemon:zubat",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "35-45",
"weight": 9
},
{
"species": "cobblemon:machop",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "36-46",
"weight": 8
},
{
"species": "cobblemon:graveler",
"bucket": "uncommon",
"spawnablePositionType": "grounded",
"levelRange": "40-50",
"weight": 6
},
{
"species": "cobblemon:golbat",
"bucket": "uncommon",
"spawnablePositionType": "grounded",
"levelRange": "40-50",
"weight": 6
}
]
}
@@ -1,41 +0,0 @@
{
"name": "cobblemon.habitat.oak_wildlife_scar.name",
"type": "cobblemon:natural",
"spawns": [
{
"species": "cobblemon:geodude",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "35-45",
"weight": 10
},
{
"species": "cobblemon:zubat",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "35-45",
"weight": 9
},
{
"species": "cobblemon:machop",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "36-46",
"weight": 8
},
{
"species": "cobblemon:graveler",
"bucket": "uncommon",
"spawnablePositionType": "grounded",
"levelRange": "40-50",
"weight": 6
},
{
"species": "cobblemon:golbat",
"bucket": "uncommon",
"spawnablePositionType": "grounded",
"levelRange": "40-50",
"weight": 6
}
]
}
@@ -1,41 +0,0 @@
{
"name": "cobblemon.habitat.spruce_wildlife_scar.name",
"type": "cobblemon:natural",
"spawns": [
{
"species": "cobblemon:geodude",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "35-45",
"weight": 10
},
{
"species": "cobblemon:zubat",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "35-45",
"weight": 9
},
{
"species": "cobblemon:machop",
"bucket": "common",
"spawnablePositionType": "grounded",
"levelRange": "36-46",
"weight": 8
},
{
"species": "cobblemon:graveler",
"bucket": "uncommon",
"spawnablePositionType": "grounded",
"levelRange": "40-50",
"weight": 6
},
{
"species": "cobblemon:golbat",
"bucket": "uncommon",
"spawnablePositionType": "grounded",
"levelRange": "40-50",
"weight": 6
}
]
}
@@ -17,7 +17,7 @@
"weightMultiplier": {
"multiplier": 3.0,
"condition": {
"minLight": 1
"minLight": 8
}
},
"condition": {
@@ -44,7 +44,7 @@
"weightMultiplier": {
"multiplier": 3.0,
"condition": {
"minLight": 1
"minLight": 8
}
},
"condition": {
@@ -76,7 +76,7 @@
"#cobblemon:is_forest"
],
"timeRange": "night",
"maxLight": 0
"maxLight": 7
}
},
{
@@ -98,7 +98,7 @@
],
"timeRange": "night",
"isRaining": true,
"maxLight": 0
"maxLight": 7
}
},
{
@@ -119,7 +119,7 @@
"#cobblemon:is_forest"
],
"timeRange": "night",
"minLight": 1
"minLight": 8
}
},
{
@@ -141,7 +141,7 @@
],
"timeRange": "night",
"isRaining": true,
"minLight": 1
"minLight": 8
}
}
]
@@ -17,7 +17,7 @@
"weightMultiplier": {
"multiplier": 3.0,
"condition": {
"minLight": 1
"minLight": 8
}
},
"condition": {
@@ -50,7 +50,7 @@
],
"timeRange": "night",
"isRaining": false,
"maxLight": 0
"maxLight": 7
}
},
{
@@ -72,7 +72,7 @@
],
"timeRange": "night",
"isRaining": false,
"minLight": 1
"minLight": 8
}
}
]
@@ -27,7 +27,7 @@
"#aether:is_aether",
"#cobblemon:is_overworld"
],
"maxLight": 0
"maxLight": 7
},
"anticondition": {
"biomes": [
@@ -87,7 +87,7 @@
"biomes": [
"#cobblemon:is_spooky"
],
"maxLight": 0
"maxLight": 7
}
},
{
@@ -27,7 +27,7 @@
"#aether:is_aether",
"#cobblemon:is_overworld"
],
"maxLight": 0
"maxLight": 7
},
"anticondition": {
"biomes": [
@@ -87,7 +87,7 @@
"biomes": [
"#cobblemon:is_spooky"
],
"maxLight": 0
"maxLight": 7
}
},
{
@@ -27,7 +27,7 @@
"#aether:is_aether",
"#cobblemon:is_overworld"
],
"maxLight": 0
"maxLight": 7
},
"anticondition": {
"biomes": [
@@ -87,7 +87,7 @@
"biomes": [
"#cobblemon:is_spooky"
],
"maxLight": 0
"maxLight": 7
}
},
{
@@ -18,7 +18,7 @@
"weightMultiplier": {
"multiplier": 11.0,
"condition": {
"minLight": 1
"minLight": 8
}
},
"condition": {
@@ -47,7 +47,7 @@
"weightMultiplier": {
"multiplier": 3.0,
"condition": {
"minLight": 1
"minLight": 8
}
},
"condition": {
@@ -145,6 +145,11 @@
"biomes": [
"#cobblemon:is_glacial"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_frozen_ocean"
]
}
}
]
@@ -145,6 +145,11 @@
"biomes": [
"#cobblemon:is_glacial"
]
},
"anticondition": {
"biomes": [
"#cobblemon:is_frozen_ocean"
]
}
}
]
@@ -33,7 +33,7 @@
},
{
"id": "rockruff-dusk-2",
"pokemon": "rockruff dusk",
"pokemon": "rockruff wolf_form=dusk",
"presets": [
"natural",
"wild"
@@ -5,7 +5,7 @@
"spawns": [
{
"id": "lycanroc-midday-1",
"pokemon": "lycanroc midday",
"pokemon": "lycanroc wolf_form=midday",
"presets": [
"natural",
"wild"
@@ -33,7 +33,7 @@
},
{
"id": "lycanroc-midnight-2",
"pokemon": "lycanroc midnight",
"pokemon": "lycanroc wolf_form=midnight",
"presets": [
"natural",
"wild"
@@ -61,7 +61,7 @@
},
{
"id": "lycanroc-dusk-3",
"pokemon": "lycanroc dusk",
"pokemon": "lycanroc wolf_form=dusk",
"presets": [
"natural",
"wild"
@@ -10,7 +10,7 @@
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "1-19",
"weight": 30.0,
"weight": 24.0,
"weightMultipliers": [
{
"multiplier": 1.5,
@@ -10,12 +10,12 @@
"spawnablePositionType": "grounded",
"bucket": "common",
"level": "14-48",
"weight": 60.0,
"weight": 12.0,
"weightMultipliers": [
{
"multiplier": 3.0,
"condition": {
"minLight": 1
"minLight": 8
}
},
{
@@ -22,7 +22,7 @@
],
"timeRange": "night",
"isRaining": false,
"minLight": 1
"minLight": 8
},
"herdablePokemon": [
{
@@ -55,7 +55,7 @@
],
"timeRange": "night",
"isRaining": false,
"minLight": 1
"minLight": 8
},
"herdablePokemon": [
{
@@ -33,7 +33,7 @@
},
"herdablePokemon": [
{
"pokemon": "farfetchd held_item=minecraft.stick alpha=true",
"pokemon": "farfetchd held_item=minecraft:stick alpha=true",
"weight": 30.0,
"levelRange": "1-100",
"maxTimes": 1,

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