Compare commits

..
Author SHA1 Message Date
Guilherme Pereira 1986cb480b add moves tooltips 2024-12-15 22:47:47 -03:00
470 changed files with 6268 additions and 6653 deletions

No files matched your search

-1
View File
@@ -431,7 +431,6 @@
- Fixed display case not being able to be fed items from underneath.
- Fixed Pokémon battling in water continuously sinking to the bottom.
- Fixed passive healing and wake from faint not disabling when their config values are set to 0.
- Fixed an issue where rebinding the R key to a mouse button prevented players from closing the battle interface using that button.
### Developer
- `SpawnCause` is now an implementation of `SpawningInfluence`.
@@ -0,0 +1,23 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.moves
enum class MoveEffectiveness(val showdownId: Int, val multiplier: Double) {
NORMAL(0, 1.0),
WEAKNESS(1, 2.0),
RESISTANCE(2, 0.5),
IMMUNITY(3, 0.0);
companion object {
fun of(showdownId: Int): MoveEffectiveness {
return entries.find { it.showdownId == showdownId }
?: throw IllegalArgumentException("Unknown MoveEffectiveness: $showdownId")
}
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.api.moves
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.runner.ShowdownService
object TypeChart {
private val movesEffectiveness = mutableMapOf<ElementalType, MutableMap<ElementalType, MoveEffectiveness>>()
fun load() {
movesEffectiveness.clear()
val typeChartJson = ShowdownService.service.getTypeChart()
typeChartJson.keySet().forEach { type ->
val defenderType = ElementalTypes.get(type) ?: return@forEach
val moveTypes = typeChartJson.get(type).asJsonObject.get("damageTaken").asJsonObject
moveTypes.keySet().forEach innerLoop@ {
val moveType = ElementalTypes.get(it) ?: return@innerLoop
val moveEffectiveness = moveTypes.get(it).asInt
val defenderMap = movesEffectiveness.getOrPut(moveType) { mutableMapOf() }
defenderMap[defenderType] = MoveEffectiveness.of(moveEffectiveness)
}
}
}
fun getMoveEffectiveness(moveType: ElementalType, defenderTypes: List<ElementalType?>): Double {
var multiplier = 1.0
defenderTypes.filterNotNull().forEach {
multiplier *= getMoveEffectiveness(moveType, it).multiplier
}
return multiplier
}
private fun getMoveEffectiveness(moveType: ElementalType, defenderType: ElementalType): MoveEffectiveness {
return movesEffectiveness[moveType]?.get(defenderType) ?: throw IllegalArgumentException("Unknown effectiveness type: $moveType $defenderType")
}
}
@@ -62,9 +62,9 @@ class NPCClass {
fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeString(resourceIdentifier.toString())
buffer.writeCollection(names) { _, v -> buffer.writeText(v) }
buffer.writeFloat(hitbox.width)
buffer.writeFloat(hitbox.height)
buffer.writeBoolean(hitbox.fixed)
buffer.writeFloat(this.hitbox.width)
buffer.writeFloat(this.hitbox.height)
buffer.writeBoolean(this.hitbox.fixed)
battleConfiguration.encode(buffer)
buffer.writeNullable(interaction) { _, value ->
buffer.writeString(value.type)
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.api.drop.ItemDropMethod
import com.cobblemon.mod.common.api.entity.EntityDimensionsAdapter
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.moves.TypeChart
import com.cobblemon.mod.common.api.moves.adapters.MoveTemplateAdapter
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffect
import com.cobblemon.mod.common.api.pokemon.effect.adapter.ShoulderEffectAdapter
@@ -125,6 +126,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
it.indicateSpeciesInitialized()
// Reload this with the mod
CobblemonHeldItemManager.load()
TypeChart.load()
Cobblemon.LOGGER.info("Loaded {} Pokémon species", this.speciesByIdentifier.size)
this.observable.emit(this)
}
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.battles.runner
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.battles.runner.graal.GraalShowdownService
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import java.util.UUID
/**
@@ -30,6 +31,7 @@ interface ShowdownService {
fun getAbilityIds(): JsonArray
fun getMoves(): JsonArray
fun getItemIds(): JsonArray
fun getTypeChart(): JsonObject
fun registerSpecies()
fun registerBagItems()
fun indicateSpeciesInitialized() {}
@@ -38,4 +40,4 @@ interface ShowdownService {
companion object {
val service: ShowdownService by lazy { GraalShowdownService() }
}
}
}
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.battles.ShowdownInterpreter
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import java.io.File
import java.io.IOException
import java.net.URI
@@ -152,6 +153,12 @@ class GraalShowdownService : ShowdownService {
return gson.fromJson(arrayResult, JsonArray::class.java)
}
override fun getTypeChart(): JsonObject {
val getCobbledItemIdsFn = context.getBindings("js").getMember("getTypeChart")
val arrayResult = getCobbledItemIdsFn.execute().asString()
return gson.fromJson(arrayResult, JsonObject::class.java)
}
override fun registerSpecies() {
val receiveSpeciesDataFn = this.context.getBindings("js").getMember("receiveSpeciesData")
val jsArray = this.context.eval("js", "new Array();")
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.pokemon.FormData
import com.cobblemon.mod.common.pokemon.Species
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.OutputStreamWriter
@@ -123,6 +124,13 @@ class SocketShowdownService(val host: String = "localhost", val port: Int = 1846
return gson.fromJson(response, JsonArray::class.java)
}
override fun getTypeChart(): JsonObject {
writer.write(">getTypeChart")
writer.flush()
val response = readMessage()
return gson.fromJson(response, JsonObject::class.java)
}
private fun sendSpeciesData(species: Species, form: FormData?) {
writer.write(">receiveSpeciesData ${gson.toJson(PokemonSpecies.ShowdownSpecies(species, form))}\n")
acknowledge()
@@ -184,16 +184,15 @@ class BattleGUI : Screen(battleLang("gui.title")), CobblemonRenderable {
override fun charTyped(chr: Char, modifiers: Int): Boolean {
if (chr.toString().equals(PartySendBinding.boundKey().displayName.string, ignoreCase = true) && CobblemonClient.battleOverlay.opacity == BattleOverlay.MAX_OPACITY && PartySendBinding.canAction()) {
return minimizeBattle()
val battle = CobblemonClient.battle ?: return false
battle.minimised = !battle.minimised
PartySendBinding.actioned()
return true
}
return super.charTyped(chr, modifiers)
}
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
if (button == PartySendBinding.boundKey().value && CobblemonClient.battleOverlay.opacity == BattleOverlay.MAX_OPACITY && PartySendBinding.canAction()) {
return minimizeBattle()
}
val battle = CobblemonClient.battle
if (battle?.spectating == true && specBackButton.isHovered(mouseX, mouseY)) {
RemoveSpectatorPacket(battle.battleId).sendToServer()
@@ -201,11 +200,4 @@ class BattleGUI : Screen(battleLang("gui.title")), CobblemonRenderable {
}
return super.mouseClicked(mouseX, mouseY, button)
}
private fun minimizeBattle(): Boolean {
val battle = CobblemonClient.battle ?: return false
battle.minimised = !battle.minimised
PartySendBinding.actioned()
return true
}
}
@@ -11,12 +11,11 @@ package com.cobblemon.mod.common.client.gui.battle.subscreen
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.gold
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.api.moves.TypeChart
import com.cobblemon.mod.common.api.text.*
import com.cobblemon.mod.common.battles.*
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.battle.ActiveClientBattlePokemon
import com.cobblemon.mod.common.client.battle.SingleActionRequest
import com.cobblemon.mod.common.client.gui.MoveCategoryIcon
import com.cobblemon.mod.common.client.gui.TypeIcon
@@ -24,12 +23,16 @@ import com.cobblemon.mod.common.client.gui.battle.BattleGUI
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.util.battleLang
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.lang
import com.cobblemon.mod.common.util.math.toRGB
import com.google.common.collect.Lists
import net.fabricmc.loader.impl.util.StringUtil
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.client.resources.sounds.SimpleSoundInstance
import net.minecraft.client.sounds.SoundManager
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import net.minecraft.util.Mth.floor
class BattleMoveSelection(
@@ -91,16 +94,16 @@ class BattleMoveSelection(
open val response: MoveActionResponse get() = MoveActionResponse(move.id, targetPnx)
open val selectable: Boolean get() = !move.disabled
val targetPnx: String? get() = targetList?.let { targets ->
val target: Targetable? get() = targetList?.let { targets ->
return@let when {
targets.isEmpty() -> null
targets.size == 1 -> targets[0].getPNX()
targets.size == 1 -> targets[0]
else -> null // TODO: multi-battles
}
}
val targetPnx: String? get() = target?.getPNX()
fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
val selectConditionOpacity = moveSelection.opacity * if (!selectable) 0.5F else 1F
blitk(
@@ -173,6 +176,8 @@ class BattleMoveSelection(
opacity = moveSelection.opacity,
centered = true
)
drawTooltip(context, mouseX, mouseY)
}
fun isHovered(mouseX: Double, mouseY: Double) = mouseX >= x && mouseX <= x + MOVE_WIDTH && mouseY >= y && mouseY <= y + MOVE_HEIGHT
@@ -182,6 +187,41 @@ class BattleMoveSelection(
moveSelection.playDownSound(Minecraft.getInstance().soundManager)
moveSelection.battleGUI.selectAction(moveSelection.request, response)
}
private fun drawTooltip(context: GuiGraphics, mouseX: Int, mouseY: Int) {
if (!isHovered(mouseX.toDouble(), mouseY.toDouble())) return
val textTooltip: MutableList<MutableComponent> = mutableListOf()
for (descriptionLine in StringUtil.wrapLines(moveTemplate.description.string, 80).split("\n")) {
textTooltip.add(Component.literal(descriptionLine).gray())
}
textTooltip.add(Component.literal(""))
if (moveTemplate.power > 0) textTooltip.add(lang("ui.power").append(String.format(": %d", moveTemplate.power.toInt())))
if (moveTemplate.accuracy > 0) textTooltip.add(lang("ui.accuracy").append(String.format(": %d%%", moveTemplate.accuracy.toInt())))
if (moveTemplate.power > 0 && moveTemplate.target != MoveTarget.self && target is ActiveClientBattlePokemon) {
val species = (target as ActiveClientBattlePokemon).battlePokemon?.species
if (species != null) {
val moveEffectiveness: Double = TypeChart.getMoveEffectiveness(elementalType, listOf(species.primaryType, species.secondaryType))
textTooltip.add(when {
moveEffectiveness == 0.0 -> lang("battle.ui.effectiveness.immunity", moveEffectiveness).gray()
moveEffectiveness < 1.0 -> lang("battle.ui.effectiveness.resistance", moveEffectiveness).gray()
moveEffectiveness > 1.0 -> lang("battle.ui.effectiveness.super_effective", moveEffectiveness).yellow()
else -> lang("battle.ui.effectiveness.normal", moveEffectiveness).white()
})
}
}
context.renderTooltip(
Minecraft.getInstance().font,
Lists.transform(textTooltip, Component::getVisualOrderText),
mouseX,
mouseY
)
}
}
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
@@ -70,7 +70,6 @@ import net.minecraft.world.InteractionResult
import net.minecraft.world.damagesource.DamageSource
import net.minecraft.world.entity.AgeableMob
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.EntityDimensions
import net.minecraft.world.entity.Pose
import net.minecraft.world.entity.ai.Brain
import net.minecraft.world.entity.ai.attributes.AttributeSupplier
@@ -102,8 +101,6 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
brain = makeBrain(brainDynamic ?: makeEmptyBrainDynamic())
}
}
this.refreshDimensions()
}
val level: Int
@@ -111,8 +108,6 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
var skill: Int? = null // range from 0 - 5
var hitbox: EntityDimensions? = null
var party: NPCPartyStore? = null
var isMovable: Boolean? = null
@@ -347,14 +342,6 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
it.putByteArray(DataKeys.NPC_PLAYER_TEXTURE_TEXTURE, playerTexture.texture)
})
}
val hitbox = hitbox
if (hitbox != null) {
nbt.put(DataKeys.NPC_HITBOX, CompoundTag().also {
it.putFloat(DataKeys.NPC_HITBOX_WIDTH, hitbox.width)
it.putFloat(DataKeys.NPC_HITBOX_HEIGHT, hitbox.height)
it.putBoolean(DataKeys.NPC_HITBOX_FIXED, hitbox.fixed)
})
}
val isMovable = isMovable
if (isMovable != null) {
nbt.putBoolean(DataKeys.NPC_IS_MOVABLE, isMovable)
@@ -374,6 +361,9 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
return nbt
}
override fun hasCustomName() = true
override fun isCustomNameVisible() = true
override fun load(nbt: CompoundTag) {
npc = NPCClasses.getByIdentifier(ResourceLocation.parse(nbt.getString(DataKeys.NPC_CLASS))) ?: NPCClasses.classes.first()
entityData.set(LEVEL, nbt.getInt(DataKeys.NPC_LEVEL).takeIf { it != 0 } ?: 1)
@@ -406,17 +396,7 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
this.isInvulnerable = if (nbt.contains(DataKeys.NPC_IS_INVULNERABLE)) nbt.getBoolean(DataKeys.NPC_IS_INVULNERABLE) else null
this.isLeashable = if (nbt.contains(DataKeys.NPC_IS_LEASHABLE)) nbt.getBoolean(DataKeys.NPC_IS_LEASHABLE) else null
this.allowProjectileHits = if (nbt.contains(DataKeys.NPC_ALLOW_PROJECTILE_HITS)) nbt.getBoolean(DataKeys.NPC_ALLOW_PROJECTILE_HITS) else null
this.hitbox = if (nbt.contains(DataKeys.NPC_HITBOX)) {
val hitboxNBT = nbt.getCompound(DataKeys.NPC_HITBOX)
val width = hitboxNBT.getFloat(DataKeys.NPC_HITBOX_WIDTH)
val height = hitboxNBT.getFloat(DataKeys.NPC_HITBOX_HEIGHT)
val fixed = hitboxNBT.getBoolean(DataKeys.NPC_HITBOX_FIXED)
if (fixed) EntityDimensions.fixed(width, height) else EntityDimensions.scalable(width, height)
} else {
null
}
updateAspects()
}
@@ -446,13 +426,9 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
updateAspects()
}
override fun hasCustomName() = true
override fun isCustomNameVisible() = true
override fun isPersistenceRequired() = !npc.canDespawn
override fun getDimensions(pose: Pose): EntityDimensions = hitbox ?: npc.hitbox
override fun getDefaultDimensions(pose: Pose) = npc.hitbox
override fun isPushable(): Boolean {
return isMovable ?: npc.isMovable
@@ -394,10 +394,9 @@ open class PokemonEntity(
// Deploy a platform if a non-wild Pokemon is touching water but not underwater.
// This can't be done in the BattleMovementGoal as the sleep goal will override it.
if (ticksLived > 5 && platform == PlatformType.NONE
&& ownerUUID != null
&& this.ownerUUID != null
&& isInWater && !isUnderWater
&& !exposedForm.behaviour.moving.swim.canBreatheUnderwater && !exposedForm.behaviour.moving.swim.canWalkOnWater
&& !getBehaviourFlag(PokemonBehaviourFlag.FLYING)) {
&& !exposedForm.behaviour.moving.swim.canBreatheUnderwater && !exposedForm.behaviour.moving.swim.canWalkOnWater) {
platform = PlatformType.getPlatformTypeForPokemon((exposedForm))
}
} else {
@@ -745,7 +744,6 @@ open class PokemonEntity(
goalSelector.addGoal(4, PokemonMoveIntoFluidGoal(this))
goalSelector.addGoal(5, SleepOnTrainerGoal(this))
goalSelector.addGoal(5, WildRestGoal(this))
goalSelector.addGoal(5, PokemonHideInGrassGoal(this))
if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.HAS_BEEN_SHEARED) != null) {
goalSelector.addGoal(5, EatBlockGoal(this))
@@ -1,111 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.entity.pokemon.ai.goals
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.toVec3d
import net.minecraft.core.BlockPos
import net.minecraft.world.entity.ai.goal.Goal
import net.minecraft.world.level.block.Blocks
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.AABB
class PokemonHideInGrassGoal(private val pokemonEntity: PokemonEntity): Goal() {
companion object {
private const val GRASS_SEARCH_HORIZONTAL_RANGE = 16.0
private const val GRASS_SEARCH_VERTICAL_RANGE = 2.0
private val SECONDS_IN_SAME_GRASS = 5 .. 10
private val VALID_GRASS_BLOCKS = setOf(
Blocks.SHORT_GRASS,
Blocks.TALL_GRASS,
Blocks.FERN,
Blocks.LARGE_FERN,
)
}
private var pickedGrassBlockPos: BlockPos? = null
private var ticksInGrass = 0
private var wantedTicksInGrass = 0
override fun canUse(): Boolean =
pokemonEntity.pokemon.species.behaviour.moving.hideInGrass
&& pokemonEntity.pokemon.isWild()
&& getNearbyGrassBlocks().isNotEmpty()
override fun start() {
super.start()
pickedGrassBlockPos = getNearbyGrassBlocks().random()
ticksInGrass = 0
wantedTicksInGrass = pokemonEntity.random.nextIntBetweenInclusive(SECONDS_IN_SAME_GRASS.first, SECONDS_IN_SAME_GRASS.last) * 20
}
override fun tick() {
super.tick()
val grassBlockCenterPos = pickedGrassBlockPos?.bottomCenter ?: return stop()
val couldMoveToGrass = pokemonEntity.navigation.moveTo(
grassBlockCenterPos.x,
grassBlockCenterPos.y,
grassBlockCenterPos.z,
1.0
)
if (!couldMoveToGrass) return stop()
ticksInGrass++
}
override fun canContinueToUse(): Boolean {
if (ticksInGrass >= wantedTicksInGrass) return false
pickedGrassBlockPos?.let {
val grassStillExists = isGrass(pokemonEntity.level().getBlockState(it))
if (!grassStillExists) return false
val grassBox = AABB.ofSize(it.toVec3d(), 0.5, 0.5, 0.5)
val isGrassOccupiedByAnotherEntity = pokemonEntity.level().getEntities(pokemonEntity, grassBox).isNotEmpty()
if (isGrassOccupiedByAnotherEntity) {
return false
}
} ?: return false
return true
}
override fun stop() {
super.stop()
pickedGrassBlockPos = null
ticksInGrass = 0
pokemonEntity.navigation.stop()
}
private fun getNearbyGrassBlocks(): List<BlockPos> {
val searchBox = AABB.ofSize(
pokemonEntity.position(),
GRASS_SEARCH_HORIZONTAL_RANGE,
GRASS_SEARCH_VERTICAL_RANGE,
GRASS_SEARCH_HORIZONTAL_RANGE
)
val grassBlocks: MutableList<BlockPos> = mutableListOf()
BlockPos.betweenClosedStream(searchBox).forEach {
val blockState = pokemonEntity.level().getBlockState(it)
if (isGrass(blockState)) {
grassBlocks.add(BlockPos(it))
}
}
return grassBlocks
}
private fun isGrass(blockState: BlockState): Boolean = VALID_GRASS_BLOCKS.contains(blockState.block)
}
@@ -50,7 +50,7 @@ class PokemonInBattleMovementGoal(val entity: PokemonEntity, val range: Int) : G
entity.navigation.moveTo(battlePos!!.x, battlePos!!.y, battlePos!!.z, 1.0)
hasMovedToPos = true
}
if (entity.ticksLived > 1 && !entity.getBehaviourFlag(PokemonBehaviourFlag.FLYING) && entity.navigation.isAirborne(entity.level(), entity.blockPosition())) {
if (entity.ticksLived > 1 && !entity.onGround() && !entity.getBehaviourFlag(PokemonBehaviourFlag.FLYING)) {
// Let flyers fly in battle if they're in the air
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
}
@@ -23,5 +23,4 @@ class MoveBehaviour {
val wanderSpeed = 1.0
val canLook = true
val looksAtEntities = true
val hideInGrass = false
}
@@ -219,10 +219,6 @@ object DataKeys {
const val NPC_IS_INVULNERABLE = "IsInvulnerable"
const val NPC_IS_LEASHABLE = "IsLeashable"
const val NPC_ALLOW_PROJECTILE_HITS = "AllowProjectileHits"
const val NPC_HITBOX = "Hitbox"
const val NPC_HITBOX_WIDTH = "Width"
const val NPC_HITBOX_HEIGHT = "Height"
const val NPC_HITBOX_FIXED = "Fixed"
// PokemonProperties
const val ELEMENTAL_TYPE = "ElementalType"
@@ -1268,6 +1268,7 @@
"cobblemon.ui.status.psn": "PSN",
"cobblemon.ui.status.slp": "SLP",
"cobblemon.ui.status.tox": "PSN",
"cobblemon.battle.ui.fight": "Fight",
"cobblemon.battle.ui.switch": "Switch",
"cobblemon.battle.ui.capture": "Catch",
@@ -1277,6 +1278,11 @@
"cobblemon.battle.ui.hide_label": "Press %1$s to move around.",
"cobblemon.battle.ui.actions_label": "You need to choose an action. Press %1$s.",
"cobblemon.battle.ui.effectiveness.normal": "%1$sx Normal",
"cobblemon.battle.ui.effectiveness.super_effective": "%1$sx Super Effective",
"cobblemon.battle.ui.effectiveness.resistance": "%1$sx Resistance",
"cobblemon.battle.ui.effectiveness.immunity": "%1$sx Immunity",
"cobblemon.ui.evolve": "Evolve",
"cobblemon.ui.evolution": "Evolution",
"cobblemon.ui.evolve.hint": "%1$s seems ready to evolve!",
@@ -6770,7 +6776,7 @@
"cobblemon.ability.schooling": "Schooling",
"cobblemon.ability.schooling.desc": "When it has a lot of HP, the Pokémon forms a powerful school. It stops schooling when its HP is low.",
"cobblemon.ability.scrappy": "Scrappy",
"cobblemon.ability.scrappy.desc": "The Pokémon can hit Ghost-type Pokémon with Normal- and Fighting-type moves. It also grants immunity to Intimidate.",
"cobblemon.ability.scrappy.desc": "The Pokémon can hit Ghost-type Pokémon with Normal- and Fighting-type moves.",
"cobblemon.ability.screencleaner": "Screen Cleaner",
"cobblemon.ability.screencleaner.desc": "When the Pokémon enters a battle, the effects of Light Screen, Reflect, and Aurora Veil are nullified for both opposing and ally Pokémon.",
"cobblemon.ability.seedsower": "Seed Sower",
@@ -1,9 +0,0 @@
{
"item": "cobblemon:enigma_berry",
"effects": [
{
"type": "cobblemon:ha_chance",
"chance": 0.05
}
]
}
@@ -0,0 +1,9 @@
{
"item": "cobblemon:enigma_berry",
"effects": [
{
"type": "cobblemon:ha_chance",
"chance": 0.05
}
]
}
@@ -1,8 +0,0 @@
{
"item": "cobblemon:berry_sweet",
"effects": [
{
"type": "cobblemon:inert"
}
]
}
@@ -1,8 +0,0 @@
{
"item": "cobblemon:clover_sweet",
"effects": [
{
"type": "cobblemon:inert"
}
]
}
@@ -1,8 +0,0 @@
{
"item": "cobblemon:flower_sweet",
"effects": [
{
"type": "cobblemon:inert"
}
]
}
@@ -1,8 +0,0 @@
{
"item": "cobblemon:love_sweet",
"effects": [
{
"type": "cobblemon:inert"
}
]
}
@@ -1,8 +0,0 @@
{
"item": "cobblemon:ribbon_sweet",
"effects": [
{
"type": "cobblemon:inert"
}
]
}
@@ -1,8 +0,0 @@
{
"item": "cobblemon:star_sweet",
"effects": [
{
"type": "cobblemon:inert"
}
]
}
@@ -1,8 +0,0 @@
{
"item": "cobblemon:strawberry_sweet",
"effects": [
{
"type": "cobblemon:inert"
}
]
}
@@ -1,9 +1,9 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" GA",
"GGA",
"II "
"GCA",
"ICA",
"I "
],
"key": {
"I": {
@@ -12,6 +12,9 @@
"G": {
"item": "minecraft:gold_ingot"
},
"C": {
"item": "minecraft:copper_ingot"
},
"A": {
"item": "minecraft:amethyst_shard"
}
@@ -1,20 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"IA",
"CI",
"C "
" Q",
"CPC",
"Q "
],
"key": {
"I": {
"item": "minecraft:iron_ingot"
},
"C": {
"item": "minecraft:copper_ingot"
},
"A": {
"item": "minecraft:amethyst_shard"
}
"Q": {
"item": "minecraft:quartz"
},
"C": {
"item": "minecraft:copper_ingot"
},
"P": {
"item": "minecraft:ender_pearl"
}
},
"result": {
"id": "cobblemon:wide_lens"
@@ -1,8 +1,8 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"AGG",
"GCC",
"AGC",
"GGC",
" C"
],
"key": {
@@ -5,7 +5,22 @@
],
"maxY": 62,
"neededNearbyBlocks": [
"#cobblemon:ancient_city_blocks"
"minecraft:chiseled_deepslate",
"minecraft:cobbled_deepslate_wall",
"minecraft:cracked_deepslate_bricks",
"minecraft:cracked_deepslate_tiles",
"minecraft:deepslate_brick_slab",
"minecraft:deepslate_brick_stairs",
"minecraft:deepslate_brick_wall",
"minecraft:deepslate_bricks",
"minecraft:deepslate_tile_slab",
"minecraft:deepslate_tile_stairs",
"minecraft:deepslate_tile_wall",
"minecraft:deepslate_tiles",
"minecraft:polished_basalt",
"minecraft:polished_deepslate",
"minecraft:polished_deepslate_slab",
"minecraft:polished_deepslate_wall"
]
}
}
Loaded 100 of 470 files, more files were not shown because too many files have changed in this diff. Show more