Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da82eb8d61 | ||
|
|
2dc93f3336 | ||
|
|
e8864418d4 | ||
|
|
82b418d54d | ||
|
|
d5a08314eb | ||
|
|
062c32be2a | ||
|
|
09590b49cd | ||
|
|
420cbd2c99 | ||
|
|
0380013f37 | ||
|
|
6c1fcc103a | ||
|
|
59b01c3988 | ||
|
|
678fa2d0ce | ||
|
|
94abd79923 | ||
|
|
0a1931aaae | ||
|
|
85d76dcc29 | ||
|
|
bd0a9ef654 | ||
|
|
7a702e276c | ||
|
|
3f9a2825cb | ||
|
|
d1462bc27b | ||
|
|
211b14dbd0 | ||
|
|
47e83003c3 | ||
|
|
59134c4212 | ||
|
|
44b434562c | ||
|
|
344b0750f9 | ||
|
|
10d9d97c11 | ||
|
|
94bcfba076 | ||
|
|
69a75ffcd4 | ||
|
|
cc1317dd06 | ||
|
|
e15ac73b1b | ||
|
|
6c6576c117 | ||
|
|
ebdfa7edc0 | ||
|
|
297e8eae77 | ||
|
|
ea8179018d | ||
|
|
14fccfae1d | ||
|
|
a3c5a6c377 | ||
|
|
abb5346305 | ||
|
|
9466f66721 | ||
|
|
716ea55bc7 | ||
|
|
15f0ad1821 | ||
|
|
a16975c750 | ||
|
|
c0e6d87c40 | ||
|
|
91078b917e | ||
|
|
b7e27fa52a | ||
|
|
dc87ffd2a8 | ||
|
|
cbeda361d4 | ||
|
|
079a2fb50d |
@@ -300,6 +300,8 @@
|
||||
- Regional Foods will now prioritize being eaten instead of used for healing Pokémon, shift clicking will use it as healing
|
||||
- Resolved Z-Fighting on Pokédex Models
|
||||
- Restored Ninjask's ability to do barrel rolls
|
||||
- Fixed a crash caused by adding enchanted items to the Resurrection Machine
|
||||
- Fixed a crash that could occur when starting a PvN battle with only fainted Pokémon.
|
||||
|
||||
### Fixes
|
||||
- Fixed Croagunk's walkspeed
|
||||
@@ -360,6 +362,7 @@
|
||||
- Separated all the functions of MoLangFunctions.kt into their own files.
|
||||
- Spawn buckets and their base weights are now provided by the spawner, with different base weights for world, fishing, snack, and habitat spawn buckets.
|
||||
- Removed "SpawnBucket" class in favour of just storing maps of bucket names to weights.
|
||||
- Fixed nicknames not being applied to Pokémon spawned from `spawn_pool_world` files
|
||||
|
||||
### Molang & Datapacks
|
||||
- Added `moveset_builders` datapack folder for different styles of movesets.
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.api.gui
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.gui.components.AbstractWidget
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput
|
||||
import net.minecraft.network.chat.Component
|
||||
@@ -54,8 +55,6 @@ abstract class ParentWidget(
|
||||
}
|
||||
|
||||
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
if (!active) return false
|
||||
|
||||
return children.any {
|
||||
it.mouseClicked(pMouseX, pMouseY, pButton)
|
||||
}
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.gui
|
||||
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
interface TreeNode<T> {
|
||||
val children: List<TreeNode<T>>
|
||||
}
|
||||
|
||||
class TreeDrawingNode<T>(
|
||||
val value: T,
|
||||
val children: List<TreeDrawingNode<T>>,
|
||||
) {
|
||||
var x = 0
|
||||
var y = 0
|
||||
var offset = 0
|
||||
}
|
||||
|
||||
fun <T> createDrawingTree(treeNode: TreeNode<T>): TreeDrawingNode<T> {
|
||||
val root = setup(treeNode, 0, mutableListOf<Int>(), mutableListOf<Int>())
|
||||
addMods(root, 0)
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <T> setup(
|
||||
treeNode: TreeNode<T>,
|
||||
depth: Int,
|
||||
nexts: MutableList<Int>,
|
||||
offset: MutableList<Int>,
|
||||
): TreeDrawingNode<T> {
|
||||
val children = treeNode.children.map { child ->
|
||||
setup(child, depth + 1, nexts, offset)
|
||||
}
|
||||
|
||||
val treeDrawingNode = TreeDrawingNode<T>(treeNode as T, children)
|
||||
treeDrawingNode.y = depth
|
||||
|
||||
while (nexts.size <= depth) {
|
||||
nexts.add(0)
|
||||
}
|
||||
|
||||
while (offset.size <= depth) {
|
||||
offset.add(0)
|
||||
}
|
||||
|
||||
var place =
|
||||
if (children.isEmpty()) {
|
||||
nexts[depth]
|
||||
} else if (children.size == 1) {
|
||||
// children.first().x - 1
|
||||
children.first().x
|
||||
} else {
|
||||
// (children[0].x + children[1].x) / 2
|
||||
(children.first().x + children.last().x) / 2
|
||||
}
|
||||
|
||||
offset[depth] = max(offset[depth], nexts[depth] - place)
|
||||
|
||||
if (children.isEmpty()) {
|
||||
treeDrawingNode.x = place
|
||||
} else {
|
||||
treeDrawingNode.x = place + offset[depth]
|
||||
}
|
||||
|
||||
nexts[depth] += 2
|
||||
treeDrawingNode.offset = offset[depth]
|
||||
|
||||
return treeDrawingNode
|
||||
}
|
||||
|
||||
private fun <T> addMods(
|
||||
treeNode: TreeDrawingNode<T>,
|
||||
modSum: Int,
|
||||
) {
|
||||
treeNode.x += modSum
|
||||
val newModSum = modSum + treeNode.offset
|
||||
|
||||
treeNode.children.forEach { child ->
|
||||
addMods(child, newModSum)
|
||||
}
|
||||
}
|
||||
|
||||
data class TreeDrawingBounds(val minX: Int, val maxX: Int, val minY: Int, val maxY: Int) {
|
||||
val width = maxX - minX
|
||||
val height = maxY - minY
|
||||
val xCenter = (maxX + minX) / 2.0
|
||||
val yCenter = (maxY + minY) / 2.0
|
||||
}
|
||||
|
||||
fun <T> calculateBounds(treeDrawingNode: TreeDrawingNode<T>): TreeDrawingBounds {
|
||||
var minX = treeDrawingNode.x
|
||||
var maxX = treeDrawingNode.x
|
||||
var minY = treeDrawingNode.y
|
||||
var maxY = treeDrawingNode.y
|
||||
|
||||
for (child in treeDrawingNode.children) {
|
||||
val childBounds = calculateBounds(child)
|
||||
|
||||
minX = min(minX, childBounds.minX)
|
||||
maxX = max(maxX, childBounds.maxX)
|
||||
minY = min(minY, childBounds.minY)
|
||||
maxY = max(maxY, childBounds.maxY)
|
||||
}
|
||||
|
||||
return TreeDrawingBounds(minX, maxX, minY, maxY)
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class HabitatPool {
|
||||
pool.spawns = spawns
|
||||
return pool
|
||||
} else {
|
||||
return HabitatPools.habitatPoolsById[poolId] ?: HabitatPool.default()
|
||||
return HabitatPools.habitatPoolsById[poolId] ?: default()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,14 @@ class HabitatPool {
|
||||
return spawns.mapNotNull { it.createSpawnDetail(habitatBlockEntity) }
|
||||
}
|
||||
|
||||
fun getPhaseCount(): Int {
|
||||
return spawns
|
||||
.flatMap { it.phases?.ranges?.flatten() ?: emptySet() }
|
||||
.toSet()
|
||||
.count()
|
||||
.coerceAtLeast(1)
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(id)
|
||||
buffer.writeUtf(name)
|
||||
|
||||
@@ -17,7 +17,6 @@ import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class HabitatSettingsDTO() {
|
||||
var numberOfPhases = 1
|
||||
var phaseOrder = HabitatPhaseOrder.SIMPLE
|
||||
lateinit var levelRange: IntRange
|
||||
var modifiers: String = ""
|
||||
@@ -28,7 +27,6 @@ class HabitatSettingsDTO() {
|
||||
var naturalSettings: NaturalHabitatSettingsDTO? = null
|
||||
|
||||
constructor(habitatBlockEntity: HabitatBlockEntity) : this() {
|
||||
this.numberOfPhases = habitatBlockEntity.numberOfPhases
|
||||
this.phaseOrder = habitatBlockEntity.phaseOrder
|
||||
this.levelRange = habitatBlockEntity.levelRange
|
||||
this.modifiers = habitatBlockEntity.modifiers.asString()
|
||||
@@ -44,7 +42,6 @@ class HabitatSettingsDTO() {
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeInt(numberOfPhases)
|
||||
buffer.writeEnum(phaseOrder)
|
||||
buffer.writeInt(levelRange.first)
|
||||
buffer.writeInt(levelRange.last)
|
||||
@@ -60,7 +57,6 @@ class HabitatSettingsDTO() {
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.numberOfPhases = buffer.readInt()
|
||||
this.phaseOrder = buffer.readEnum(HabitatPhaseOrder::class.java)
|
||||
val levelRangeStart = buffer.readInt()
|
||||
val levelRangeEnd = buffer.readInt()
|
||||
|
||||
@@ -72,40 +72,6 @@ abstract class AbstractPokedexManager {
|
||||
} ?: PokedexEntryProgress.UNREGISTERED
|
||||
}
|
||||
|
||||
fun getHighestKnowledgeFor(entry: PokedexEntry, form: PokedexForm?): PokedexEntryProgress {
|
||||
if (form == null) return getHighestKnowledgeFor(entry)
|
||||
|
||||
val speciesRecord = getSpeciesRecord(entry.speciesId) ?: return PokedexEntryProgress.UNREGISTERED
|
||||
val hasAllAspects = entry.conditionAspects.all(speciesRecord::hasAspect)
|
||||
if (!hasAllAspects) {
|
||||
return PokedexEntryProgress.UNREGISTERED
|
||||
}
|
||||
|
||||
return speciesRecord.getFormRecord(form.displayForm)?.knowledge ?: PokedexEntryProgress.UNREGISTERED
|
||||
}
|
||||
|
||||
fun getHighestKnowledgeFor(entry: PokedexEntry, form: PokedexForm?, aspects: Iterable<String>): PokedexEntryProgress {
|
||||
val formKnowledge = getHighestKnowledgeFor(entry, form)
|
||||
|
||||
if (formKnowledge == PokedexEntryProgress.UNREGISTERED) return PokedexEntryProgress.UNREGISTERED
|
||||
|
||||
val seenAspects = getSeenAspects(entry)
|
||||
val allSeenAspects = aspects
|
||||
// TODO this is ugly
|
||||
.filter { it ->
|
||||
if (Dexes.equivalentFormsLookup[it] != null) return@filter false
|
||||
if (it.uppercase() in setOf(Gender.MALE.name, Gender.FEMALE.name, Gender.GENDERLESS.name)) return@filter false
|
||||
if ("shiny".equals(it, ignoreCase = true)) return@filter false
|
||||
|
||||
return@filter true
|
||||
}
|
||||
.all { it -> seenAspects.contains(it) }
|
||||
|
||||
if (!allSeenAspects) return PokedexEntryProgress.UNREGISTERED
|
||||
|
||||
return formKnowledge
|
||||
}
|
||||
|
||||
fun getEncounteredForms(entry: PokedexEntry) : List<PokedexForm> {
|
||||
return getFormsWithKnowledge(entry, PokedexEntryProgress.SEEN)
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@ package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.pokedex.def.PokedexDef
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PokedexDexSyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.CodecBackedAdapter
|
||||
@@ -43,17 +40,6 @@ object Dexes : JsonDataRegistry<PokedexDef> {
|
||||
//Maps a dex id to its PokedexDef
|
||||
val dexEntryMap = linkedMapOf<ResourceLocation, PokedexDef>()
|
||||
|
||||
val equivalentForms = mapOf(
|
||||
"galar" to listOf("region-bias-galar", "bias-galar", "galar-bias", "galarian", "galar"),
|
||||
"alola" to listOf("region-bias-alola", "bias-alola", "alola-bias", "alolan", "alola"),
|
||||
"hisui" to listOf("region-bias-hisui", "bias-hisui", "hisui-bias", "hisuian", "hisui"),
|
||||
"paldea" to listOf("region-bias-paldea", "bias-paldea", "paldea-bias", "paldean", "paldea"),
|
||||
)
|
||||
|
||||
val equivalentFormsLookup = equivalentForms.flatMap { (key, values) ->
|
||||
values.map { it to key }
|
||||
}.toMap()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokedexDef>) {
|
||||
dexEntryMap.clear()
|
||||
data.entries.sortedBy { it.value.sortOrder }.forEach { (id, def) -> dexEntryMap[id] = def }
|
||||
@@ -63,34 +49,4 @@ object Dexes : JsonDataRegistry<PokedexDef> {
|
||||
override fun sync(player: ServerPlayer) {
|
||||
PokedexDexSyncPacket(dexEntryMap.values).sendToPlayer(player)
|
||||
}
|
||||
|
||||
fun findDexEntryBySpeciesId(regionId: ResourceLocation, speciesId: ResourceLocation): PokedexEntry? {
|
||||
return dexEntryMap[regionId]?.getEntries()?.firstOrNull { it -> it.speciesId == speciesId }
|
||||
}
|
||||
|
||||
fun findDexEntryBySpeciesId(speciesId: ResourceLocation): PokedexEntry? {
|
||||
return findDexEntryBySpeciesId(cobblemonResource("national"), speciesId)
|
||||
}
|
||||
|
||||
fun findRootDexEntryBySpeciesId(speciesId: ResourceLocation, formName: String): Pair<PokedexEntry, PokedexForm> {
|
||||
var rootSpecies = speciesId.let { PokemonSpecies.getByIdentifier(it) }!!
|
||||
while (rootSpecies.preEvolution != null) {
|
||||
rootSpecies = rootSpecies.preEvolution!!.species
|
||||
}
|
||||
|
||||
val entry = findDexEntryBySpeciesId(rootSpecies.resourceIdentifier)
|
||||
?: throw RuntimeException("Root dex entry not found")
|
||||
|
||||
val formEquivalents = getFormEquivalents(formName)
|
||||
val form =
|
||||
entry.forms.firstOrNull { formEquivalents.contains(it.displayForm.lowercase()) } ?:
|
||||
entry.forms.first { it.displayForm.equals("Normal", ignoreCase = true) }
|
||||
|
||||
return entry to form
|
||||
}
|
||||
|
||||
fun getFormEquivalents(formName: String): List<String> {
|
||||
val key = equivalentFormsLookup[formName.lowercase()]
|
||||
return equivalentForms[key] ?: listOf(formName.lowercase())
|
||||
}
|
||||
}
|
||||
@@ -759,6 +759,7 @@ open class PokemonProperties {
|
||||
shiny?.let { json.addProperty(DataKeys.POKEMON_SHINY, it) }
|
||||
gender?.let { json.addProperty(DataKeys.POKEMON_GENDER, it.name) }
|
||||
species?.let { json.addProperty(DataKeys.POKEMON_SPECIES_TEXT, it) }
|
||||
nickname?.let { json.addProperty(DataKeys.POKEMON_NICKNAME, it.string) }
|
||||
form?.let { json.addProperty(DataKeys.POKEMON_FORM_ID, it) }
|
||||
friendship?.let { json.addProperty(DataKeys.POKEMON_FRIENDSHIP, it) }
|
||||
fullness?.let { json.addProperty(DataKeys.POKEMON_FULLNESS, it) }
|
||||
@@ -795,6 +796,7 @@ open class PokemonProperties {
|
||||
shiny = json.get(DataKeys.POKEMON_SHINY)?.asBoolean
|
||||
gender = json.get(DataKeys.POKEMON_GENDER)?.asString?.let { Gender.valueOf(it) }
|
||||
species = json.get(DataKeys.POKEMON_SPECIES_TEXT)?.asString
|
||||
nickname = json.get(DataKeys.POKEMON_NICKNAME)?.asString?.let(Component::literal)
|
||||
form = json.get(DataKeys.POKEMON_FORM_ID)?.asString
|
||||
friendship = json.get(DataKeys.POKEMON_FRIENDSHIP)?.asInt
|
||||
fullness = json.get(DataKeys.POKEMON_FULLNESS)?.asInt
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon.evolution
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.*
|
||||
|
||||
interface EvolutionVisitor<R> {
|
||||
fun visit(evolution: Evolution): R? {
|
||||
return when (evolution) {
|
||||
is BlockClickEvolution -> visitBlockClickEvolution(evolution)
|
||||
is DummyEvolution -> visitDummyEvolution(evolution)
|
||||
is ItemInteractionEvolution -> visitItemInteractionEvolution(evolution)
|
||||
is LevelUpEvolution -> visitLevelUpEvolution(evolution)
|
||||
is TradeEvolution -> visitTradeEvolution(evolution)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun visitBlockClickEvolution(blockClickEvolution: BlockClickEvolution): R
|
||||
fun visitDummyEvolution(evolution: Evolution): R // TODO: Use dummyEvolution?
|
||||
fun visitItemInteractionEvolution(itemInteractionEvolution: ItemInteractionEvolution): R
|
||||
fun visitLevelUpEvolution(levelUpEvolution: LevelUpEvolution): R
|
||||
fun visitTradeEvolution(tradeEvolution: TradeEvolution): R
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
abstract class EntityQueryRequirement : Requirement() {
|
||||
interface EntityQueryRequirement : Requirement {
|
||||
override fun check(pokemon: Pokemon): Boolean {
|
||||
val queriedEntity = pokemon.entity ?: pokemon.getOwnerPlayer() ?: return false
|
||||
return this.check(pokemon, queriedEntity)
|
||||
@@ -34,5 +34,5 @@ abstract class EntityQueryRequirement : Requirement() {
|
||||
* @param queriedEntity The [LivingEntity] that can be compared in context of a [Level].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
abstract fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean
|
||||
fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import net.minecraft.world.entity.player.Player
|
||||
* @author Polymeta
|
||||
* @since May 6th, 2025
|
||||
*/
|
||||
abstract class OwnerQueryRequirement : Requirement() {
|
||||
interface OwnerQueryRequirement : Requirement {
|
||||
override fun check(pokemon: Pokemon): Boolean {
|
||||
val owner = pokemon.getOwnerEntity() ?: return false
|
||||
return when (owner) {
|
||||
@@ -44,7 +44,7 @@ abstract class OwnerQueryRequirement : Requirement() {
|
||||
* @param owner The [Player] that owns this [Pokemon].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
abstract fun checkPlayer(pokemon: Pokemon, owner: Player): Boolean
|
||||
fun checkPlayer(pokemon: Pokemon, owner: Player): Boolean
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] & [NPCEntity] satisfies the requirement.
|
||||
@@ -55,5 +55,5 @@ abstract class OwnerQueryRequirement : Requirement() {
|
||||
* @param owner The [NPCEntity] that owns this [Pokemon].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
abstract fun checkNPC(pokemon: Pokemon, owner: NPCEntity): Boolean
|
||||
fun checkNPC(pokemon: Pokemon, owner: NPCEntity): Boolean
|
||||
}
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.pokemon.requirement
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.ContextEvolution
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Represents a universal requirement suitable for various checks on pokemon..
|
||||
@@ -23,7 +22,7 @@ import net.minecraft.resources.ResourceLocation
|
||||
* @author Licious
|
||||
* @since March 19th, 2022
|
||||
*/
|
||||
abstract class Requirement {
|
||||
fun interface Requirement {
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] satisfies the requirement.
|
||||
@@ -31,8 +30,6 @@ abstract class Requirement {
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
abstract fun check(pokemon: Pokemon): Boolean
|
||||
fun check(pokemon: Pokemon): Boolean
|
||||
|
||||
val pokedexIcon: ResourceLocation? = null
|
||||
val pokedexTooltip: String? = null
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon.requirement
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.requirements.*
|
||||
|
||||
interface RequirementVisitor<R> {
|
||||
fun visit(requirement: Requirement): R? {
|
||||
return when (requirement) {
|
||||
is AdvancementRequirement -> visitAdvancementRequirement(requirement)
|
||||
is AnyRequirement -> visitAnyRequirement(requirement)
|
||||
is AreaRequirement -> visitAreaRequirement(requirement)
|
||||
is AttackDefenceRatioRequirement -> visitAttackDefenceRatioRequirement(requirement)
|
||||
is BattleCriticalHitsRequirement -> visitBattleCriticalHitsRequirement(requirement)
|
||||
is BiomeRequirement -> visitBiomeRequirement(requirement)
|
||||
is BlocksTraveledRequirement -> visitBlocksTraveledRequirement(requirement)
|
||||
is DamageTakenRequirement -> visitDamageTakenRequirement(requirement)
|
||||
is DefeatRequirement -> visitDefeatRequirement(requirement)
|
||||
is FriendshipRequirement -> visitFriendshipRequirement(requirement)
|
||||
is HeldItemRequirement -> visitHeldItemRequirement(requirement)
|
||||
is LevelRequirement -> visitLevelRequirement(requirement)
|
||||
is MoonPhaseRequirement -> visitMoonPhaseRequirement(requirement)
|
||||
is MoveSetRequirement -> visitMoveSetRequirement(requirement)
|
||||
is MoveTypeRequirement -> visitMoveTypeRequirement(requirement)
|
||||
is OwnerHoldsItemRequirement -> visitOwnerHoldsItemRequirement(requirement)
|
||||
is PartyMemberRequirement -> visitPartyMemberRequirement(requirement)
|
||||
is PokemonPropertiesRequirement -> visitPokemonPropertiesRequirement(requirement)
|
||||
is PropertyRangeRequirement -> visitPropertyRangeRequirement(requirement)
|
||||
is RecoilRequirement -> visitRecoilRequirement(requirement)
|
||||
is StatCompareRequirement -> visitStatCompareRequirement(requirement)
|
||||
is StatEqualRequirement -> visitStatEqualRequirement(requirement)
|
||||
is StructureRequirement -> visitStructureRequirement(requirement)
|
||||
is TimeRangeRequirement -> visitTimeRangeRequirement(requirement)
|
||||
is UseMoveRequirement -> visitUseMoveRequirement(requirement)
|
||||
is WeatherRequirement -> visitWeatherRequirement(requirement)
|
||||
is WorldRequirement -> visitWorldRequirement(requirement)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun visitAdvancementRequirement(advancementRequirement: AdvancementRequirement): R
|
||||
fun visitAnyRequirement(anyRequirement: AnyRequirement): R
|
||||
fun visitAreaRequirement(areaRequirement: AreaRequirement): R
|
||||
fun visitAttackDefenceRatioRequirement(attackDefenceRatioRequirement: AttackDefenceRatioRequirement): R
|
||||
fun visitBattleCriticalHitsRequirement(battleCriticalHitsRequirement: BattleCriticalHitsRequirement): R
|
||||
fun visitBiomeRequirement(biomeRequirement: BiomeRequirement): R
|
||||
fun visitBlocksTraveledRequirement(blocksTraveledRequirement: BlocksTraveledRequirement): R
|
||||
fun visitDamageTakenRequirement(damageTakenRequirement: DamageTakenRequirement): R
|
||||
fun visitDefeatRequirement(defeatRequirement: DefeatRequirement): R
|
||||
fun visitFriendshipRequirement(friendshipRequirement: FriendshipRequirement): R
|
||||
fun visitHeldItemRequirement(heldItemRequirement: HeldItemRequirement): R
|
||||
fun visitLevelRequirement(levelRequirement: LevelRequirement): R
|
||||
fun visitMoonPhaseRequirement(moonPhaseRequirement: MoonPhaseRequirement): R
|
||||
fun visitMoveSetRequirement(moveSetRequirement: MoveSetRequirement): R
|
||||
fun visitMoveTypeRequirement(moveTypeRequirement: MoveTypeRequirement): R
|
||||
fun visitOwnerHoldsItemRequirement(ownerHoldsItemRequirement: OwnerHoldsItemRequirement): R
|
||||
fun visitPartyMemberRequirement(partyMemberRequirement: PartyMemberRequirement): R
|
||||
fun visitPokemonPropertiesRequirement(pokemonPropertiesRequirement: PokemonPropertiesRequirement): R
|
||||
fun visitPropertyRangeRequirement(propertyRangeRequirement: PropertyRangeRequirement): R
|
||||
fun visitRecoilRequirement(recoilRequirement: RecoilRequirement): R
|
||||
fun visitStatCompareRequirement(statCompareRequirement: StatCompareRequirement): R
|
||||
fun visitStatEqualRequirement(statEqualRequirement: StatEqualRequirement): R
|
||||
fun visitStructureRequirement(structureRequirement: StructureRequirement): R
|
||||
fun visitTimeRangeRequirement(timeRangeRequirement: TimeRangeRequirement): R
|
||||
fun visitUseMoveRequirement(useMoveRequirement: UseMoveRequirement): R
|
||||
fun visitWeatherRequirement(weatherRequirement: WeatherRequirement): R
|
||||
fun visitWorldRequirement(worldRequirement: WorldRequirement): R
|
||||
}
|
||||
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.spawning
|
||||
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange.Companion.timeRanges
|
||||
import com.cobblemon.mod.common.api.spawning.condition.SpawningCondition
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangesAdapter
|
||||
|
||||
/**
|
||||
@@ -51,25 +49,4 @@ class TimeRange : IntRanges {
|
||||
|
||||
constructor() : super()
|
||||
constructor(vararg ranges: IntRange) : super(*ranges)
|
||||
|
||||
fun displayName(): MutableComponent? {
|
||||
val key = timeRanges.entries.firstOrNull { entry -> this == entry.value }?.key ?: return null
|
||||
return lang("ui.time_range.$key")
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is TimeRange) return false
|
||||
|
||||
if (other.ranges.size != this.ranges.size) return false
|
||||
other.ranges.forEachIndexed { index, otherRange ->
|
||||
if (this.ranges[index] != otherRange) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return ranges.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.condition
|
||||
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.world.level.Level
|
||||
|
||||
/**
|
||||
@@ -44,7 +42,4 @@ enum class MoonPhase {
|
||||
fun ofWorld(world: Level): MoonPhase = VALUES[world.moonPhase]
|
||||
}
|
||||
|
||||
fun displayName(): MutableComponent {
|
||||
return lang("ui.moon_phase.${this.name.lowercase()}")
|
||||
}
|
||||
}
|
||||
@@ -349,11 +349,12 @@ object BattleBuilder {
|
||||
npcPartyStores.add(npcParty)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
val playerAvailablePokemon = playerActor.pokemonList.count { it.health > 0 }
|
||||
if (playerAvailablePokemon < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = playerActor.pokemonList.size
|
||||
hadCount = playerAvailablePokemon
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,8 @@ class TrackerActor(val uuid: UUID) {
|
||||
//we assume that AI knows it all about our allies
|
||||
trackerActor.party.addAll(actor.pokemonList.map { createAllied(it) })
|
||||
actor.activePokemon.forEach {
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == it.battlePokemon!!.uuid }
|
||||
val battlePokemon = it.battlePokemon ?: return@forEach
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == battlePokemon.uuid }
|
||||
trackerActor.party.remove(active)
|
||||
trackerActor.activePokemon.add(active)
|
||||
}
|
||||
@@ -176,7 +177,8 @@ class TrackerActor(val uuid: UUID) {
|
||||
//only know basics of what we see right now
|
||||
trackerActor.party.addAll(actor.pokemonList.map { createOpposing(it) })
|
||||
actor.activePokemon.forEach {
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == it.battlePokemon!!.uuid }
|
||||
val battlePokemon = it.battlePokemon ?: return@forEach
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == battlePokemon.uuid }
|
||||
trackerActor.party.remove(active)
|
||||
trackerActor.activePokemon.add(active)
|
||||
}
|
||||
|
||||
@@ -16,24 +16,20 @@ import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.ContainerHelper
|
||||
import net.minecraft.world.Containers
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.ItemInteractionResult
|
||||
import net.minecraft.world.WorldlyContainer
|
||||
import net.minecraft.world.*
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.level.gameevent.GameEvent
|
||||
import java.util.OptionalInt
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import java.util.*
|
||||
import kotlin.math.pow
|
||||
|
||||
class DiscShelfBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(CobblemonBlockEntities.DISC_SHELF, pos, state), WorldlyContainer {
|
||||
@@ -134,25 +130,7 @@ class DiscShelfBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobbl
|
||||
return stack.item is TechnicalMachineItem
|
||||
|| stack.item == CobblemonItems.UPGRADE
|
||||
|| stack.item == CobblemonItems.DUBIOUS_DISC
|
||||
|| stack.item == Items.MUSIC_DISC_13
|
||||
|| stack.item == Items.MUSIC_DISC_CAT
|
||||
|| stack.item == Items.MUSIC_DISC_BLOCKS
|
||||
|| stack.item == Items.MUSIC_DISC_CHIRP
|
||||
|| stack.item == Items.MUSIC_DISC_FAR
|
||||
|| stack.item == Items.MUSIC_DISC_MALL
|
||||
|| stack.item == Items.MUSIC_DISC_MELLOHI
|
||||
|| stack.item == Items.MUSIC_DISC_STAL
|
||||
|| stack.item == Items.MUSIC_DISC_STRAD
|
||||
|| stack.item == Items.MUSIC_DISC_WARD
|
||||
|| stack.item == Items.MUSIC_DISC_11
|
||||
|| stack.item == Items.MUSIC_DISC_WAIT
|
||||
|| stack.item == Items.MUSIC_DISC_OTHERSIDE
|
||||
|| stack.item == Items.MUSIC_DISC_5
|
||||
|| stack.item == Items.MUSIC_DISC_RELIC
|
||||
|| stack.item == Items.MUSIC_DISC_PRECIPICE
|
||||
|| stack.item == Items.MUSIC_DISC_CREATOR
|
||||
|| stack.item == Items.MUSIC_DISC_CREATOR_MUSIC_BOX
|
||||
|| stack.item == Items.MUSIC_DISC_PIGSTEP
|
||||
|| stack.has(DataComponents.JUKEBOX_PLAYABLE)
|
||||
}
|
||||
|
||||
fun onNoteBlockPulse(level: Level, noteBlockPos: BlockPos, soundEvent: SoundEvent) {
|
||||
|
||||
@@ -60,10 +60,12 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
|
||||
var spawningStyle: HabitatSpawningStyle = ActivatedHabitatSpawning(this)
|
||||
|
||||
var numberOfPhases: Int = 1
|
||||
var phaseOrder = HabitatPhaseOrder.SIMPLE
|
||||
var currentPhase = 1
|
||||
|
||||
val numberOfPhases: Int
|
||||
get() = pool.getPhaseCount()
|
||||
|
||||
var levelRange: IntRange = 1..Cobblemon.config.maxPokemonLevel
|
||||
var modifiers: PokemonProperties = PokemonProperties()
|
||||
var pool: HabitatPool = HabitatPool.default()
|
||||
@@ -139,7 +141,6 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
val activatedSettings = habitatSettingsDTO.activatedSettings
|
||||
val naturalSettings = habitatSettingsDTO.naturalSettings
|
||||
val isActivated = habitatSettingsDTO.isActivatedSpawning
|
||||
this.numberOfPhases = habitatSettingsDTO.numberOfPhases
|
||||
this.phaseOrder = habitatSettingsDTO.phaseOrder
|
||||
this.levelRange = habitatSettingsDTO.levelRange
|
||||
this.modifiers = PokemonProperties.parse(habitatSettingsDTO.modifiers)
|
||||
@@ -169,7 +170,6 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
override fun saveAdditional(tag: CompoundTag, registryLookup: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registryLookup)
|
||||
tag.putString(DataKeys.HABITAT_MIMIC, mimicId.toString())
|
||||
tag.putInt(DataKeys.HABITAT_PHASE_COUNT, numberOfPhases)
|
||||
tag.putString(DataKeys.HABITAT_PHASE_ORDER, phaseOrder.toString())
|
||||
// Only save the level range when it's a non-trivial one
|
||||
if (levelRange.first != 1 || levelRange.last != Cobblemon.config.maxPokemonLevel) {
|
||||
@@ -201,7 +201,6 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
return // Client doesn't need to try loading the rest
|
||||
}
|
||||
|
||||
numberOfPhases = tag.getInt(DataKeys.HABITAT_PHASE_COUNT)
|
||||
phaseOrder = HabitatPhaseOrder.valueOf(tag.getString(DataKeys.HABITAT_PHASE_ORDER))
|
||||
levelRange = tag.getString(DataKeys.HABITAT_LEVEL_RANGE).takeIf { it.isNotBlank() }?.let(IntRangeAdapter::deserialize) ?: 1..Cobblemon.config.maxPokemonLevel
|
||||
modifiers = tag.getString(DataKeys.HABITAT_MODIFIERS).takeIf { it.isNotBlank() }?.let(PokemonProperties::parse) ?: PokemonProperties()
|
||||
|
||||
@@ -630,7 +630,8 @@ class FossilMultiblockStructure (
|
||||
result.putInt(DataKeys.ORGANIC_MATERIAL, organicMaterialInside)
|
||||
val fossilInv = ListTag()
|
||||
|
||||
fossilInventory.forEach { fossilInv.add(ItemStack.CODEC.encodeStart(NbtOps.INSTANCE, it).orThrow) }
|
||||
val ops = registryLookup.createSerializationContext(NbtOps.INSTANCE)
|
||||
fossilInventory.forEach { fossilInv.add(ItemStack.CODEC.encodeStart(ops, it).getOrThrow()) }
|
||||
result.put(DataKeys.FOSSIL_INVENTORY, fossilInv)
|
||||
result.putString(DataKeys.CONNECTOR_DIRECTION, tankConnectorDirection?.toString())
|
||||
|
||||
@@ -652,9 +653,9 @@ class FossilMultiblockStructure (
|
||||
|
||||
const val TICKS_PER_MINUTE = 1200
|
||||
const val MATERIAL_TO_START = 128
|
||||
const val TIME_TO_TAKE = 100
|
||||
const val TIME_PER_STAGE = 100 / 8
|
||||
const val PROTECTION_TIME = 100
|
||||
const val TIME_TO_TAKE = TICKS_PER_MINUTE * 12
|
||||
const val TIME_PER_STAGE = TIME_TO_TAKE / 8
|
||||
const val PROTECTION_TIME = TICKS_PER_MINUTE * 5
|
||||
|
||||
fun fromNbt(nbt: CompoundTag, registryLookup: HolderLookup.Provider, animAge: Int = -1, partialTicks: Float = 0f): FossilMultiblockStructure {
|
||||
val monitorPos = NbtUtils.readBlockPos(nbt, DataKeys.MONITOR_POS).get()
|
||||
@@ -669,7 +670,10 @@ class FossilMultiblockStructure (
|
||||
|
||||
val fossilInv = if (nbt.contains(DataKeys.FOSSIL_INVENTORY)) { (nbt.get(DataKeys.FOSSIL_INVENTORY) as ListTag) } else ListTag()
|
||||
val actualFossilList = mutableListOf<ItemStack>()
|
||||
fossilInv.forEach { ItemStack.parse(registryLookup, it).ifPresent(actualFossilList::add) }
|
||||
|
||||
val ops = registryLookup.createSerializationContext(NbtOps.INSTANCE)
|
||||
fossilInv.forEach { ItemStack.CODEC.parse(ops, it).result().ifPresent(actualFossilList::add) }
|
||||
|
||||
result.fossilInventory = actualFossilList
|
||||
result.tankConnectorDirection = Direction.byName(nbt.getString(DataKeys.CONNECTOR_DIRECTION))
|
||||
|
||||
|
||||
@@ -115,35 +115,19 @@ class HabitatEditGUI(
|
||||
addOptionWidget(mimicInput)
|
||||
y += spacing
|
||||
|
||||
labels.add(lang("ui.edit.habitat.phase_number") to (10 to y))
|
||||
y += 12
|
||||
val phasesInput = EditBox(font, 10, y, buttonWidth, 20, "Phases".text())
|
||||
phasesInput.value = habitatSettingsDTO.numberOfPhases.toString()
|
||||
phasesInput.setResponder { value ->
|
||||
val phases = value.toIntOrNull()
|
||||
val valid = phases != null && phases > 0
|
||||
if (valid) {
|
||||
habitatSettingsDTO.numberOfPhases = phases
|
||||
}
|
||||
phasesInput.setTextColor(if (valid) validTextColor else invalidTextColor)
|
||||
setFieldValidity("phases", valid, "ui.edit.habitat.validation.phases")
|
||||
// Phase setting only visible if there's more than one phase
|
||||
val phaseCount = habitatSettingsDTO.pool.toHabitatPool()?.getPhaseCount() ?: 1
|
||||
if (phaseCount > 1) {
|
||||
phaseOrderButton = addOptionWidget(
|
||||
Button.builder(getPhaseOrderText()) {
|
||||
val orders = HabitatPhaseOrder.entries
|
||||
val currentIndex = orders.indexOf(habitatSettingsDTO.phaseOrder)
|
||||
habitatSettingsDTO.phaseOrder = orders[(currentIndex + 1) % orders.size]
|
||||
refresh()
|
||||
}.bounds(10, y, buttonWidth, 20).build()
|
||||
)
|
||||
y += spacing
|
||||
}
|
||||
val initialPhases = phasesInput.value.toIntOrNull()
|
||||
val initialPhasesValid = initialPhases != null && initialPhases > 0
|
||||
phasesInput.setTextColor(if (initialPhasesValid) validTextColor else invalidTextColor)
|
||||
setFieldValidity("phases", initialPhasesValid, "ui.edit.habitat.validation.phases")
|
||||
addOptionWidget(phasesInput)
|
||||
y += spacing
|
||||
|
||||
phaseOrderButton = addOptionWidget(
|
||||
Button.builder(getPhaseOrderText()) {
|
||||
val orders = HabitatPhaseOrder.entries
|
||||
val currentIndex = orders.indexOf(habitatSettingsDTO.phaseOrder)
|
||||
habitatSettingsDTO.phaseOrder = orders[(currentIndex + 1) % orders.size]
|
||||
refresh()
|
||||
}.bounds(10, y, buttonWidth, 20).build()
|
||||
)
|
||||
y += spacing
|
||||
|
||||
labels.add(lang("ui.edit.habitat.level_range") to (10 to y))
|
||||
y += 12
|
||||
@@ -390,7 +374,10 @@ class HabitatEditGUI(
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
phaseOrderButton.message = getPhaseOrderText()
|
||||
val phaseCount = habitatSettingsDTO.pool.toHabitatPool()?.getPhaseCount() ?: 1
|
||||
if (phaseCount > 1 && ::phaseOrderButton.isInitialized) {
|
||||
phaseOrderButton.message = getPhaseOrderText()
|
||||
}
|
||||
spawnModeButton.message = getSpawnModeText()
|
||||
poolSelectorButton.message = getPoolText()
|
||||
viewPoolButton.message = getViewPoolText()
|
||||
@@ -439,6 +426,7 @@ class HabitatEditGUI(
|
||||
}
|
||||
habitatSettingsDTO.pool = newCustomPool
|
||||
}
|
||||
rebuildWidgets()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -451,6 +439,7 @@ class HabitatEditGUI(
|
||||
}
|
||||
|
||||
habitatSettingsDTO.pool = selectedPool
|
||||
rebuildWidgets()
|
||||
}
|
||||
|
||||
private fun validateLevelRangeInputs() {
|
||||
|
||||
@@ -45,7 +45,6 @@ class HabitatSpawnEditorGUI(
|
||||
private val actionButtonBottomMargin = 10
|
||||
private val validTextColor = 0xFFFFFF
|
||||
private val invalidTextColor = 0xFF5555
|
||||
private val moonPhaseRange = 0..7
|
||||
private lateinit var positionTypeButton: Button
|
||||
private lateinit var bucketButton: Button
|
||||
private lateinit var timeOfDayButton: Button
|
||||
@@ -185,7 +184,7 @@ class HabitatSpawnEditorGUI(
|
||||
phasesInput.setTextColor(validTextColor)
|
||||
setFieldValidity("phases_list", true, "ui.edit.habitat.validation.phases_list")
|
||||
} else {
|
||||
val parsed = parseMoonPhases(value)
|
||||
val parsed = parsePhases(value)
|
||||
val valid = parsed != null
|
||||
if (valid) {
|
||||
spawn.phases = parsed
|
||||
@@ -194,7 +193,7 @@ class HabitatSpawnEditorGUI(
|
||||
setFieldValidity("phases_list", valid, "ui.edit.habitat.validation.phases_list")
|
||||
}
|
||||
}
|
||||
val initialPhasesValid = phasesInput.value.isBlank() || parseMoonPhases(phasesInput.value) != null
|
||||
val initialPhasesValid = phasesInput.value.isBlank() || parsePhases(phasesInput.value) != null
|
||||
phasesInput.setTextColor(if (initialPhasesValid) validTextColor else invalidTextColor)
|
||||
setFieldValidity("phases_list", initialPhasesValid, "ui.edit.habitat.validation.phases_list")
|
||||
addOptionWidget(phasesInput)
|
||||
@@ -332,7 +331,7 @@ class HabitatSpawnEditorGUI(
|
||||
return runCatching { PokemonSpecies.getByName(lowered) }.getOrNull()
|
||||
}
|
||||
|
||||
private fun parseMoonPhases(raw: String): IntRanges? {
|
||||
private fun parsePhases(raw: String): IntRanges? {
|
||||
val ranges = mutableListOf<IntRange>()
|
||||
val tokens = raw.split(",").map(String::trim)
|
||||
if (tokens.isEmpty() || tokens.any { it.isEmpty() }) {
|
||||
@@ -344,13 +343,12 @@ class HabitatSpawnEditorGUI(
|
||||
val range = when (parts.size) {
|
||||
1 -> {
|
||||
val value = parts[0].toIntOrNull() ?: return null
|
||||
if (value !in moonPhaseRange) return null
|
||||
value..value
|
||||
}
|
||||
2 -> {
|
||||
val start = parts[0].toIntOrNull() ?: return null
|
||||
val end = parts[1].toIntOrNull() ?: return null
|
||||
if (start !in moonPhaseRange || end !in moonPhaseRange || start > end) {
|
||||
if (start > end) {
|
||||
return null
|
||||
}
|
||||
start..end
|
||||
|
||||
@@ -34,27 +34,28 @@ import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HEADER_BAR_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.ICONS_ARROW_PADDING_AROUND
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.ICONS_PADDING_AROUND
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_ABILITIES
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_DESCRIPTION
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_DROPS
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_EVOLUTION_TREE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_ICON_SIZE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_MOVES
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_SIZE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.TAB_STATS
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.*
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.EvolutionTreeWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.AbilitiesWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.DescriptionWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.DropsScrollingWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.EntriesScrollingWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.MovesLearnsetWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.PokemonInfoWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.SearchWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.SizeWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.StatsWidget
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.abilities.HiddenAbility
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.isInventoryKeyPressed
|
||||
@@ -91,10 +92,6 @@ class PokedexGUI private constructor(
|
||||
|
||||
private val categoryBarOverlay = cobblemonResource("textures/gui/pokedex/pokedex_screen_bar_category.png")
|
||||
|
||||
// TODO: separate into smaller components / widgets?
|
||||
private val backgroundOverlay = cobblemonResource("textures/gui/pokedex/pokedex_screen_info_overlay.png")
|
||||
private val expandedBackgroundOverlay = cobblemonResource("textures/gui/pokedex/pokedex_screen_info_overlay_expanded.png")
|
||||
|
||||
private val tabSelectArrow = cobblemonResource("textures/gui/pokedex/select_arrow.png")
|
||||
private val tabIcons = arrayOf(
|
||||
cobblemonResource("textures/gui/pokedex/tab_info.png"),
|
||||
@@ -102,8 +99,7 @@ class PokedexGUI private constructor(
|
||||
cobblemonResource("textures/gui/pokedex/tab_size.png"),
|
||||
cobblemonResource("textures/gui/pokedex/tab_stats.png"),
|
||||
cobblemonResource("textures/gui/pokedex/tab_drops.png"),
|
||||
cobblemonResource("textures/gui/pokedex/tab_moves.png"),
|
||||
cobblemonResource("textures/gui/pokedex/tab_evolution_tree.png"),
|
||||
cobblemonResource("textures/gui/pokedex/tab_moves.png")
|
||||
)
|
||||
|
||||
val arrowUpIcon = cobblemonResource("textures/gui/pokedex/arrow_up.png")
|
||||
@@ -116,8 +112,6 @@ class PokedexGUI private constructor(
|
||||
TAB_MOVES
|
||||
)
|
||||
|
||||
private val ICONS_PADDING_BETWEEN = (BASE_WIDTH / 2 - ICONS_PADDING_AROUND * 2) / tabIcons.size
|
||||
|
||||
/**
|
||||
* Attempts to open this screen for a client.
|
||||
*/
|
||||
@@ -136,7 +130,6 @@ class PokedexGUI private constructor(
|
||||
|
||||
var oldDragPosX = 0.0
|
||||
var canDragRender = false
|
||||
private var activeDragableElement: GuiEventListener? = null
|
||||
|
||||
private var filteredPokedex: Collection<PokedexDef> = mutableListOf()
|
||||
private var seenCount = "0000"
|
||||
@@ -160,29 +153,13 @@ class PokedexGUI private constructor(
|
||||
private lateinit var scrollScreen: EntriesScrollingWidget
|
||||
private lateinit var pokemonInfoWidget: PokemonInfoWidget
|
||||
private lateinit var searchWidget: SearchWidget
|
||||
private lateinit var pokemonNameWidget: PokemonNameWidget
|
||||
|
||||
private var selectedSearchByType: SearchByType = SearchByType.SPECIES
|
||||
private var selectedCategoryFilter: PokedexCategoryFilterType = PokedexCategoryFilterType.ALL
|
||||
private val tabButtons: MutableList<ScaledButton> = mutableListOf()
|
||||
|
||||
var seenShinyStates = setOf<String>()
|
||||
var shiny = false
|
||||
var maleRatio = -1F
|
||||
var gender = Gender.GENDERLESS
|
||||
var aspects = mutableSetOf<String>()
|
||||
|
||||
lateinit var tabInfoElement: GuiEventListener
|
||||
var tabInfoIndex = TAB_DESCRIPTION
|
||||
var evolutionTreeExpanded = false
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
if (::pokemonInfoWidget.isInitialized) {
|
||||
pokemonInfoWidget.active = !value
|
||||
pokemonInfoWidget.visible = !value
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderBlurredBackground(delta: Float) {}
|
||||
override fun renderMenuBackground(context: GuiGraphics) {}
|
||||
@@ -201,7 +178,7 @@ class PokedexGUI private constructor(
|
||||
|
||||
//Info Widget
|
||||
if (::pokemonInfoWidget.isInitialized) removeWidget(pokemonInfoWidget)
|
||||
pokemonInfoWidget = PokemonInfoWidget(this, x + 180, y + 28) { newForm -> updateSelectedForm(newForm) }
|
||||
pokemonInfoWidget = PokemonInfoWidget(x + 180, y + 28) { newForm -> updateSelectedForm(newForm) }
|
||||
addRenderableWidget(pokemonInfoWidget)
|
||||
|
||||
setUpTabs()
|
||||
@@ -213,10 +190,6 @@ class PokedexGUI private constructor(
|
||||
searchWidget = SearchWidget(x + 26, y + 28, 120, HEADER_BAR_HEIGHT, update = ::updateFilters)
|
||||
addRenderableWidget(searchWidget)
|
||||
|
||||
if (::pokemonNameWidget.isInitialized) removeWidget(pokemonNameWidget)
|
||||
pokemonNameWidget = PokemonNameWidget(this, x + 180, y + 28)
|
||||
addRenderableWidget(pokemonNameWidget)
|
||||
|
||||
if (::regionSelectWidgetUp.isInitialized) removeWidget(regionSelectWidgetUp)
|
||||
regionSelectWidgetUp = ScaledButton(
|
||||
buttonX = (x + 95).toFloat(),
|
||||
@@ -392,14 +365,6 @@ class PokedexGUI private constructor(
|
||||
shadow = true
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = if (evolutionTreeExpanded) expandedBackgroundOverlay else backgroundOverlay,
|
||||
x = pokemonInfoWidget.x, y = pokemonInfoWidget.y,
|
||||
width = HALF_OVERLAY_WIDTH,
|
||||
height = HALF_OVERLAY_HEIGHT
|
||||
)
|
||||
|
||||
// Category filter
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
@@ -435,7 +400,7 @@ class PokedexGUI private constructor(
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = tabSelectArrow,
|
||||
x = (x + BASE_WIDTH / 2 + ICONS_ARROW_PADDING_AROUND + tabInfoIndex * ICONS_PADDING_BETWEEN) / SCALE,
|
||||
x = (x + 191.5F + (22F * tabInfoIndex)) / SCALE,
|
||||
y = (y + 177) / SCALE,
|
||||
width = 12,
|
||||
height = 6,
|
||||
@@ -469,7 +434,6 @@ class PokedexGUI private constructor(
|
||||
val canDisplayEntry = true //selectedForm?.unlockForms
|
||||
|
||||
if (::pokemonInfoWidget.isInitialized
|
||||
&& pokemonInfoWidget.active
|
||||
&& !pokemonInfoWidget.suppressViewport
|
||||
&& pokemonInfoWidget.isWithinPortraitSpace(mouseX, mouseY)
|
||||
&& canDisplayEntry == true
|
||||
@@ -478,12 +442,6 @@ class PokedexGUI private constructor(
|
||||
isDragging = true
|
||||
oldDragPosX = mouseX
|
||||
playSound(CobblemonSounds.POKEDEX_CLICK_SHORT)
|
||||
activeDragableElement = pokemonInfoWidget
|
||||
} else if (tabInfoIndex == TAB_EVOLUTION_TREE &&
|
||||
::tabInfoElement.isInitialized &&
|
||||
(tabInfoElement as EvolutionTreeWidget).isHovered(mouseX, mouseY)
|
||||
) {
|
||||
activeDragableElement = tabInfoElement
|
||||
}
|
||||
return try {
|
||||
super.mouseClicked(mouseX, mouseY, button)
|
||||
@@ -495,18 +453,14 @@ class PokedexGUI private constructor(
|
||||
override fun mouseReleased(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
if (canDragRender) canDragRender = false
|
||||
if (isDragging) isDragging = false
|
||||
activeDragableElement = null
|
||||
return super.mouseReleased(pMouseX, pMouseY, pButton)
|
||||
}
|
||||
|
||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
|
||||
if (isDragging && canDragRender && activeDragableElement == pokemonInfoWidget) {
|
||||
if (isDragging && canDragRender) {
|
||||
val dragOffsetY = (oldDragPosX - mouseX).toFloat()
|
||||
pokemonInfoWidget.rotationY = (((pokemonInfoWidget.rotationY + dragOffsetY) % 360 + 360) % 360)
|
||||
} else if (activeDragableElement == tabInfoElement) {
|
||||
tabInfoElement.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
}
|
||||
|
||||
oldDragPosX = mouseX
|
||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
}
|
||||
@@ -597,8 +551,6 @@ class PokedexGUI private constructor(
|
||||
selectedForm = CobblemonClient.clientPokedexData.getEncounteredForms(newSelectedEntry).firstOrNull()
|
||||
|
||||
pokemonInfoWidget.setDexEntry(selectedEntry!!)
|
||||
pokemonNameWidget.update(selectedEntry!!)
|
||||
|
||||
displaytabInfoElement(tabInfoIndex)
|
||||
}
|
||||
|
||||
@@ -610,7 +562,7 @@ class PokedexGUI private constructor(
|
||||
|
||||
for (i in tabIcons.indices) {
|
||||
tabButtons.add(ScaledButton(
|
||||
x + BASE_WIDTH / 2 + ICONS_PADDING_AROUND + i * ICONS_PADDING_BETWEEN,
|
||||
x + 190.5F + (i * 22F),
|
||||
y + 181.5F,
|
||||
TAB_ICON_SIZE,
|
||||
TAB_ICON_SIZE,
|
||||
@@ -623,8 +575,6 @@ class PokedexGUI private constructor(
|
||||
}
|
||||
|
||||
fun displaytabInfoElement(tabIndex: Int, update: Boolean = true) {
|
||||
if (tabIndex != TAB_EVOLUTION_TREE) evolutionTreeExpanded = false
|
||||
|
||||
val showActiveTab = selectedEntry?.let { selectedForm in getSufficientlyKnownForms(it, tabIndex) } == true
|
||||
var statSubIndex = 0
|
||||
|
||||
@@ -676,9 +626,6 @@ class PokedexGUI private constructor(
|
||||
TAB_MOVES -> {
|
||||
tabInfoElement = MovesLearnsetWidget(x + 180, y + 28)
|
||||
}
|
||||
TAB_EVOLUTION_TREE -> {
|
||||
tabInfoElement = EvolutionTreeWidget(this, x, y)
|
||||
}
|
||||
}
|
||||
val element = tabInfoElement
|
||||
if (element is Renderable && element is NarratableEntry) {
|
||||
@@ -753,9 +700,6 @@ class PokedexGUI private constructor(
|
||||
selectedForm = fallbackForm
|
||||
) { next -> cycleSelectedForm(next) }
|
||||
}
|
||||
TAB_EVOLUTION_TREE -> {
|
||||
(tabInfoElement as EvolutionTreeWidget).setup(selectedEntry, selectedForm)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tabInfoIndex != TAB_DESCRIPTION) displaytabInfoElement(TAB_DESCRIPTION)
|
||||
|
||||
@@ -16,8 +16,6 @@ object PokedexGUIConstants {
|
||||
const val HEADER_BAR_HEIGHT = 11
|
||||
const val POKEMON_DESCRIPTION_HEIGHT = 42
|
||||
const val POKEMON_DESCRIPTION_PADDING = 9
|
||||
const val ICONS_PADDING_AROUND = 18.5f
|
||||
const val ICONS_ARROW_PADDING_AROUND = ICONS_PADDING_AROUND + 1
|
||||
|
||||
const val TAB_ICON_SIZE = 16
|
||||
|
||||
@@ -38,7 +36,6 @@ object PokedexGUIConstants {
|
||||
const val TAB_STATS = 3
|
||||
const val TAB_DROPS = 4
|
||||
const val TAB_MOVES = 5
|
||||
const val TAB_EVOLUTION_TREE = 6
|
||||
|
||||
// RowScrollingWidget
|
||||
const val SCROLL_BASE_HEIGHT = 141
|
||||
|
||||
@@ -20,95 +20,31 @@ import net.minecraft.network.chat.MutableComponent
|
||||
private val tooltipEdge = cobblemonResource("textures/gui/pokedex/tooltip_edge.png")
|
||||
private val tooltipBackground = cobblemonResource("textures/gui/pokedex/tooltip_background.png")
|
||||
|
||||
fun renderTooltip(
|
||||
context: GuiGraphics,
|
||||
text: MutableComponent,
|
||||
posX: Int,
|
||||
posY: Int,
|
||||
delta: Float,
|
||||
offsetY: Int = 0,
|
||||
) {
|
||||
renderTooltip(
|
||||
context,
|
||||
listOf(text),
|
||||
posX,
|
||||
posY,
|
||||
delta,
|
||||
offsetY,
|
||||
)
|
||||
}
|
||||
|
||||
fun renderTooltip(
|
||||
context: GuiGraphics,
|
||||
text: List<MutableComponent>,
|
||||
posX: Int,
|
||||
posY: Int,
|
||||
delta: Float,
|
||||
offsetY: Int = 0,
|
||||
) {
|
||||
fun renderTooltip(context: GuiGraphics, text: MutableComponent, posX: Int, posY: Int, delta: Float, offsetY: Int = 0) {
|
||||
val poseStack = context.pose()
|
||||
val textWidth = text.maxOf { Minecraft.getInstance().font.width(it.font(CobblemonResources.DEFAULT_LARGE)) }
|
||||
val tooltipPadding = 6
|
||||
val tooltipWidth = textWidth + tooltipPadding
|
||||
val textWidth = Minecraft.getInstance().font.width(text.font(CobblemonResources.DEFAULT_LARGE))
|
||||
val tooltipWidth = textWidth + 6
|
||||
val tooltipHeight = 11
|
||||
val tooltipTop = posY + offsetY
|
||||
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.0, 0.0, 1000.0)
|
||||
|
||||
Minecraft.getInstance().let {
|
||||
it.mainRenderTarget.bindWrite(false)
|
||||
context.enableScissor(
|
||||
posX - (tooltipWidth / 2),
|
||||
tooltipTop + 1,
|
||||
(posX - (tooltipWidth / 2)) + tooltipWidth,
|
||||
tooltipTop + tooltipHeight * text.size - 1
|
||||
tooltipTop + 10
|
||||
)
|
||||
it.gameRenderer.processBlurEffect(delta)
|
||||
context.disableScissor()
|
||||
it.mainRenderTarget.bindWrite(true)
|
||||
}
|
||||
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = tooltipEdge,
|
||||
x = posX - (tooltipWidth / 2) - 1,
|
||||
y = tooltipTop,
|
||||
width = 1,
|
||||
height = tooltipHeight * text.size
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = tooltipBackground,
|
||||
x = posX - (tooltipWidth / 2),
|
||||
y = tooltipTop,
|
||||
width = tooltipWidth,
|
||||
height = tooltipHeight * text.size
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = poseStack,
|
||||
texture = tooltipEdge,
|
||||
x = posX + (tooltipWidth / 2),
|
||||
y = tooltipTop,
|
||||
width = 1,
|
||||
height = tooltipHeight * text.size
|
||||
)
|
||||
|
||||
val centered = text.size == 1
|
||||
|
||||
text.forEachIndexed { index, it ->
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = it,
|
||||
x = if (centered) posX else posX - tooltipWidth / 2 + tooltipPadding / 2,
|
||||
y = tooltipTop + 1 + (tooltipHeight - 2) * index,
|
||||
shadow = true,
|
||||
centered = centered
|
||||
)
|
||||
}
|
||||
|
||||
blitk(matrixStack = poseStack, texture = tooltipEdge, x = posX - (tooltipWidth / 2) - 1, y = tooltipTop, width = 1, height = tooltipHeight)
|
||||
blitk(matrixStack = poseStack, texture = tooltipBackground, x = posX - (tooltipWidth / 2), y = tooltipTop, width = tooltipWidth, height = tooltipHeight)
|
||||
blitk(matrixStack = poseStack, texture = tooltipEdge, x = posX + (tooltipWidth / 2), y = tooltipTop, width = 1, height = tooltipHeight)
|
||||
drawScaledText(context = context, font = CobblemonResources.DEFAULT_LARGE, text = text, x = posX, y = tooltipTop + 1, shadow = true, centered = true)
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class ScaledButton(
|
||||
buttonX: Float,
|
||||
buttonY: Float,
|
||||
var buttonX: Float,
|
||||
var buttonY: Float,
|
||||
val buttonWidth: Number,
|
||||
val buttonHeight: Number,
|
||||
var resource: ResourceLocation? = null,
|
||||
@@ -30,18 +30,6 @@ class ScaledButton(
|
||||
val clickAction: Button.OnPress
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), "".text(), clickAction, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
var buttonX: Float = buttonX
|
||||
set(value) {
|
||||
field = value
|
||||
this.x = value.toInt()
|
||||
}
|
||||
|
||||
var buttonY: Float = buttonY
|
||||
set(value) {
|
||||
field = value
|
||||
this.y = value.toInt()
|
||||
}
|
||||
|
||||
var isWidgetActive = false
|
||||
var isVisible = true
|
||||
|
||||
|
||||
@@ -12,13 +12,14 @@ import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.ScrollingWidget
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCROLL_BAR_WIDTH
|
||||
@@ -26,14 +27,19 @@ import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCROLL_BA
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCROLL_SLOT_SIZE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCROLL_SLOT_SPACING
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.EntriesScrollingWidget.PokemonScrollSlotRow
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.util.Mth
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
|
||||
class EntriesScrollingWidget(val pX: Int, val pY: Int, val setPokedexEntry: (PokedexEntry) -> (Unit)): ScrollingWidget<PokemonScrollSlotRow>(
|
||||
width = PokedexGUIConstants.HALF_OVERLAY_WIDTH,
|
||||
@@ -129,6 +135,13 @@ class EntriesScrollingWidget(val pX: Int, val pY: Int, val setPokedexEntry: (Pok
|
||||
val discoveryLevelList: MutableList<PokedexEntryProgress>,
|
||||
val setPokedexEntry : (PokedexEntry) -> (Unit)
|
||||
): Slot<PokemonScrollSlotRow>() {
|
||||
companion object {
|
||||
private val slotResource = cobblemonResource("textures/gui/pokedex/pokedex_slot.png")
|
||||
private val slotHighlight = cobblemonResource("textures/gui/pokedex/slot_select.png")
|
||||
private val caughtIcon = cobblemonResource("textures/gui/pokedex/caught_icon_small.png")
|
||||
private val unknownIcon = cobblemonResource("textures/gui/pokedex/pokedex_slot_unknown.png")
|
||||
private val unimplementedIcon = cobblemonResource("textures/gui/pokedex/pokedex_slot_unimplemented.png")
|
||||
}
|
||||
val runtime = MoLangRuntime().setupClient().setup().also {
|
||||
it.environment.query.addFunction("get_pokedex") { CobblemonClient.clientPokedexData.struct }
|
||||
}
|
||||
@@ -148,42 +161,128 @@ class EntriesScrollingWidget(val pX: Int, val pY: Int, val setPokedexEntry: (Pok
|
||||
hovered: Boolean,
|
||||
tickDelta: Float
|
||||
) {
|
||||
dexDataList.forEachIndexed { index, pokedexEntry ->
|
||||
val species = PokemonSpecies.getByIdentifier(pokedexEntry.speciesId)
|
||||
dexDataList.forEachIndexed { index, dexData ->
|
||||
val state = FloatingState()
|
||||
val species = PokemonSpecies.getByIdentifier(dexData.speciesId)
|
||||
//FIXME: This may not work properly when accounting for custom pokemon with the same dex number
|
||||
val pokemonNumber = (species?.nationalPokedexNumber?.toString() ?: "0").padStart(4, '0')
|
||||
|
||||
val speciesNumber = pokemonNumber.text()
|
||||
val discoveryLevel = discoveryLevelList[index]
|
||||
val firstVisibleForm = CobblemonClient.clientPokedexData.getEncounteredForms(pokedexEntry).firstOrNull()
|
||||
val firstVisibleForm = CobblemonClient.clientPokedexData.getEncounteredForms(dexData).firstOrNull()
|
||||
val shouldDrawMon = firstVisibleForm != null
|
||||
|
||||
if (species == null) {
|
||||
return@forEachIndexed
|
||||
}
|
||||
|
||||
val renderablePokemon =
|
||||
if (firstVisibleForm != null) {
|
||||
val firstVisibleGender = CobblemonClient.clientPokedexData.getSeenGenders(pokedexEntry, firstVisibleForm).firstOrNull()
|
||||
val shinyStates = CobblemonClient.clientPokedexData.getSeenShinyStates(pokedexEntry, firstVisibleForm)
|
||||
val firstVisibleShiny = shinyStates.count() == 1 && shinyStates.first() == "shiny"
|
||||
val formAspects = species.forms.firstOrNull { it.name.equals(firstVisibleForm.displayForm, ignoreCase = true) }?.aspects ?: species.standardForm.aspects
|
||||
val seenAspects = CobblemonClient.clientPokedexData.getSeenAspects(pokedexEntry)
|
||||
val variationAspects = pokedexEntry.variations.mapNotNull { it.aspects.firstOrNull { it in seenAspects } }
|
||||
val aspectsToDraw = (pokedexEntry.displayAspects + variationAspects + formAspects + (firstVisibleGender ?: Gender.GENDERLESS).name.lowercase()).toMutableSet()
|
||||
if (firstVisibleShiny) {
|
||||
aspectsToDraw.add("shiny")
|
||||
}
|
||||
val matrices = context.pose()
|
||||
|
||||
RenderablePokemon(species, aspectsToDraw)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val startPosX = x + ((SCROLL_SLOT_SPACING + SCROLL_SLOT_SIZE) * index)
|
||||
val startPosY = y + SCROLL_SLOT_SPACING + 1
|
||||
|
||||
PokemonSlotWidget.render(
|
||||
context,
|
||||
x = x + (SCROLL_SLOT_SPACING + SCROLL_SLOT_SIZE) * index,
|
||||
y = y + SCROLL_SLOT_SPACING + 1,
|
||||
getHoveredSlotIndex(mouseX, mouseY) == index,
|
||||
species,
|
||||
renderablePokemon,
|
||||
discoveryLevel,
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = slotResource,
|
||||
x = startPosX,
|
||||
y = startPosY,
|
||||
width = SCROLL_SLOT_SIZE,
|
||||
height = SCROLL_SLOT_SIZE
|
||||
)
|
||||
|
||||
if (getHoveredSlotIndex(mouseX, mouseY) == index) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = slotHighlight,
|
||||
x = startPosX,
|
||||
y = startPosY,
|
||||
width = SCROLL_SLOT_SIZE,
|
||||
height = SCROLL_SLOT_SIZE,
|
||||
vOffset = SCROLL_SLOT_SIZE,
|
||||
textureHeight = SCROLL_SLOT_SIZE * 2
|
||||
)
|
||||
}
|
||||
|
||||
if (shouldDrawMon) {
|
||||
val firstVisibleGender = CobblemonClient.clientPokedexData.getSeenGenders(dexData, firstVisibleForm).firstOrNull()
|
||||
val shinyStates = CobblemonClient.clientPokedexData.getSeenShinyStates(dexData, firstVisibleForm)
|
||||
val firstVisibleShiny = shinyStates.count() == 1 && shinyStates.first() == "shiny"
|
||||
val formAspects = species.forms.firstOrNull { it.name.equals(firstVisibleForm.displayForm, ignoreCase = true) }?.aspects ?: species.standardForm.aspects
|
||||
val seenAspects = CobblemonClient.clientPokedexData.getSeenAspects(dexData)
|
||||
val variationAspects = dexData.variations.mapNotNull { it.aspects.firstOrNull { it in seenAspects } }
|
||||
context.enableScissor(
|
||||
startPosX + 1,
|
||||
startPosY + 1,
|
||||
startPosX + SCROLL_SLOT_SIZE - 1,
|
||||
startPosY + SCROLL_SLOT_SIZE - 2
|
||||
)
|
||||
val aspectsToDraw = (dexData.displayAspects + variationAspects + formAspects + (firstVisibleGender ?: Gender.GENDERLESS).name.lowercase()).toMutableSet()
|
||||
if (firstVisibleShiny) {
|
||||
aspectsToDraw.add("shiny")
|
||||
}
|
||||
state.currentAspects = aspectsToDraw
|
||||
matrices.pushPose()
|
||||
matrices.translate(startPosX + (SCROLL_SLOT_SIZE / 2.0), startPosY + 1.0, 0.0)
|
||||
matrices.scale(2.5F, 2.5F, 1F)
|
||||
drawProfilePokemon(
|
||||
renderablePokemon = RenderablePokemon(species, aspectsToDraw),
|
||||
matrixStack = matrices,
|
||||
rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(13F, 35F, 0F)),
|
||||
state = state,
|
||||
partialTicks = 0F,
|
||||
scale = 4.5F
|
||||
)
|
||||
matrices.popPose()
|
||||
context.disableScissor()
|
||||
} else {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = unknownIcon,
|
||||
x = startPosX + 8.5,
|
||||
y = startPosY + 9,
|
||||
width = 8,
|
||||
height = 10
|
||||
)
|
||||
|
||||
if (!species.implemented) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = unimplementedIcon,
|
||||
x = (startPosX + 14) / SCALE,
|
||||
y = (startPosY + 15.5) / SCALE,
|
||||
width = 7,
|
||||
height = 7,
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure elements are not hidden behind Pokémon render
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, 0.0, 100.0)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = speciesNumber,
|
||||
x = startPosX + 1.5,//2,
|
||||
y = startPosY + 2.5,//2
|
||||
shadow = true,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
if (discoveryLevel == PokedexEntryProgress.OWNED) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = caughtIcon,
|
||||
x = (startPosX + 18) / SCALE,
|
||||
y = (startPosY + 1.5) / SCALE,
|
||||
width = 11,
|
||||
height = 11,
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
|
||||
matrices.popPose()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ package com.cobblemon.mod.common.client.gui.pokedex.widgets
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexCosmeticVariation
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
@@ -24,9 +24,8 @@ import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUI
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_PORTRAIT_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_PORTRAIT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.PORTRAIT_POKE_BALL_HEIGHT
|
||||
@@ -52,13 +51,15 @@ import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import java.io.FileNotFoundException
|
||||
|
||||
class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val updateForm: (PokedexForm) -> (Unit)) : SoundlessWidget(
|
||||
class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm) -> (Unit)) : SoundlessWidget(
|
||||
pX,
|
||||
pY,
|
||||
POKEMON_PORTRAIT_WIDTH,
|
||||
@@ -80,6 +81,7 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
private val arrowFormLeft = cobblemonResource("textures/gui/pokedex/forms_arrow_left.png")
|
||||
private val arrowFormRight = cobblemonResource("textures/gui/pokedex/forms_arrow_right.png")
|
||||
|
||||
private val caughtIcon = cobblemonResource("textures/gui/pokedex/caught_icon.png")
|
||||
private val typeBar = cobblemonResource("textures/gui/pokedex/type_bar.png")
|
||||
private val typeBarDouble = cobblemonResource("textures/gui/pokedex/type_bar_double.png")
|
||||
|
||||
@@ -97,6 +99,9 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
|
||||
var currentEntry : PokedexEntry? = null
|
||||
|
||||
var speciesName: MutableComponent = Component.translatable("")
|
||||
var speciesNumber: MutableComponent = "0000".text()
|
||||
|
||||
val runtime = MoLangRuntime().setupClient().setup().also {
|
||||
it.environment.query.addFunction("get_pokedex") { CobblemonClient.clientPokedexData.struct }
|
||||
}
|
||||
@@ -105,6 +110,10 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
var selectedFormIndex: Int = 0
|
||||
|
||||
var type: Array<ElementalType?> = arrayOf(null, null)
|
||||
var seenShinyStates: Set<String> = setOf()
|
||||
var shiny = false
|
||||
var maleRatio = -1F
|
||||
var gender: Gender = Gender.GENDERLESS
|
||||
|
||||
var renderablePokemon : RenderablePokemon? = null
|
||||
|
||||
@@ -185,10 +194,7 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
20,
|
||||
resource = buttonGenderMale,
|
||||
clickAction = {
|
||||
val maleRatio = parent.maleRatio
|
||||
if (maleRatio > 0 && maleRatio < 1) {
|
||||
parent.gender = if (parent.gender == Gender.MALE) Gender.FEMALE else Gender.MALE
|
||||
}
|
||||
if (maleRatio > 0 && maleRatio < 1) gender = if (gender == Gender.MALE) Gender.FEMALE else Gender.MALE
|
||||
updateAspects()
|
||||
}
|
||||
).apply { addWidget(this) }
|
||||
@@ -200,8 +206,8 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
20,
|
||||
buttonNone,
|
||||
clickAction = {
|
||||
if (parent.seenShinyStates.size > 1) {
|
||||
parent.shiny = !parent.shiny
|
||||
if (seenShinyStates.size > 1) {
|
||||
shiny = !shiny
|
||||
updateAspects()
|
||||
}
|
||||
}
|
||||
@@ -256,7 +262,8 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val currentEntry = this.currentEntry ?: return
|
||||
|
||||
val hasKnowledge = CobblemonClient.clientPokedexData.getKnowledgeForSpecies(currentEntry.speciesId) != PokedexEntryProgress.UNREGISTERED
|
||||
val hasKnowledge =
|
||||
CobblemonClient.clientPokedexData.getKnowledgeForSpecies(currentEntry.speciesId) != PokedexEntryProgress.UNREGISTERED
|
||||
val species = currentEntry.speciesId.let { PokemonSpecies.getByIdentifier(it) } ?: return
|
||||
|
||||
val matrices = context.pose()
|
||||
@@ -269,6 +276,37 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
height = HALF_OVERLAY_HEIGHT
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = speciesNumber.bold(),
|
||||
x = pX + 3,
|
||||
y = pY + 1,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = (if (hasKnowledge) speciesName else lang("ui.generic.question_marks")).bold(),
|
||||
x = pX + 26,
|
||||
y = pY + 1,
|
||||
colour = 0x606B6E
|
||||
)
|
||||
|
||||
// Caught icon
|
||||
if (isSelectedPokemonOwned()) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = caughtIcon,
|
||||
x = (pX + 129) / SCALE,
|
||||
y = (pY + 2) / SCALE,
|
||||
width = 14,
|
||||
height = 14,
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
|
||||
if (!suppressViewport) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
@@ -531,6 +569,8 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
|
||||
if (species != null) {
|
||||
this.visibleForms = CobblemonClient.clientPokedexData.getEncounteredForms(pokedexEntry).toMutableList()
|
||||
this.speciesNumber = species.nationalPokedexNumber.toString().padStart(4, '0').text()
|
||||
this.speciesName = species.translatedName
|
||||
|
||||
if (forms.isNotEmpty()) {
|
||||
formLeftButton.active = true
|
||||
@@ -556,23 +596,23 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
variationButtons.forEach { removeWidget(it.getWidget()) }
|
||||
variationButtons.clear()
|
||||
|
||||
parent.seenShinyStates = CobblemonClient.clientPokedexData.getSeenShinyStates(pokedexEntry, pokedexForm)
|
||||
parent.shiny = parent.seenShinyStates.count() == 1 && parent.seenShinyStates.first() == "shiny"
|
||||
shinyButton.resource = if (parent.shiny) buttonShiny else buttonNone
|
||||
shinyButton.visible = parent.shiny || parent.seenShinyStates.size > 1
|
||||
shinyButton.active = parent.seenShinyStates.size > 1
|
||||
seenShinyStates = CobblemonClient.clientPokedexData.getSeenShinyStates(pokedexEntry, pokedexForm)
|
||||
shiny = seenShinyStates.count() == 1 && seenShinyStates.first() == "shiny"
|
||||
shinyButton.resource = if (shiny) buttonShiny else buttonNone
|
||||
shinyButton.visible = shiny || seenShinyStates.size > 1
|
||||
shinyButton.active = seenShinyStates.size > 1
|
||||
|
||||
val form = species.forms.find { it.name.equals(pokedexForm.displayForm, ignoreCase = true) } ?: species.standardForm
|
||||
parent.maleRatio = form.maleRatio
|
||||
maleRatio = form.maleRatio
|
||||
|
||||
val seenGenders = CobblemonClient.clientPokedexData.getSeenGenders(pokedexEntry, pokedexForm)
|
||||
val visibleGenders = seenGenders.filter { it != Gender.GENDERLESS }
|
||||
if (visibleGenders.isEmpty()) {
|
||||
parent.gender = Gender.GENDERLESS
|
||||
gender = Gender.GENDERLESS
|
||||
genderButton.visible = false
|
||||
genderButton.active = false
|
||||
} else {
|
||||
parent.gender = visibleGenders.first()
|
||||
gender = visibleGenders.first()
|
||||
genderButton.visible = true
|
||||
genderButton.active = visibleGenders.size > 1
|
||||
}
|
||||
@@ -651,8 +691,8 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
return
|
||||
}
|
||||
|
||||
genderButton.resource = if (parent.gender == Gender.FEMALE) buttonGenderFemale else buttonGenderMale
|
||||
shinyButton.resource = if (parent.shiny) buttonShiny else buttonNone
|
||||
genderButton.resource = if (gender == Gender.FEMALE) buttonGenderFemale else buttonGenderMale
|
||||
shinyButton.resource = if (shiny) buttonShiny else buttonNone
|
||||
|
||||
val species = currentEntry?.speciesId?.let { PokemonSpecies.getByIdentifier(it) }
|
||||
if (species != null) {
|
||||
@@ -661,14 +701,12 @@ class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val up
|
||||
|
||||
updateType(species, form)
|
||||
|
||||
val aspects = parent.aspects
|
||||
aspects.clear()
|
||||
val aspects = mutableSetOf<String>()
|
||||
if (shiny) aspects.add(SHINY_ASPECT.aspect)
|
||||
|
||||
if (parent.shiny) aspects.add(SHINY_ASPECT.aspect)
|
||||
|
||||
if (parent.gender == Gender.FEMALE) {
|
||||
if (gender == Gender.FEMALE) {
|
||||
aspects.add("female")
|
||||
} else if (parent.gender == Gender.MALE) {
|
||||
} else if (gender == Gender.MALE) {
|
||||
aspects.add("male")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUI
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_PORTRAIT_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_PORTRAIT_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
class PokemonNameWidget(
|
||||
val parent: PokedexGUI,
|
||||
val pX: Int,
|
||||
val pY: Int,
|
||||
) : SoundlessWidget(
|
||||
pX,
|
||||
pY,
|
||||
POKEMON_PORTRAIT_WIDTH,
|
||||
POKEMON_PORTRAIT_HEIGHT,
|
||||
lang("ui.pokedex.pokemon_name"),
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private val caughtIcon = cobblemonResource("textures/gui/pokedex/caught_icon.png")
|
||||
}
|
||||
|
||||
var hasKnowledge: Boolean = false
|
||||
var isOwned: Boolean = false
|
||||
var speciesName: MutableComponent = Component.translatable("")
|
||||
var speciesNumber: MutableComponent = "0000".text()
|
||||
|
||||
override fun renderWidget(
|
||||
context: GuiGraphics,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
partialTick: Float
|
||||
) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = speciesNumber.bold(),
|
||||
x = pX + 3,
|
||||
y = pY + 1,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
if (hasKnowledge) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = speciesName.bold(),
|
||||
x = pX + 26,
|
||||
y = pY + 1,
|
||||
colour = 0x606B6E
|
||||
)
|
||||
}
|
||||
|
||||
if (isOwned) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = caughtIcon,
|
||||
x = (pX + 129) / SCALE,
|
||||
y = (pY + 2) / SCALE,
|
||||
width = 14,
|
||||
height = 14,
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun update(pokedexEntry: PokedexEntry) {
|
||||
val species = PokemonSpecies.getByIdentifier(pokedexEntry.speciesId) ?: return
|
||||
|
||||
val progress = CobblemonClient.clientPokedexData.getKnowledgeForSpecies(pokedexEntry.speciesId)
|
||||
this.hasKnowledge = progress != PokedexEntryProgress.UNREGISTERED
|
||||
this.isOwned = progress == PokedexEntryProgress.OWNED
|
||||
this.speciesNumber = species.nationalPokedexNumber.toString().padStart(4, '0').text()
|
||||
this.speciesName = species.translatedName
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCROLL_SLOT_SIZE
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
|
||||
abstract class PokemonSlotWidget {
|
||||
companion object {
|
||||
private val slotResource = cobblemonResource("textures/gui/pokedex/pokedex_slot.png")
|
||||
private val slotHighlight = cobblemonResource("textures/gui/pokedex/slot_select.png")
|
||||
private val caughtIcon = cobblemonResource("textures/gui/pokedex/caught_icon_small.png")
|
||||
private val unknownIcon = cobblemonResource("textures/gui/pokedex/pokedex_slot_unknown.png")
|
||||
private val unimplementedIcon = cobblemonResource("textures/gui/pokedex/pokedex_slot_unimplemented.png")
|
||||
|
||||
fun render(
|
||||
context: GuiGraphics,
|
||||
x: Int,
|
||||
y: Int,
|
||||
isHovered: Boolean,
|
||||
species: Species,
|
||||
renderablePokemon: RenderablePokemon?,
|
||||
discoveryLevel: PokedexEntryProgress,
|
||||
) {
|
||||
val shouldDrawMon = renderablePokemon != null
|
||||
|
||||
// FIXME: This may not work properly when accounting for custom pokemon with the same dex number
|
||||
val pokemonNumber = species.nationalPokedexNumber.toString().padStart(4, '0')
|
||||
val speciesNumber = pokemonNumber.text()
|
||||
|
||||
val matrices = context.pose()
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = slotResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = SCROLL_SLOT_SIZE,
|
||||
height = SCROLL_SLOT_SIZE,
|
||||
)
|
||||
|
||||
if (isHovered) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = slotHighlight,
|
||||
x = x,
|
||||
y = y,
|
||||
width = SCROLL_SLOT_SIZE,
|
||||
height = SCROLL_SLOT_SIZE,
|
||||
vOffset = SCROLL_SLOT_SIZE,
|
||||
textureHeight = SCROLL_SLOT_SIZE * 2,
|
||||
)
|
||||
}
|
||||
|
||||
if (shouldDrawMon && discoveryLevel != PokedexEntryProgress.UNREGISTERED) {
|
||||
context.enableScissor(
|
||||
x + 1,
|
||||
y + 1,
|
||||
x + SCROLL_SLOT_SIZE - 1,
|
||||
y + SCROLL_SLOT_SIZE - 2,
|
||||
)
|
||||
|
||||
matrices.pushPose()
|
||||
matrices.translate(x + SCROLL_SLOT_SIZE / 2.0, y + 1.0, 0.0)
|
||||
matrices.scale(2.5F, 2.5F, 1F)
|
||||
|
||||
val state = FloatingState()
|
||||
state.currentAspects = renderablePokemon.aspects
|
||||
|
||||
drawProfilePokemon(
|
||||
renderablePokemon = renderablePokemon,
|
||||
matrixStack = matrices,
|
||||
rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(13F, 35F, 0F)),
|
||||
state = state,
|
||||
partialTicks = 0F,
|
||||
scale = 4.5F
|
||||
)
|
||||
|
||||
matrices.popPose()
|
||||
context.disableScissor()
|
||||
} else {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = unknownIcon,
|
||||
x = x + 8.5,
|
||||
y = y + 9,
|
||||
width = 8,
|
||||
height = 10
|
||||
)
|
||||
|
||||
if (!species.implemented) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = unimplementedIcon,
|
||||
x = (x + 14) / SCALE,
|
||||
y = (y + 15.5) / SCALE,
|
||||
width = 7,
|
||||
height = 7,
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure elements are not hidden behind Pokémon render
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, 0.0, 100.0)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = speciesNumber,
|
||||
x = x + 1.5,
|
||||
y = y + 2.5,
|
||||
shadow = true,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
if (discoveryLevel == PokedexEntryProgress.OWNED) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = caughtIcon,
|
||||
x = (x + 18) / SCALE,
|
||||
y = (y + 1.5) / SCALE,
|
||||
width = 11,
|
||||
height = 11,
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
|
||||
matrices.popPose()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.EvolutionVisitor
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.EvolutionTreeEvolutionVisitor.RenderEvolutionData
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.EvolutionTreeRequirementVisitor.RenderRequirementData
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.LevelUpEvolution
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.TradeEvolution
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class EvolutionTreeEvolutionVisitor : EvolutionVisitor<RenderEvolutionData?> {
|
||||
|
||||
data class RenderEvolutionData(
|
||||
val label: MutableComponent,
|
||||
val icons: List<Item>,
|
||||
val tooltips: List<MutableComponent>,
|
||||
)
|
||||
|
||||
private val requirementVisitor = EvolutionTreeRequirementVisitor()
|
||||
|
||||
private fun visitRequirement(requirement: Requirement): RenderRequirementData? {
|
||||
val icon = requirement.pokedexIcon?.let {
|
||||
Minecraft.getInstance()?.player?.level()?.itemRegistry?.get(it)
|
||||
}
|
||||
|
||||
val tooltip = requirement.pokedexTooltip?.let {
|
||||
Component.translatable(it)
|
||||
}
|
||||
|
||||
if (icon != null && tooltip != null) {
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
return requirementVisitor.visit(requirement)
|
||||
}
|
||||
|
||||
override fun visitBlockClickEvolution(blockClickEvolution: BlockClickEvolution): RenderEvolutionData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitDummyEvolution(evolution: Evolution): RenderEvolutionData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitItemInteractionEvolution(itemInteractionEvolution: ItemInteractionEvolution): RenderEvolutionData? {
|
||||
val label = lang("ui.pokedex.evolution.item_interact.label").bold()
|
||||
val item = itemInteractionEvolution.requiredContext.items.get().first().value()
|
||||
val icons = mutableListOf(item)
|
||||
val tooltips =
|
||||
mutableListOf(lang("ui.pokedex.evolution.item_interact.tooltip", item.description.plainCopy().green()))
|
||||
|
||||
val requirementsDataList = itemInteractionEvolution.requirements.mapNotNull { requirement ->
|
||||
visitRequirement(requirement)
|
||||
}
|
||||
|
||||
requirementsDataList.forEach { requirement ->
|
||||
icons.add(requirement.icon)
|
||||
tooltips.add(requirement.tooltip)
|
||||
}
|
||||
|
||||
return RenderEvolutionData(label, icons, tooltips)
|
||||
}
|
||||
|
||||
override fun visitLevelUpEvolution(levelUpEvolution: LevelUpEvolution): RenderEvolutionData? {
|
||||
val requirementsDataList = levelUpEvolution.requirements.map { requirement ->
|
||||
visitRequirement(requirement)
|
||||
}
|
||||
|
||||
val label = requirementsDataList.firstNotNullOfOrNull { requirement -> requirement?.label }
|
||||
val icons = requirementsDataList.mapNotNull { requirementData -> requirementData?.icon }
|
||||
val tooltips = requirementsDataList.mapNotNull { requirementData -> requirementData?.tooltip }
|
||||
|
||||
return RenderEvolutionData(label ?: Component.literal(""), icons, tooltips)
|
||||
}
|
||||
|
||||
override fun visitTradeEvolution(tradeEvolution: TradeEvolution): RenderEvolutionData? {
|
||||
val label = lang("ui.pokedex.evolution.trade.label")
|
||||
val icons = mutableListOf<Item>(CobblemonItems.LINK_CABLE)
|
||||
val tooltips = mutableListOf<MutableComponent>()
|
||||
|
||||
val species = tradeEvolution.requiredContext.species
|
||||
if (species == null) {
|
||||
tooltips.add(lang("ui.pokedex.evolution.trade.tooltip.with_any_species"))
|
||||
} else {
|
||||
PokemonSpecies.getByIdentifier(cobblemonResource(species))?.let {
|
||||
tooltips.add(lang("ui.pokedex.evolution.trade.tooltip.with_species", it.translatedName.green()))
|
||||
}
|
||||
}
|
||||
|
||||
val requirementsDataList = tradeEvolution.requirements.mapNotNull { requirement ->
|
||||
visitRequirement(requirement)
|
||||
}
|
||||
|
||||
requirementsDataList.forEach { requirement ->
|
||||
icons.add(requirement.icon)
|
||||
tooltips.add(requirement.tooltip)
|
||||
}
|
||||
|
||||
return RenderEvolutionData(label, icons, tooltips)
|
||||
}
|
||||
}
|
||||
@@ -1,271 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.EvolutionTreeRequirementVisitor.RenderRequirementData
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.RequirementVisitor
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.text.add
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.pokemon.requirements.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.Items
|
||||
|
||||
class EvolutionTreeRequirementVisitor : RequirementVisitor<RenderRequirementData?> {
|
||||
data class RenderRequirementData(
|
||||
val icon: Item,
|
||||
val tooltip: MutableComponent,
|
||||
val label: MutableComponent? = null,
|
||||
)
|
||||
|
||||
override fun visitAdvancementRequirement(advancementRequirement: AdvancementRequirement): RenderRequirementData? {
|
||||
val icon = Items.BOOK
|
||||
val advancementLanguageKey = advancementRequirement.requiredAdvancement.toLanguageKey()
|
||||
val advancementComponent = Component.translatable("advancements.$advancementLanguageKey").green()
|
||||
val tooltip = lang("ui.pokedex.requirement.advancement.tooltip", advancementComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitAnyRequirement(anyRequirement: AnyRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitAreaRequirement(areaRequirement: AreaRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitAttackDefenceRatioRequirement(attackDefenceRatioRequirement: AttackDefenceRatioRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitBattleCriticalHitsRequirement(battleCriticalHitsRequirement: BattleCriticalHitsRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.MEDICINAL_LEEK
|
||||
val criticalsComponent = Component.literal(battleCriticalHitsRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.battle_critical_hits.tooltip", criticalsComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitBiomeRequirement(biomeRequirement: BiomeRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitBlocksTraveledRequirement(blocksTraveledRequirement: BlocksTraveledRequirement): RenderRequirementData? {
|
||||
val icon = Items.LEATHER_BOOTS
|
||||
val blocksComponent = Component.literal(blocksTraveledRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.blocks_traveled.tooltip", blocksComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitDamageTakenRequirement(damageTakenRequirement: DamageTakenRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.PUNCHING_GLOVE
|
||||
val blocksComponent = Component.literal(damageTakenRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.damage_taken.tooltip", blocksComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitDefeatRequirement(defeatRequirement: DefeatRequirement): RenderRequirementData? {
|
||||
val species = defeatRequirement.target.species?.let { PokemonSpecies.getByIdentifier(cobblemonResource(it)) } ?: return null
|
||||
val icon = CobblemonItems.PUNCHING_GLOVE
|
||||
val defeatedAmount = defeatRequirement.amount
|
||||
|
||||
val descriptionComponent = Component.literal(defeatedAmount.toString()).plainCopy().add(" ").add(species.translatedName).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.defeat.tooltip", descriptionComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitFriendshipRequirement(friendshipRequirement: FriendshipRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.SOOTHE_BELL
|
||||
val friendshipAmountComponent = Component.literal(friendshipRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.friendship.tooltip", friendshipAmountComponent)
|
||||
val label = lang("ui.pokedex.requirement.friendship.label")
|
||||
|
||||
return RenderRequirementData(icon, tooltip, label)
|
||||
}
|
||||
|
||||
override fun visitHeldItemRequirement(heldItemRequirement: HeldItemRequirement): RenderRequirementData? {
|
||||
val item = heldItemRequirement.itemCondition.items.get().first().value()
|
||||
val tooltip = lang("ui.pokedex.requirement.held_item.tooltip", item.description.plainCopy().green())
|
||||
|
||||
return RenderRequirementData(item, tooltip)
|
||||
}
|
||||
|
||||
override fun visitLevelRequirement(levelRequirement: LevelRequirement): RenderRequirementData? {
|
||||
val minLevel = levelRequirement.minLevel
|
||||
val maxLevel = levelRequirement.maxLevel
|
||||
|
||||
val icon = CobblemonItems.RARE_CANDY
|
||||
val tooltip =
|
||||
if (minLevel == maxLevel || maxLevel == Int.MAX_VALUE)
|
||||
lang("ui.pokedex.requirement.level.tooltip.min", Component.literal(minLevel.toString()).green())
|
||||
else
|
||||
lang("ui.pokedex.requirement.level.tooltip.between", Component.literal(minLevel.toString()).green(), Component.literal(maxLevel.toString()).green())
|
||||
|
||||
val label = lang("ui.pokedex.requirement.level.label", minLevel)
|
||||
|
||||
return RenderRequirementData(icon, tooltip, label)
|
||||
}
|
||||
|
||||
override fun visitMoonPhaseRequirement(moonPhaseRequirement: MoonPhaseRequirement): RenderRequirementData? {
|
||||
val icon = Items.CLOCK
|
||||
val moonPhaseComponent = moonPhaseRequirement.moonPhase.displayName().green()
|
||||
val tooltip = lang("ui.pokedex.requirement.moon_phase.tooltip", moonPhaseComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitMoveSetRequirement(moveSetRequirement: MoveSetRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.PP_MAX
|
||||
val tooltip = lang("ui.pokedex.requirement.has_move.tooltip", moveSetRequirement.move.displayName.green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitMoveTypeRequirement(moveTypeRequirement: MoveTypeRequirement): RenderRequirementData? {
|
||||
val type = ElementalTypes.get(moveTypeRequirement.type.name)
|
||||
val icon = when (type) {
|
||||
ElementalTypes.NORMAL -> CobblemonItems.NORMAL_GEM
|
||||
ElementalTypes.FIRE -> CobblemonItems.FIRE_GEM
|
||||
ElementalTypes.WATER -> CobblemonItems.WATER_GEM
|
||||
ElementalTypes.GRASS -> CobblemonItems.GRASS_GEM
|
||||
ElementalTypes.ELECTRIC -> CobblemonItems.ELECTRIC_GEM
|
||||
ElementalTypes.ICE -> CobblemonItems.ICE_GEM
|
||||
ElementalTypes.FIGHTING -> CobblemonItems.FIGHTING_GEM
|
||||
ElementalTypes.POISON -> CobblemonItems.POISON_GEM
|
||||
ElementalTypes.GROUND -> CobblemonItems.GROUND_GEM
|
||||
ElementalTypes.FLYING -> CobblemonItems.FLYING_GEM
|
||||
ElementalTypes.PSYCHIC -> CobblemonItems.PSYCHIC_GEM
|
||||
ElementalTypes.BUG -> CobblemonItems.BUG_GEM
|
||||
ElementalTypes.ROCK -> CobblemonItems.ROCK_GEM
|
||||
ElementalTypes.GHOST -> CobblemonItems.GHOST_GEM
|
||||
ElementalTypes.DRAGON -> CobblemonItems.DRAGON_GEM
|
||||
ElementalTypes.DARK -> CobblemonItems.DARK_GEM
|
||||
ElementalTypes.STEEL -> CobblemonItems.STEEL_GEM
|
||||
ElementalTypes.FAIRY -> CobblemonItems.FAIRY_GEM
|
||||
else -> CobblemonItems.NORMAL_GEM
|
||||
}
|
||||
|
||||
val tooltip = lang("ui.pokedex.requirement.has_move_type.tooltip", moveTypeRequirement.type.displayName.green())
|
||||
val label = lang("ui.pokedex.requirement.has_move_type.label")
|
||||
|
||||
return RenderRequirementData(icon, tooltip, label)
|
||||
}
|
||||
|
||||
// TODO test
|
||||
override fun visitOwnerHoldsItemRequirement(ownerHoldsItemRequirement: OwnerHoldsItemRequirement): RenderRequirementData? {
|
||||
val item = ownerHoldsItemRequirement.itemCondition.items.get().first().value()
|
||||
val tooltip = lang("ui.pokedex.requirement.owner_held_item.tooltip", item.description.plainCopy().green())
|
||||
|
||||
return RenderRequirementData(item, tooltip)
|
||||
}
|
||||
|
||||
override fun visitPartyMemberRequirement(partyMemberRequirement: PartyMemberRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitPokemonPropertiesRequirement(pokemonPropertiesRequirement: PokemonPropertiesRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitPropertyRangeRequirement(propertyRangeRequirement: PropertyRangeRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitRecoilRequirement(recoilRequirement: RecoilRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.LIFE_ORB
|
||||
val recoilComponent = Component.literal(recoilRequirement.amount.toString()).green()
|
||||
val tooltip = lang("ui.pokedex.requirement.recoil.tooltip", recoilComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitStatCompareRequirement(statCompareRequirement: StatCompareRequirement): RenderRequirementData? {
|
||||
val highStat = Stats.getStat(statCompareRequirement.highStat)
|
||||
val lowStat = Stats.getStat(statCompareRequirement.lowStat)
|
||||
|
||||
val icon = when (highStat) {
|
||||
Stats.HP, Stats.EVASION, Stats.ACCURACY -> CobblemonItems.HEALTH_MOCHI
|
||||
Stats.ATTACK -> CobblemonItems.MUSCLE_MOCHI
|
||||
Stats.DEFENCE -> CobblemonItems.RESIST_MOCHI
|
||||
Stats.SPECIAL_ATTACK -> CobblemonItems.GENIUS_MOCHI
|
||||
Stats.SPECIAL_DEFENCE -> CobblemonItems.CLEVER_MOCHI
|
||||
Stats.SPEED -> CobblemonItems.SWIFT_MOCHI
|
||||
}
|
||||
|
||||
val highStatComponent = highStat.displayName.plainCopy().green()
|
||||
val lowStatComponent = lowStat.displayName.plainCopy().green()
|
||||
val tooltip = lang("ui.pokedex.requirement.stat_compare.tooltip", highStatComponent, lowStatComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitStatEqualRequirement(statEqualRequirement: StatEqualRequirement): RenderRequirementData? {
|
||||
val statOne = Stats.getStat(statEqualRequirement.statOne)
|
||||
val statTwo = Stats.getStat(statEqualRequirement.statTwo)
|
||||
|
||||
val statOneComponent = statOne.displayName.plainCopy().green()
|
||||
val statTwoComponent = statTwo.displayName.plainCopy().green()
|
||||
|
||||
val icon = CobblemonItems.FRESH_START_MOCHI
|
||||
val tooltip = lang("ui.pokedex.requirement.stat_equal.tooltip", statOneComponent, statTwoComponent)
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitStructureRequirement(structureRequirement: StructureRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitTimeRangeRequirement(timeRangeRequirement: TimeRangeRequirement): RenderRequirementData? {
|
||||
val icon = Items.CLOCK
|
||||
val timeRangeComponent = timeRangeRequirement.range.displayName() ?: return null
|
||||
val tooltip = lang("ui.pokedex.requirement.time_range.tooltip", timeRangeComponent.green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitUseMoveRequirement(useMoveRequirement: UseMoveRequirement): RenderRequirementData? {
|
||||
val icon = CobblemonItems.CHOICE_BAND
|
||||
val tooltip = lang("ui.pokedex.requirement.use_move.tooltip", useMoveRequirement.move.displayName.green())
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun visitWeatherRequirement(weatherRequirement: WeatherRequirement): RenderRequirementData? {
|
||||
var icon: Item
|
||||
var tooltip: MutableComponent
|
||||
|
||||
if (weatherRequirement.isThundering == true) {
|
||||
icon = Items.LIGHTNING_ROD
|
||||
tooltip = lang("ui.pokedex.requirement.weather.tooltip.thundering")
|
||||
} else {
|
||||
icon = Items.WATER_BUCKET
|
||||
tooltip = lang("ui.pokedex.requirement.weather.tooltip.raining")
|
||||
}
|
||||
|
||||
return RenderRequirementData(icon, tooltip)
|
||||
}
|
||||
|
||||
override fun visitWorldRequirement(worldRequirement: WorldRequirement): RenderRequirementData? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,552 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.gui.*
|
||||
import com.cobblemon.mod.common.api.pokedex.Dexes
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.text.add
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUI
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_DESCRIPTION_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCROLL_SLOT_SIZE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.ScaledButton
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.renderTooltip
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.PokemonSlotWidget
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.EvolutionTreeEvolutionVisitor.RenderEvolutionData
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.RenderablePokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
class EvolutionTreeWidget(
|
||||
val parent: PokedexGUI,
|
||||
val pX: Int,
|
||||
val pY: Int,
|
||||
) : SoundlessWidget(
|
||||
pX, pY,
|
||||
HALF_OVERLAY_WIDTH,
|
||||
POKEMON_DESCRIPTION_HEIGHT,
|
||||
lang("ui.pokedex.pokemon_info")
|
||||
) {
|
||||
companion object {
|
||||
private val slotResource = cobblemonResource("textures/gui/pokedex/pokedex_slot.png")
|
||||
private val expandResource = cobblemonResource("textures/gui/pokedex/expand.png")
|
||||
private val minimizeResource = cobblemonResource("textures/gui/pokedex/minimize.png")
|
||||
|
||||
const val X_MARGIN = 180
|
||||
const val Y_MARGIN_MINIMIZED = 135
|
||||
const val Y_MARGIN_EXPANDED = 53
|
||||
const val EXPANDED_HEIGHT = 125
|
||||
|
||||
const val HORIZONTAL_PADDING = 38
|
||||
const val VERTICAL_PADDING = 2
|
||||
const val TREE_FORK_LENGTH = 4
|
||||
|
||||
const val ICON_X_PADDING = -4.0
|
||||
const val ICON_Y_PADDING = -4.0
|
||||
const val MILLIS_BETWEEN_ICONS_CYCLE = 1000
|
||||
|
||||
const val ICON_SLOT_BACKGROUND_SIZE = 8
|
||||
const val ICON_SLOT_PADDING = 4
|
||||
const val ICON_SLOT_HALF_PADDING = ICON_SLOT_PADDING / 2
|
||||
|
||||
const val LINE_COLOR = 0xff1d6b85.toInt()
|
||||
|
||||
const val EXPAND_BUTTON_X_MARGIN = 127f
|
||||
const val EXPAND_BUTTON_Y_MARGIN = -10.5f
|
||||
const val EXPAND_BUTTON_SIZE = 20
|
||||
|
||||
private var previousRootPokedexEntry: PokedexEntry? = null
|
||||
private var previousRootPokedexForm: PokedexForm? = null
|
||||
|
||||
private val evolutionVisitor = EvolutionTreeEvolutionVisitor()
|
||||
}
|
||||
|
||||
private var rootTreeDrawingNode: TreeDrawingNode<EvolutionNode>? = null
|
||||
private var treeDrawingBounds: TreeDrawingBounds? = null
|
||||
private var zoomLevel: Double = 0.0
|
||||
private var panningX: Double = 0.0
|
||||
private var panningY: Double = 0.0
|
||||
|
||||
private var hoveredTooltips: List<MutableComponent>? = null
|
||||
|
||||
private val expandButton: ScaledButton = ScaledButton(
|
||||
0f,
|
||||
0f,
|
||||
EXPAND_BUTTON_SIZE,
|
||||
EXPAND_BUTTON_SIZE,
|
||||
resource = expandResource,
|
||||
clickAction = {
|
||||
parent.evolutionTreeExpanded = !parent.evolutionTreeExpanded
|
||||
expandButton.resource = if (parent.evolutionTreeExpanded) minimizeResource else expandResource
|
||||
updatePositioning()
|
||||
}
|
||||
).apply { addWidget(this) }
|
||||
|
||||
override fun renderWidget(
|
||||
guiGraphics: GuiGraphics,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
partialTick: Float,
|
||||
) {
|
||||
drawScaledText(
|
||||
context = guiGraphics,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = Component.translatable("cobblemon.ui.pokedex.info.evolution_tree").bold(),
|
||||
x = x + 9,
|
||||
y = y - 10,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
expandButton.render(guiGraphics, mouseX, mouseY, partialTick)
|
||||
|
||||
rootTreeDrawingNode?.let {
|
||||
enableScissors(guiGraphics)
|
||||
renderTreeDrawingNode(guiGraphics, it, mouseX, mouseY, partialTick)
|
||||
guiGraphics.disableScissor()
|
||||
|
||||
hoveredTooltips?.let { tooltips ->
|
||||
renderTooltip(
|
||||
guiGraphics,
|
||||
tooltips,
|
||||
mouseX,
|
||||
mouseY,
|
||||
partialTick,
|
||||
4,
|
||||
)
|
||||
}
|
||||
|
||||
hoveredTooltips = null
|
||||
}
|
||||
}
|
||||
|
||||
fun setup(pokedexEntry: PokedexEntry?, pokedexForm: PokedexForm?) {
|
||||
if (pokedexEntry == null || pokedexForm == null) return
|
||||
|
||||
updatePositioning()
|
||||
|
||||
val (rootPokedexEntry, rootPokedexForm) = Dexes.findRootDexEntryBySpeciesId(pokedexEntry.speciesId, pokedexForm.displayForm)
|
||||
val rootEvolutionNode = buildEvolutionTree(rootPokedexEntry, rootPokedexForm, null)
|
||||
|
||||
// val isSameEntry = previousRootPokedexEntry != null && pokedexEntry?.id == previousRootPokedexEntry?.id
|
||||
// val isSameForm =
|
||||
// previousRootPokedexForm != null && pokedexForm?.displayForm == previousRootPokedexForm?.displayForm
|
||||
|
||||
// TODO: figure out how to prevent pokedex from resetting all the widgets state
|
||||
// if (isSameEntry && isSameForm) {
|
||||
// return
|
||||
// }
|
||||
|
||||
previousRootPokedexEntry = pokedexEntry
|
||||
previousRootPokedexForm = pokedexForm
|
||||
|
||||
createDrawingTree(rootEvolutionNode).also {
|
||||
rootTreeDrawingNode = it
|
||||
treeDrawingBounds = calculateBounds<EvolutionNode>(it)
|
||||
}
|
||||
|
||||
zoomLevel = 0.0
|
||||
panningX = 0.0
|
||||
panningY = 0.0
|
||||
}
|
||||
|
||||
fun updatePositioning() {
|
||||
x = pX + X_MARGIN
|
||||
y = pY + if (parent.evolutionTreeExpanded) Y_MARGIN_EXPANDED else Y_MARGIN_MINIMIZED
|
||||
height = if (parent.evolutionTreeExpanded) EXPANDED_HEIGHT else POKEMON_DESCRIPTION_HEIGHT
|
||||
|
||||
panningX = 0.0
|
||||
panningY = 0.0
|
||||
|
||||
expandButton.buttonX = x + EXPAND_BUTTON_X_MARGIN
|
||||
expandButton.buttonY = y + EXPAND_BUTTON_Y_MARGIN
|
||||
}
|
||||
|
||||
private fun buildEvolutionTree(
|
||||
pokedexEntry: PokedexEntry,
|
||||
pokedexForm: PokedexForm,
|
||||
evolution: Evolution? = null
|
||||
): EvolutionNode {
|
||||
val species = PokemonSpecies.getByIdentifier(pokedexEntry.speciesId)!!
|
||||
|
||||
val formEquivalents = Dexes.getFormEquivalents(pokedexForm.displayForm)
|
||||
val form = species.forms.firstOrNull { formEquivalents.contains(it.name.lowercase()) }
|
||||
val parentSpecies = Dexes.findDexEntryBySpeciesId(species.resourceIdentifier)!!
|
||||
val parentPokedexForm = parentSpecies.forms.first { formEquivalents.contains(it.displayForm.lowercase()) }
|
||||
|
||||
val aspects = evolution?.result?.aspects?.toMutableSet() ?: mutableSetOf()
|
||||
form?.aspects?.let { aspects.addAll(it) }
|
||||
|
||||
val discoveryLevel = CobblemonClient.clientPokedexData.getHighestKnowledgeFor(pokedexEntry, pokedexForm, aspects)
|
||||
|
||||
val evolutions = form?.evolutions ?: species.evolutions
|
||||
val drawData = evolution?.let { evolutionVisitor.visit(evolution) }
|
||||
|
||||
// TODO: figure out if this works for fakemon
|
||||
val children = evolutions.mapNotNull { evolution ->
|
||||
val speciesId = cobblemonResource(evolution.result.species!!)
|
||||
val childPokedexEntry =
|
||||
Dexes.findDexEntryBySpeciesId(speciesId)
|
||||
|
||||
if (childPokedexEntry == null) {
|
||||
Cobblemon.LOGGER.warn("Dex entry not found for species: $speciesId")
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
val evolutionResult = evolution.result.create()
|
||||
val formEquivalents = Dexes.getFormEquivalents(evolutionResult.form.name.lowercase())
|
||||
val childPokedexForm = childPokedexEntry.forms.first { formEquivalents.contains(it.displayForm.lowercase()) }
|
||||
|
||||
return@mapNotNull buildEvolutionTree(childPokedexEntry, childPokedexForm, evolution)
|
||||
}
|
||||
|
||||
return EvolutionNode(pokedexEntry, parentPokedexForm, aspects, discoveryLevel, children, drawData)
|
||||
}
|
||||
|
||||
private fun renderTreeDrawingNode(
|
||||
guiGraphics: GuiGraphics,
|
||||
treeDrawingNode: TreeDrawingNode<EvolutionNode>,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
delta: Float,
|
||||
) {
|
||||
val (treeX, treeY) = getDrawingCoordinates(treeDrawingNode)
|
||||
|
||||
if (treeDrawingNode.children.size == 1) {
|
||||
val child = treeDrawingNode.children.first()
|
||||
val (childX, _) = getDrawingCoordinates(child)
|
||||
|
||||
val lineStartX = treeX + SCROLL_SLOT_SIZE
|
||||
val lineEndX = childX
|
||||
val lineY = treeY + SCROLL_SLOT_SIZE / 2
|
||||
|
||||
child.value.renderData?.let { renderData ->
|
||||
drawEvolutionInfo(
|
||||
guiGraphics,
|
||||
renderData,
|
||||
lineStartX,
|
||||
lineEndX,
|
||||
lineY,
|
||||
mouseX,
|
||||
mouseY,
|
||||
delta,
|
||||
)
|
||||
}
|
||||
} else if (treeDrawingNode.children.size > 1) {
|
||||
val treeForkStart = treeX + SCROLL_SLOT_SIZE
|
||||
val treeForkEnd = treeX + SCROLL_SLOT_SIZE + TREE_FORK_LENGTH
|
||||
val middleStart = treeY + SCROLL_SLOT_SIZE / 2
|
||||
|
||||
val (_, firstChildY) = getDrawingCoordinates(treeDrawingNode.children.first())
|
||||
val (_, lastChildY) = getDrawingCoordinates(treeDrawingNode.children.last())
|
||||
|
||||
guiGraphics.hLine(
|
||||
treeForkStart,
|
||||
treeForkEnd,
|
||||
middleStart,
|
||||
LINE_COLOR,
|
||||
)
|
||||
|
||||
guiGraphics.vLine(
|
||||
treeForkEnd,
|
||||
firstChildY + SCROLL_SLOT_SIZE / 2,
|
||||
lastChildY + SCROLL_SLOT_SIZE / 2,
|
||||
LINE_COLOR,
|
||||
)
|
||||
|
||||
treeDrawingNode.children.forEach { child ->
|
||||
val (childX, childY) = getDrawingCoordinates(child)
|
||||
|
||||
val lineStartX = treeForkEnd
|
||||
val lineEndX = childX
|
||||
val lineY = childY + SCROLL_SLOT_SIZE / 2
|
||||
|
||||
child.value.renderData?.let { renderData ->
|
||||
drawEvolutionInfo(
|
||||
guiGraphics,
|
||||
renderData,
|
||||
lineStartX,
|
||||
lineEndX,
|
||||
lineY,
|
||||
mouseX,
|
||||
mouseY,
|
||||
delta,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
treeDrawingNode.children.forEach { child ->
|
||||
renderTreeDrawingNode(guiGraphics, child, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
val isVisible =
|
||||
treeX >= x - SCROLL_SLOT_SIZE &&
|
||||
treeX <= x + width &&
|
||||
treeY >= y - SCROLL_SLOT_SIZE &&
|
||||
treeY <= y + height
|
||||
|
||||
if (!isVisible) return
|
||||
|
||||
val evolutionNode = treeDrawingNode.value
|
||||
val isSlotHovered =
|
||||
isElementHovered(mouseX, mouseY, treeX, treeX + SCROLL_SLOT_SIZE, treeY, treeY + SCROLL_SLOT_SIZE)
|
||||
|
||||
val discoveryLevel = evolutionNode.pokedexEntryProgress
|
||||
if (isSlotHovered) {
|
||||
val text =
|
||||
if (discoveryLevel == PokedexEntryProgress.UNREGISTERED) {
|
||||
lang("ui.pokedex.unknown")
|
||||
} else {
|
||||
val species = PokemonSpecies.getByIdentifier(evolutionNode.pokedexEntry.speciesId)!!
|
||||
val speciesComponent = species.translatedName
|
||||
val formName = evolutionNode.pokedexForm.displayForm.lowercase()
|
||||
val formComponent =
|
||||
if (formName == "normal") null
|
||||
else lang("ui.pokedex.info.form.${species}-${formName.replace("-", "")}")
|
||||
|
||||
formComponent?.add(" ")?.add(speciesComponent) ?: speciesComponent
|
||||
}
|
||||
|
||||
guiGraphics.disableScissor()
|
||||
renderTooltip(
|
||||
context = guiGraphics,
|
||||
text = text,
|
||||
posX = mouseX,
|
||||
posY = mouseY,
|
||||
delta,
|
||||
4,
|
||||
)
|
||||
enableScissors(guiGraphics)
|
||||
}
|
||||
|
||||
|
||||
val pokedexEntry = evolutionNode.pokedexEntry
|
||||
val pokedexForm = evolutionNode.pokedexForm
|
||||
val species = PokemonSpecies.getByIdentifier(evolutionNode.pokedexEntry.speciesId)!!
|
||||
val encounteredForms = CobblemonClient.clientPokedexData.getEncounteredForms(pokedexEntry)
|
||||
val formToRender = encounteredForms.firstOrNull { it.displayForm.equals(pokedexForm.displayForm, ignoreCase = true) }
|
||||
|
||||
val renderablePokemon =
|
||||
if (formToRender != null) {
|
||||
val seenGenders = CobblemonClient.clientPokedexData.getSeenGenders(pokedexEntry, formToRender)
|
||||
val seenShinyStates = CobblemonClient.clientPokedexData.getSeenShinyStates(pokedexEntry, formToRender)
|
||||
|
||||
val aspectsToDraw = (pokedexEntry.displayAspects + evolutionNode.aspects).toMutableSet()
|
||||
|
||||
val formAspects = species.forms.firstOrNull { it.name.equals(formToRender.displayForm, ignoreCase = true) }?.aspects
|
||||
if (formAspects != null) {
|
||||
aspectsToDraw.addAll(formAspects)
|
||||
}
|
||||
|
||||
if (seenGenders.contains(parent.gender)) {
|
||||
aspectsToDraw.add(parent.gender.name.lowercase())
|
||||
} else {
|
||||
aspectsToDraw.add((seenGenders.firstOrNull() ?: Gender.GENDERLESS).name.lowercase())
|
||||
}
|
||||
|
||||
if (parent.shiny && seenShinyStates.contains("shiny")) {
|
||||
aspectsToDraw.add("shiny")
|
||||
}
|
||||
|
||||
RenderablePokemon(species, aspectsToDraw)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
PokemonSlotWidget.render(
|
||||
context = guiGraphics,
|
||||
x = treeX,
|
||||
y = treeY,
|
||||
isHovered = isSlotHovered,
|
||||
species = species,
|
||||
renderablePokemon = renderablePokemon,
|
||||
discoveryLevel = discoveryLevel,
|
||||
)
|
||||
}
|
||||
|
||||
private fun drawEvolutionInfo(
|
||||
guiGraphics: GuiGraphics,
|
||||
renderData: RenderEvolutionData,
|
||||
lineStartX: Int,
|
||||
lineEndX: Int,
|
||||
lineY: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
delta: Float,
|
||||
) {
|
||||
val lineXMiddle = (lineStartX + lineEndX) / 2
|
||||
val iconX = (lineXMiddle + ICON_X_PADDING - ICON_SLOT_HALF_PADDING).toInt()
|
||||
val iconY = (lineY + ICON_Y_PADDING - ICON_SLOT_HALF_PADDING).toInt()
|
||||
val iconSize = ICON_SLOT_BACKGROUND_SIZE + ICON_SLOT_PADDING
|
||||
|
||||
val isVisible =
|
||||
iconX >= x - iconSize &&
|
||||
iconX <= x + width &&
|
||||
iconY >= y - iconSize &&
|
||||
iconY <= y + height
|
||||
|
||||
if (!isVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
if (renderData.icons.isEmpty()) {
|
||||
guiGraphics.hLine(
|
||||
lineStartX,
|
||||
lineEndX,
|
||||
lineY,
|
||||
LINE_COLOR,
|
||||
)
|
||||
} else {
|
||||
guiGraphics.hLine(
|
||||
lineStartX,
|
||||
iconX - 1,
|
||||
lineY,
|
||||
LINE_COLOR,
|
||||
)
|
||||
|
||||
guiGraphics.hLine(
|
||||
iconX + iconSize,
|
||||
lineEndX,
|
||||
lineY,
|
||||
LINE_COLOR,
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = guiGraphics.pose(),
|
||||
texture = slotResource,
|
||||
x = iconX,
|
||||
y = iconY,
|
||||
width = iconSize,
|
||||
height = iconSize,
|
||||
)
|
||||
|
||||
val index = (System.currentTimeMillis() / MILLIS_BETWEEN_ICONS_CYCLE) % renderData.icons.size
|
||||
val item = renderData.icons[index.toInt()]
|
||||
|
||||
renderScaledGuiItemIcon(
|
||||
itemStack = item.defaultInstance,
|
||||
x = lineXMiddle + ICON_X_PADDING,
|
||||
y = lineY + ICON_Y_PADDING,
|
||||
matrixStack = guiGraphics.pose(),
|
||||
scale = PokedexGUIConstants.SCALE.toDouble(),
|
||||
)
|
||||
}
|
||||
|
||||
val isLineHovered = isElementHovered(mouseX, mouseY, lineStartX, lineEndX, lineY - 1, lineY + 1)
|
||||
val isIconHovered = isElementHovered(
|
||||
mouseX,
|
||||
mouseY,
|
||||
iconX.toInt(),
|
||||
iconX.toInt() + iconSize,
|
||||
iconY.toInt(),
|
||||
iconY.toInt() + iconSize,
|
||||
)
|
||||
|
||||
if (renderData.tooltips.isNotEmpty() &&
|
||||
(isLineHovered || isIconHovered) &&
|
||||
this.isHovered(mouseX.toDouble(), mouseY.toDouble())
|
||||
) {
|
||||
hoveredTooltips = renderData.tooltips
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDrawingCoordinates(node: TreeDrawingNode<EvolutionNode>): Pair<Int, Int> {
|
||||
val halfSlot = SCROLL_SLOT_SIZE / 2f
|
||||
|
||||
val xStep = halfSlot + HORIZONTAL_PADDING
|
||||
val yStep = halfSlot + VERTICAL_PADDING
|
||||
|
||||
// Swaps the x and y to draw the tree horizontally
|
||||
val xDislocation = (node.y - treeDrawingBounds!!.yCenter) * xStep
|
||||
val yDislocation = (node.x - treeDrawingBounds!!.xCenter) * yStep
|
||||
|
||||
val xCenter = width / 2f - halfSlot
|
||||
val yCenter = height / 2f - halfSlot
|
||||
|
||||
val screenX = (xCenter.toInt() + xDislocation.toInt() + panningX.toInt() + x)
|
||||
val screenY = (yCenter.toInt() + yDislocation.toInt() + panningY.toInt() + y)
|
||||
|
||||
return screenX to screenY
|
||||
}
|
||||
|
||||
private fun isElementHovered(
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
startX: Int,
|
||||
endX: Int,
|
||||
startY: Int,
|
||||
endY: Int,
|
||||
): Boolean {
|
||||
return mouseX >= startX && mouseX <= endX && mouseY >= startY && mouseY <= endY
|
||||
}
|
||||
|
||||
override fun mouseDragged(
|
||||
mouseX: Double,
|
||||
mouseY: Double,
|
||||
button: Int,
|
||||
deltaX: Double,
|
||||
deltaY: Double
|
||||
): Boolean {
|
||||
panningX += deltaX
|
||||
panningY += deltaY
|
||||
|
||||
val bounds = treeDrawingBounds ?: return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
val treeHeight = bounds.height.coerceAtLeast(1)
|
||||
val treeWidth = bounds.width.coerceAtLeast(1)
|
||||
|
||||
val xStep = HORIZONTAL_PADDING + SCROLL_SLOT_SIZE / 2.0
|
||||
val yStep = VERTICAL_PADDING + SCROLL_SLOT_SIZE / 2.0
|
||||
|
||||
val minPanningX = (treeHeight - 1) * -xStep / 2.0 - (width + SCROLL_SLOT_SIZE) / 2.0
|
||||
val maxPanningX = (treeHeight - 1) * xStep / 2.0 + (width + SCROLL_SLOT_SIZE) / 2.0
|
||||
|
||||
val divideBy = if (treeWidth % 2 == 0) 4.0 else 2.0
|
||||
val minPanningY = (treeWidth - 1) * -yStep / 2.0 - height / 2.0 + SCROLL_SLOT_SIZE / divideBy
|
||||
val maxPanningY = (treeWidth - 1) * yStep / 2.0 + height / 2.0 - SCROLL_SLOT_SIZE / divideBy
|
||||
|
||||
panningX = panningX.coerceIn(minPanningX, maxPanningX)
|
||||
panningY = panningY.coerceIn(minPanningY, maxPanningY)
|
||||
|
||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Double, mouseY: Double): Boolean {
|
||||
return mouseX.toInt() in x..(x + width) && mouseY.toInt() in y..(y + height)
|
||||
}
|
||||
|
||||
fun enableScissors(guiGraphics: GuiGraphics) {
|
||||
guiGraphics.enableScissor(x + 1, y, x + width - 1, y + height)
|
||||
}
|
||||
|
||||
private class EvolutionNode(
|
||||
val pokedexEntry: PokedexEntry,
|
||||
val pokedexForm: PokedexForm,
|
||||
val aspects: Set<String>,
|
||||
val pokedexEntryProgress: PokedexEntryProgress,
|
||||
override val children: List<EvolutionNode>,
|
||||
val renderData: RenderEvolutionData?,
|
||||
) : TreeNode<EvolutionNode>
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.LevelRenderer
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
@@ -39,13 +40,13 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
|
||||
private val leftMargin = 1f
|
||||
private val rightMargin = 1f
|
||||
private val topMargin = 1f
|
||||
private val bottomMargin = 1f
|
||||
private val interRowSpacing = 0f
|
||||
private val tmOverlayDepthOffset = -0.0002f
|
||||
private val slotBrightnessMultiplier = 0.65f
|
||||
|
||||
private val tmBaseTexture = cobblemonResource("textures/block/disc_shelf/technical_machine_base.png")
|
||||
private val tmOverlayTexture = cobblemonResource("textures/block/disc_shelf/technical_machine_overlay.png")
|
||||
private val musicDiscUnknownTexture = cobblemonResource("textures/block/disc_shelf/music_disc_unknown.png")
|
||||
|
||||
override fun render(
|
||||
entity: DiscShelfBlockEntity,
|
||||
@@ -77,7 +78,6 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
|
||||
val slotWidth = slotWidthPixels / textureSize
|
||||
val slotHeight = slotHeightPixels / textureSize
|
||||
val verticalSpacing = (slotHeightPixels + interRowSpacing) / textureSize
|
||||
val totalHeight = slotHeight * 7 + interRowSpacing * 6 / textureSize
|
||||
val startY = topMargin / textureSize
|
||||
|
||||
for ((index, item) in entity.items.withIndex()) {
|
||||
@@ -188,6 +188,13 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
|
||||
|
||||
private fun getItemTexture(itemStack: ItemStack): ResourceLocation {
|
||||
val id = BuiltInRegistries.ITEM.getKey(itemStack.item)
|
||||
return cobblemonResource("textures/block/disc_shelf/${id.path}.png")
|
||||
val resource = cobblemonResource("textures/block/disc_shelf/${id.path}.png")
|
||||
|
||||
val resourceManager = Minecraft.getInstance().resourceManager
|
||||
if (resourceManager.getResource(resource).isEmpty) {
|
||||
return musicDiscUnknownTexture
|
||||
}
|
||||
|
||||
return resource
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import net.minecraft.world.entity.player.Player
|
||||
*
|
||||
* @author whatsy
|
||||
*/
|
||||
class AdvancementRequirement(val requiredAdvancement: ResourceLocation) : OwnerQueryRequirement() {
|
||||
class AdvancementRequirement(val requiredAdvancement: ResourceLocation) : OwnerQueryRequirement {
|
||||
|
||||
override fun checkPlayer(
|
||||
pokemon: Pokemon,
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
*
|
||||
* @property possibilities A collection of possible [Requirement]s that can allow this requirement to be valid.
|
||||
*/
|
||||
class AnyRequirement(val possibilities: Collection<Requirement>) : Requirement() {
|
||||
class AnyRequirement(val possibilities: Collection<Requirement>) : Requirement {
|
||||
override fun check(pokemon: Pokemon) = this.possibilities.any { it.check(pokemon) }
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "any"
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.world.phys.Vec3
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
class AreaRequirement : EntityQueryRequirement() {
|
||||
class AreaRequirement : EntityQueryRequirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "area"
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.pokemon.requirements
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class AttackDefenceRatioRequirement : Requirement() {
|
||||
class AttackDefenceRatioRequirement : Requirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "attack_defence_ratio"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHit
|
||||
* @since October 2nd, 2022
|
||||
*/
|
||||
@Suppress("unused", "CanBePrimaryConstructorProperty")
|
||||
class BattleCriticalHitsRequirement(amount: Int) : Requirement() {
|
||||
class BattleCriticalHitsRequirement(amount: Int) : Requirement {
|
||||
|
||||
constructor() : this(0)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import net.minecraft.world.level.biome.Biome
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
class BiomeRequirement : EntityQueryRequirement() {
|
||||
class BiomeRequirement : EntityQueryRequirement {
|
||||
val biomeCondition: RegistryLikeCondition<Biome>? = null
|
||||
val biomeAnticondition: RegistryLikeCondition<Biome>? = null
|
||||
override fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean {
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
* @author Licious
|
||||
* @since January 28th, 2023
|
||||
*/
|
||||
class BlocksTraveledRequirement(amount: Int) : Requirement() {
|
||||
class BlocksTraveledRequirement(amount: Int) : Requirement {
|
||||
|
||||
constructor() : this(0)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import kotlin.random.Random
|
||||
* @author Hiroku
|
||||
* @since January 30th, 2026
|
||||
*/
|
||||
class ChanceRequirement : Requirement() {
|
||||
class ChanceRequirement : Requirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "chance"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.cobblemon.mod.common.pokemon.evolution.progress.DamageTakenEvolutionP
|
||||
* @author Licious
|
||||
* @since January 27th, 2022
|
||||
*/
|
||||
class DamageTakenRequirement(amount: Int) : Requirement() {
|
||||
class DamageTakenRequirement(amount: Int) : Requirement {
|
||||
|
||||
constructor() : this(0)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgre
|
||||
* @author Licious
|
||||
* @since January 28th, 2022
|
||||
*/
|
||||
class DefeatRequirement(target: PokemonProperties, amount: Int) : Requirement() {
|
||||
class DefeatRequirement(target: PokemonProperties, amount: Int) : Requirement {
|
||||
|
||||
constructor() : this(PokemonProperties(), 0)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
class FriendshipRequirement : Requirement() {
|
||||
class FriendshipRequirement : Requirement {
|
||||
val amount = 0
|
||||
override fun check(pokemon: Pokemon) = pokemon.friendship >= this.amount
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.minecraft.world.item.Items
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
class HeldItemRequirement(val itemCondition: ItemPredicate) : Requirement() {
|
||||
class HeldItemRequirement(val itemCondition: ItemPredicate) : Requirement {
|
||||
|
||||
constructor() : this(ItemPredicate.Builder.item().of(Items.EGG).build())
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.pokemon.requirements
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class LevelRequirement : Requirement() {
|
||||
class LevelRequirement : Requirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "level"
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
* @author Licious
|
||||
* @since January 25th, 2023
|
||||
*/
|
||||
class MoonPhaseRequirement(moonPhase: MoonPhase) : EntityQueryRequirement() {
|
||||
class MoonPhaseRequirement(moonPhase: MoonPhase) : EntityQueryRequirement {
|
||||
|
||||
constructor() : this(MoonPhase.FULL_MOON)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
class MoveSetRequirement : Requirement() {
|
||||
class MoveSetRequirement : Requirement {
|
||||
val move: MoveTemplate = Moves.getByNameOrDummy("tackle")
|
||||
override fun check(pokemon: Pokemon) = pokemon.moveSet.getMoves().any { move -> move.name.equals(this.move.name, true) }
|
||||
companion object {
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class MoveTypeRequirement : Requirement() {
|
||||
class MoveTypeRequirement : Requirement {
|
||||
val type: ElementalType = ElementalTypes.NORMAL
|
||||
override fun check(pokemon: Pokemon) = pokemon.moveSet.getMoves().any { move -> move.type == type }
|
||||
companion object {
|
||||
|
||||
@@ -24,7 +24,7 @@ import net.minecraft.world.entity.player.Player
|
||||
* @author Polymeta
|
||||
*/
|
||||
class OwnerHoldsItemRequirement(val itemCondition: ItemPredicate)
|
||||
: OwnerQueryRequirement() {
|
||||
: OwnerQueryRequirement {
|
||||
|
||||
override fun checkPlayer(
|
||||
pokemon: Pokemon,
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
class PartyMemberRequirement : Requirement() {
|
||||
class PartyMemberRequirement : Requirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "party_member"
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
* @author Licious
|
||||
* @since March 26th, 2022
|
||||
*/
|
||||
class PokemonPropertiesRequirement : Requirement() {
|
||||
class PokemonPropertiesRequirement : Requirement {
|
||||
val target = PokemonProperties()
|
||||
override fun check(pokemon: Pokemon) = this.target.matches(pokemon)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.cobblemon.mod.common.api.pokemon.feature.IntSpeciesFeature
|
||||
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class PropertyRangeRequirement : Requirement() {
|
||||
class PropertyRangeRequirement : Requirement {
|
||||
val range = IntRange(0, 256)
|
||||
val feature: String = ""
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.cobblemon.mod.common.pokemon.evolution.progress.RecoilEvolutionProgre
|
||||
* @author Licious
|
||||
* @since January 27th, 2022
|
||||
*/
|
||||
class RecoilRequirement(amount: Int) : Requirement() {
|
||||
class RecoilRequirement(amount: Int) : Requirement {
|
||||
|
||||
constructor() : this(0)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class StatCompareRequirement : Requirement() {
|
||||
class StatCompareRequirement : Requirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "stat_compare"
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class StatEqualRequirement : Requirement() {
|
||||
class StatEqualRequirement : Requirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "stat_equal"
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import net.minecraft.world.level.levelgen.structure.Structure
|
||||
* @author whatsy
|
||||
* @since December 5th, 2023
|
||||
*/
|
||||
class StructureRequirement : EntityQueryRequirement() {
|
||||
class StructureRequirement : EntityQueryRequirement {
|
||||
val structureCondition: RegistryLikeCondition<Structure>? = null
|
||||
val structureAnticondition: RegistryLikeCondition<Structure>? = null
|
||||
override fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean {
|
||||
|
||||
@@ -20,7 +20,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
* @author Licious
|
||||
* @since March 26th, 2022
|
||||
*/
|
||||
class TimeRangeRequirement : EntityQueryRequirement() {
|
||||
class TimeRangeRequirement : EntityQueryRequirement {
|
||||
val range = TimeRange(0..23999)
|
||||
override fun check(pokemon: Pokemon, queriedEntity: LivingEntity) = this.range.contains((queriedEntity.level().dayTime() % DAY_DURATION).toInt())
|
||||
companion object {
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.cobblemon.mod.common.pokemon.evolution.progress.UseMoveEvolutionProgr
|
||||
* @author Licious
|
||||
* @since January 25th, 2023
|
||||
*/
|
||||
class UseMoveRequirement(move: MoveTemplate, amount: Int) : Requirement() {
|
||||
class UseMoveRequirement(move: MoveTemplate, amount: Int) : Requirement {
|
||||
|
||||
constructor() : this(Moves.getByNameOrDummy(""), 1)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.cobblemon.mod.common.api.pokemon.requirement.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
class WeatherRequirement : EntityQueryRequirement() {
|
||||
class WeatherRequirement : EntityQueryRequirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "weather"
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.world.level.Level
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
class WorldRequirement : EntityQueryRequirement() {
|
||||
class WorldRequirement : EntityQueryRequirement {
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "world"
|
||||
}
|
||||
|
||||
@@ -274,11 +274,9 @@ object DataKeys {
|
||||
// Habitat Blocks
|
||||
const val HABITAT_SPAWNING_STYLE = "SpawningStyle"
|
||||
const val HABITAT_MIMIC = "MimicId"
|
||||
const val HABITAT_PHASE_COUNT = "PhaseCount"
|
||||
const val HABITAT_PHASE_ORDER = "PhaseOrder"
|
||||
const val HABITAT_LEVEL_RANGE = "LevelRange"
|
||||
const val HABITAT_MODIFIERS = "Modifiers"
|
||||
const val HABITAT_POOL = "Pool"
|
||||
|
||||
// --- Pools
|
||||
const val HABITAT_POOL_ID = "PoolId"
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
},
|
||||
"animation.luvdisc.ground_faint": {
|
||||
"loop": true,
|
||||
"animation_length": 2.5,
|
||||
"animation_length": 3,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": {
|
||||
|
||||
@@ -39,11 +39,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat1",
|
||||
"name": "locator_seat_1",
|
||||
"parent": "thorax",
|
||||
"pivot": [0, 11, 0],
|
||||
"locators": {
|
||||
"seat1": [0, 11, 1]
|
||||
"seat_1": [0, 11, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
"parent": "torso",
|
||||
"pivot": [0, 21, 3.75],
|
||||
"locators": {
|
||||
"seat_2": [0, 21, 3.75]
|
||||
"seat_1": [0, 21, 3.75]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"parent": "torso",
|
||||
"pivot": [0, 21, 3.75],
|
||||
"locators": {
|
||||
"seat_2": [0, 21, 3.75]
|
||||
"seat_1": [0, 21, 3.75]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -377,11 +377,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat1",
|
||||
"name": "locator_seat_1",
|
||||
"parent": "saddle",
|
||||
"pivot": [0, 23.525, 0],
|
||||
"locators": {
|
||||
"seat1": [0, 23.525, 0]
|
||||
"seat_1": [0, 23.525, 0]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -30,6 +30,14 @@
|
||||
"parent": "body_rotation",
|
||||
"pivot": [0, 8.5, 0]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "waist_rotation",
|
||||
"pivot": [0, 36, 0],
|
||||
"locators": {
|
||||
"seat_1": [0, 35.75, 8.5]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "waist_scale",
|
||||
"parent": "waist_rotation",
|
||||
|
||||
@@ -188,12 +188,10 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [-1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [-1.51, 12.8, -2], "size": [0, 1, 2], "uv": [60, 14]},
|
||||
{"origin": [-1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [56, 14]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 1, 2], "uv": [60, 16]},
|
||||
{"origin": [-1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [56, 16]},
|
||||
{"origin": [-1.51, 11.8, -2], "size": [0, 1, 2], "uv": [60, 15]},
|
||||
{"origin": [-1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [56, 15]}
|
||||
{"origin": [-1.52, 12.8, -2], "size": [0, 1, 1], "uv": [62, 15]},
|
||||
{"origin": [-1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [56, 13]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 2, 3], "uv": [56, 14]},
|
||||
{"origin": [-1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [62, 16]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -201,8 +199,8 @@
|
||||
"parent": "eye_right",
|
||||
"pivot": [-1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [56, 13]},
|
||||
{"origin": [-1.51, 13.8, -2], "size": [0, 1, 2], "uv": [60, 13]}
|
||||
{"origin": [-1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [56, 12]},
|
||||
{"origin": [-1.52, 13.8, -2], "size": [0, 1, 1], "uv": [62, 14]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -223,7 +221,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
{"origin": [-1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -240,7 +238,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.42, 13, -1.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.42, 12.5, -1.75], "size": [0, 1, 1], "uv": [1, 1]}
|
||||
{"origin": [-1.44, 12.5, -1.75], "size": [0, 1, 1], "uv": [1, 1]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -248,7 +246,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.42, 13, 0.75],
|
||||
"cubes": [
|
||||
{"origin": [-1.42, 12.5, 0.25], "size": [0, 1, 1], "uv": [1, 2]}
|
||||
{"origin": [-1.44, 12.5, 0.25], "size": [0, 1, 1], "uv": [1, 2]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -272,12 +270,10 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [1.51, 12.8, -2], "size": [0, 1, 2], "uv": [52, 14], "mirror": true},
|
||||
{"origin": [1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [48, 14], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 1, 2], "uv": [52, 16], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [48, 16], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -2], "size": [0, 1, 2], "uv": [52, 15], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [48, 15], "mirror": true}
|
||||
{"origin": [1.52, 12.8, -2], "size": [0, 1, 1], "uv": [54, 15], "mirror": true},
|
||||
{"origin": [1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [48, 13], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 2, 3], "uv": [48, 14], "mirror": true},
|
||||
{"origin": [1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [54, 16], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -285,8 +281,8 @@
|
||||
"parent": "eye_left",
|
||||
"pivot": [1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [48, 13], "mirror": true},
|
||||
{"origin": [1.51, 13.8, -2], "size": [0, 1, 2], "uv": [52, 13], "mirror": true}
|
||||
{"origin": [1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [48, 12], "mirror": true},
|
||||
{"origin": [1.52, 13.8, -2], "size": [0, 1, 1], "uv": [54, 14], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -307,7 +303,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
{"origin": [1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -324,7 +320,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.42, 13, -1.25],
|
||||
"cubes": [
|
||||
{"origin": [1.42, 12.5, -1.75], "size": [0, 1, 1], "uv": [3, 1], "mirror": true}
|
||||
{"origin": [1.44, 12.5, -1.75], "size": [0, 1, 1], "uv": [3, 1], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -332,7 +328,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.42, 13, 0.75],
|
||||
"cubes": [
|
||||
{"origin": [1.42, 12.5, 0.25], "size": [0, 1, 1], "uv": [3, 2], "mirror": true}
|
||||
{"origin": [1.44, 12.5, 0.25], "size": [0, 1, 1], "uv": [3, 2], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -188,12 +188,10 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [-1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [-1.51, 12.8, -2], "size": [0, 1, 2], "uv": [60, 12]},
|
||||
{"origin": [-1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [56, 12]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 1, 2], "uv": [60, 14]},
|
||||
{"origin": [-1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [56, 14]},
|
||||
{"origin": [-1.51, 11.8, -2], "size": [0, 1, 2], "uv": [60, 13]},
|
||||
{"origin": [-1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [56, 13]}
|
||||
{"origin": [-1.52, 12.8, -2], "size": [0, 1, 1], "uv": [62, 13]},
|
||||
{"origin": [-1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [56, 11]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 2, 3], "uv": [56, 12]},
|
||||
{"origin": [-1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [62, 14]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -201,8 +199,8 @@
|
||||
"parent": "eye_right",
|
||||
"pivot": [-1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [56, 11]},
|
||||
{"origin": [-1.51, 13.8, -2], "size": [0, 1, 2], "uv": [60, 11]}
|
||||
{"origin": [-1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [56, 10]},
|
||||
{"origin": [-1.52, 13.8, -2], "size": [0, 1, 1], "uv": [62, 12]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -211,7 +209,7 @@
|
||||
"pivot": [-1.31, 11.6, 1.3],
|
||||
"cubes": [
|
||||
{"origin": [-1.81, 10.6, 0.3], "size": [1, 2, 2], "inflate": -0.3, "uv": [58, 17]},
|
||||
{"origin": [-1.61, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 19]}
|
||||
{"origin": [-1.62, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 19]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -224,7 +222,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
{"origin": [-1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -257,12 +255,10 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [1.51, 12.8, -2], "size": [0, 1, 2], "uv": [52, 12], "mirror": true},
|
||||
{"origin": [1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [48, 12], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 1, 2], "uv": [52, 14], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [48, 14], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -2], "size": [0, 1, 2], "uv": [52, 13], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [48, 13], "mirror": true}
|
||||
{"origin": [1.52, 12.8, -2], "size": [0, 1, 1], "uv": [54, 13], "mirror": true},
|
||||
{"origin": [1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [48, 11], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 2, 3], "uv": [48, 12], "mirror": true},
|
||||
{"origin": [1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [54, 14], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -270,8 +266,8 @@
|
||||
"parent": "eye_left",
|
||||
"pivot": [1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [48, 11], "mirror": true},
|
||||
{"origin": [1.51, 13.8, -2], "size": [0, 1, 2], "uv": [52, 11], "mirror": true}
|
||||
{"origin": [1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [48, 10], "mirror": true},
|
||||
{"origin": [1.52, 13.8, -2], "size": [0, 1, 1], "uv": [54, 12], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -280,7 +276,7 @@
|
||||
"pivot": [1.31, 11.6, 1.3],
|
||||
"cubes": [
|
||||
{"origin": [0.81, 10.6, 0.3], "size": [1, 2, 2], "inflate": -0.3, "uv": [52, 17], "mirror": true},
|
||||
{"origin": [0.61, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 17], "mirror": true}
|
||||
{"origin": [0.62, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 17], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -293,7 +289,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
{"origin": [1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -274,6 +274,14 @@
|
||||
"parent": "lower_gear_rotation",
|
||||
"pivot": [0, 9, -6]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "lower_gear_rotation",
|
||||
"pivot": [0, 10.5, -4.5],
|
||||
"locators": {
|
||||
"seat_1": [0, 10.5, -4.5]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "gear4",
|
||||
"parent": "lower_gear",
|
||||
|
||||
@@ -447,6 +447,14 @@
|
||||
"cubes": [
|
||||
{"origin": [0, -24.5, -8], "size": [0, 12, 7], "uv": [98, 109]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "body",
|
||||
"pivot": [0, 54, -10],
|
||||
"locators": {
|
||||
"seat_1": [0, 54, -10]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -474,6 +474,67 @@
|
||||
"cubes": [
|
||||
{"origin": [27, 10.5, 5], "size": [15, 19, 0], "uv": [223, 39]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 30, -19],
|
||||
"locators": {
|
||||
"seat_1": [0, 30, -19]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_2",
|
||||
"parent": "torso",
|
||||
"pivot": [13, 30, -14],
|
||||
"rotation": [0, -90, 0],
|
||||
"locators": {
|
||||
"seat_2": [13, 30, -14]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_3",
|
||||
"parent": "torso",
|
||||
"pivot": [-13, 30, -14],
|
||||
"rotation": [0, 90, 0],
|
||||
"locators": {
|
||||
"seat_3": [-13, 30, -14]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_4",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 34, -3],
|
||||
"locators": {
|
||||
"seat_4": [0, 34, -3]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_5",
|
||||
"parent": "torso",
|
||||
"pivot": [13, 30, 2],
|
||||
"rotation": [0, -90, 0],
|
||||
"locators": {
|
||||
"seat_5": [13, 30, 2]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_6",
|
||||
"parent": "torso",
|
||||
"pivot": [-13, 30, 2],
|
||||
"rotation": [0, 90, 0],
|
||||
"locators": {
|
||||
"seat_6": [-13, 30, 2]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_7",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 33, 7],
|
||||
"rotation": [0, 180, 0],
|
||||
"locators": {
|
||||
"seat_7": [0, 33, 7]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1137,7 +1137,6 @@
|
||||
"cobblemon.container.tm_machine": "TM Machine",
|
||||
"cobblemon.ui.edit.habitat": "Habitat Editor",
|
||||
"cobblemon.ui.edit.habitat.mimic_id": "Mimic Block ID",
|
||||
"cobblemon.ui.edit.habitat.phase_number": "Number of Phases",
|
||||
"cobblemon.ui.edit.habitat.phase_order": "Phase Order: %s",
|
||||
"cobblemon.ui.edit.habitat.level_range": "Level Range (Min - Max)",
|
||||
"cobblemon.ui.edit.habitat.mode": "Mode: %s",
|
||||
@@ -1187,7 +1186,7 @@
|
||||
"cobblemon.ui.edit.habitat.validation.species": "Species must be a valid Pokemon name.",
|
||||
"cobblemon.ui.edit.habitat.validation.weight": "Weight must be greater than 0.",
|
||||
"cobblemon.ui.edit.habitat.validation.modifiers": "Modifiers format is invalid.",
|
||||
"cobblemon.ui.edit.habitat.validation.phases_list": "Phases must use valid moon phases (0-7), e.g. 1-3 or 1, 3-5, 6.",
|
||||
"cobblemon.ui.edit.habitat.validation.phases_list": "Phases must use a valid format for integer ranges, e.g. 1-3 or 1, 3-5, 6.",
|
||||
"cobblemon.ui.edit.habitat.validation.min_light": "Min Light must be between 0 and 15.",
|
||||
"cobblemon.ui.edit.habitat.validation.max_light": "Max Light must be between 0 and 15.",
|
||||
|
||||
@@ -1349,8 +1348,6 @@
|
||||
"cobblemon.ui.pokedex.info.drops_range": "%1$s-%2$s×",
|
||||
"cobblemon.ui.pokedex.info.drops_percentage": "%1$s%%",
|
||||
"cobblemon.ui.pokedex.info.drops_empty": "No drops available.",
|
||||
"cobblemon.ui.pokedex.info.evolution_tree": "Evolution Tree",
|
||||
|
||||
"cobblemon.ui.pokedex.info.variation": "Variation",
|
||||
"cobblemon.ui.pokedex.info.form": "Form",
|
||||
"cobblemon.ui.pokedex.info.form.normal": "Standard",
|
||||
@@ -1462,59 +1459,6 @@
|
||||
"cobblemon.ui.pokedex.unknown": "???",
|
||||
"cobblemon.ui.pokedex.weight": "Weight: %1$skg",
|
||||
"cobblemon.ui.pokedex.height": "Height: %1$sm",
|
||||
|
||||
"cobblemon.ui.pokedex.evolution.item_interact.label": "Item",
|
||||
"cobblemon.ui.pokedex.evolution.item_interact.tooltip": "Needs %1$s item to evolve",
|
||||
"cobblemon.ui.pokedex.evolution.trade.label": "Trade",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_species": "Evolves when traded with %1$s",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_any_species": "Evolves when traded",
|
||||
|
||||
"cobblemon.ui.pokedex.requirement.advancement.tooltip": "Player must have %1$s advancement",
|
||||
"cobblemon.ui.pokedex.requirement.battle_critical_hits.tooltip": "Must hit %1$s critical-hits in battle",
|
||||
"cobblemon.ui.pokedex.requirement.blocks_traveled.tooltip": "Must travel %1$s blocks",
|
||||
"cobblemon.ui.pokedex.requirement.damage_taken.tooltip": "Must take %1$s damage in battle without fainting",
|
||||
"cobblemon.ui.pokedex.requirement.defeat.tooltip": "Must defeat %1$s in battle to evolve",
|
||||
"cobblemon.ui.pokedex.requirement.friendship.label": "Frien.",
|
||||
"cobblemon.ui.pokedex.requirement.friendship.tooltip": "Requires at least %1$s friendship",
|
||||
"cobblemon.ui.pokedex.requirement.held_item.tooltip": "Must be holding %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.level.label": "Lv. %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.level.tooltip.min": "Evolves starting at level %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.moon_phase.tooltip": "Must evolve in %1$s moon phase",
|
||||
"cobblemon.ui.pokedex.requirement.level.tooltip.between": "Evolves between levels %1$s and %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.has_move.tooltip": "Must know move %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.has_move_type.tooltip": "Must know a move of type %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.has_move_type.label": "Has Move",
|
||||
"cobblemon.ui.pokedex.requirement.owner_held_item.label": "Owner must be holding %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.recoil.tooltip": "Must suffer %1$s units of recoil in battle",
|
||||
"cobblemon.ui.pokedex.requirement.stat_compare.tooltip": "Must have its %1$s higher than its %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.stat_equal.tooltip": "Must have its %1$s equals to its %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.time_range.tooltip": "Must evolve during the %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.use_move.tooltip": "Must use move %1$s in battle",
|
||||
"cobblemon.ui.pokedex.requirement.weather.tooltip.raining": "Must be in rain to evolve",
|
||||
"cobblemon.ui.pokedex.requirement.weather.tooltip.thundering": "Must be in a thunderstorm to evolve",
|
||||
|
||||
"cobblemon.ui.moon_phase.full_moon": "Full Moon",
|
||||
"cobblemon.ui.moon_phase.waning_gibbous": "Waning Gibbous",
|
||||
"cobblemon.ui.moon_phase.third_quarter": "Third Quarter",
|
||||
"cobblemon.ui.moon_phase.waning_crescent": "Waning Crescent",
|
||||
"cobblemon.ui.moon_phase.new_moon": "New Moon",
|
||||
"cobblemon.ui.moon_phase.waxing_crescent": "Waxing Crescent",
|
||||
"cobblemon.ui.moon_phase.first_quarter": "First Quarter",
|
||||
"cobblemon.ui.moon_phase.waxing_gibbous": "Waxing Gibbous",
|
||||
|
||||
"cobblemon.ui.time_range.any": "Any",
|
||||
"cobblemon.ui.time_range.day": "Day",
|
||||
"cobblemon.ui.time_range.night": "Night",
|
||||
"cobblemon.ui.time_range.noon": "Noon",
|
||||
"cobblemon.ui.time_range.midnight": "Midnight",
|
||||
"cobblemon.ui.time_range.dawn": "Dawn",
|
||||
"cobblemon.ui.time_range.dusk": "Dusk",
|
||||
"cobblemon.ui.time_range.twilight": "Twilight",
|
||||
"cobblemon.ui.time_range.morning": "Morning",
|
||||
"cobblemon.ui.time_range.afternoon": "Afternoon",
|
||||
"cobblemon.ui.time_range.predawn": "Predawn",
|
||||
"cobblemon.ui.time_range.evening": "Evening",
|
||||
|
||||
"cobblemon.pokedex.variation.cream": "Cream",
|
||||
"cobblemon.pokedex.variation.decoration": "Decoration",
|
||||
"cobblemon.pokedex.variation.flower": "Flower",
|
||||
|
||||
@@ -9351,11 +9351,11 @@
|
||||
"cobblemon.habitat.natural_lightning_rod.name": "Pararrayos natural",
|
||||
"cobblemon.habitat.quartz_spikes.name": "Picos de Cuarzo",
|
||||
"cobblemon.subtitle.tm.use": "Máquina Técnica usada",
|
||||
"cobblemon.subtitle.block.tm_machine.craft": "Máquina MT imprime MT",
|
||||
"cobblemon.subtitle.block.tm_machine.craft": "Máquina MT termina de imprimir la MT",
|
||||
"cobblemon.subtitle.block.tm_machine.off": "Máquina MT desactivada",
|
||||
"cobblemon.subtitle.block.tm_machine.on": "Máquina MT activada",
|
||||
"cobblemon.subtitle.block.tm_machine.open": "La tapa de la Máquina MT se abre",
|
||||
"cobblemon.subtitle.block.tm_machine.close": "Ma tapa de la Máquina MT se cierra",
|
||||
"cobblemon.subtitle.block.tm_machine.close": "La tapa de la Máquina MT se cierra",
|
||||
"cobblemon.subtitle.block.tm_machine.place_disc": "MT en blanco insertada en la Máquina MT",
|
||||
"cobblemon.ui.exp.number": "+%1$s §oEXP",
|
||||
"cobblemon.config.ui.award_experience_to_fainted_pokemon": "Da Exp. a Pokémon derrotados",
|
||||
@@ -9511,5 +9511,9 @@
|
||||
"advancements.cobblemon.cook_poke_snack": "Un aroma tentador",
|
||||
"advancements.cobblemon.cook_poke_snack.description": "Hornea un Poké Señuelo, un delicioso pastel que atrae a ciertos Pokémon según las bayas que uses",
|
||||
"advancements.cobblemon.register_all_tms": "Discografía completa",
|
||||
"advancements.cobblemon.plant_tumblestone.description": "Coloca un guijarro cerca de lava o de magma para que crezca a lo largo del tiempo"
|
||||
"advancements.cobblemon.plant_tumblestone.description": "Coloca un guijarro cerca de lava o de magma para que crezca a lo largo del tiempo",
|
||||
"cobblemon.subtitle.block.tm_machine.burn_loop": "Máquina MT imprime MT",
|
||||
"cobblemon.subtitle.block.tm_machine.start": "Maquina MT empieza a imprimir MT",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_insert": "MT en blanco colocada en la Máquina MT",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_retrieve": "MT retirada de la Máquina MT"
|
||||
}
|
||||
|
||||
@@ -819,7 +819,7 @@
|
||||
"advancements.cobblemon.first_catch.description": "モンスターボールを投げて、ポケモンを捕まえる",
|
||||
"advancements.cobblemon.full_party": "フルハウス",
|
||||
"advancements.cobblemon.full_party.description": "ポケモンをもっとゲットし、手持ちを6匹にする",
|
||||
"advancements.cobblemon.first_evolution": "てれ てれん",
|
||||
"advancements.cobblemon.first_evolution": "新たなる姿",
|
||||
"advancements.cobblemon.first_evolution.description": "進化条件を満たし、ポケモンを進化させる",
|
||||
"advancements.cobblemon.first_battle_victory": "勝利は目の前?",
|
||||
"advancements.cobblemon.first_battle_victory.description": "他のトレーナーに勝利する",
|
||||
@@ -831,7 +831,7 @@
|
||||
"advancements.cobblemon.obtain_leek.description": "淡水で育つ野草、クスリソウを手に入れる",
|
||||
"advancements.cobblemon.medicinal_brew": "町のジョーイさん",
|
||||
"advancements.cobblemon.medicinal_brew.description": "クスリソウを醸造して溶媒のクスリチャを作る",
|
||||
"advancements.cobblemon.brew_potion": "そんな装備で大丈夫か?",
|
||||
"advancements.cobblemon.brew_potion": "お砂糖ひとさじ",
|
||||
"advancements.cobblemon.brew_potion.description": "クスリチャを溶媒にオレンのみを醸造してキズぐすりを作る",
|
||||
"advancements.cobblemon.brew_full_restore": "チャンピオン御用達",
|
||||
"advancements.cobblemon.brew_full_restore.description": "まんたんのくすりを溶媒にラムのみを醸造してかいふくのくすりを作る",
|
||||
@@ -1235,10 +1235,10 @@
|
||||
"cobblemon.battle.fail.healblock": "%1$sは かいふくふうじで 回復できない!",
|
||||
"cobblemon.battle.fail.darkvoid": "しかし %1$sは 使うことが できなかった!",
|
||||
"cobblemon.battle.fail.teatime": "しかし 何も 起こらなかった!",
|
||||
"cobblemon.battle.fail.slp": "%1$sは すでに 眠っている",
|
||||
"cobblemon.battle.fail.par": "%1$sは すでに まひしている",
|
||||
"cobblemon.battle.fail.slp": "しかし %1$sは 眠らない!",
|
||||
"cobblemon.battle.fail.par": "しかし %1$sは まひにならない!",
|
||||
"cobblemon.battle.fail.tox": "%1$sは すでに 毒を あびている",
|
||||
"cobblemon.battle.fail.psn": "%1$sは すでに 毒を あびている",
|
||||
"cobblemon.battle.fail.psn": "しかし %1$sは 毒にならない!",
|
||||
"cobblemon.battle.fail.brn": "%1$sは すでに やけどを 負っている",
|
||||
"cobblemon.battle.fail.frz": "%1$sは すでに 凍っている",
|
||||
"cobblemon.battle.fail.uproar": "%1$sは 騒いでいて 眠れない!",
|
||||
@@ -9237,7 +9237,7 @@
|
||||
"cobblemon.ui.edit.habitat.validation.species": "種族名は有効なポケモン名でなければなりません。",
|
||||
"cobblemon.ui.edit.habitat.validation.weight": "重量は0より大きくなければなりません。",
|
||||
"cobblemon.ui.edit.habitat.validation.modifiers": "修飾子の形式が無効です。",
|
||||
"cobblemon.ui.edit.habitat.validation.phases_list": "フェーズには有効な月の満ち欠け(0-7)を指定する必要があります。例:1-3、または1、3-5、6。",
|
||||
"cobblemon.ui.edit.habitat.validation.phases_list": "フェーズでは、整数の範囲を表す際に有効な形式を使用する必要があります。例:1-3、または1、3-5、6。",
|
||||
"cobblemon.ui.edit.habitat.validation.min_light": "最小明るさ度の値は0から15の間でなければなりません。",
|
||||
"cobblemon.ui.edit.habitat.validation.max_light": "最大明るさ度の値は0から15の間でなければなりません。",
|
||||
"cobblemon.ui.moves.learnset.tm.discovered": "発見済み",
|
||||
@@ -9302,5 +9302,81 @@
|
||||
"cobblemon.habitat.pinkflowerbed_clearing.name": "ピンクフラワーベッドの開拓地",
|
||||
"cobblemon.habitat.sandpit_clearing.name": "砂場の開拓地",
|
||||
"cobblemon.habitat.sunflowerbed_clearing.name": "ヒマワリベッドの開拓地",
|
||||
"cobblemon.habitat.sunscorched_clearing.name": "日差しに焼かれた開拓地"
|
||||
"cobblemon.habitat.sunscorched_clearing.name": "日差しに焼かれた開拓地",
|
||||
"cobblemon.habitat.quartz_spikes.name": "クォーツスパイク",
|
||||
"cobblemon.habitat.reclaimed_desert_monument.name": "再生された砂漠の記念碑",
|
||||
"cobblemon.habitat.reclaimed_lush_monument.name": "再生された繁茂した記念碑",
|
||||
"cobblemon.habitat.rocky_outcrop.name": "岩の露頭",
|
||||
"cobblemon.habitat.rocky_tide_pool.name": "岩場の潮だまり",
|
||||
"cobblemon.habitat.root_nursery.name": "根苗圃",
|
||||
"cobblemon.habitat.sandy_tide_pool.name": "砂地の潮だまり",
|
||||
"cobblemon.habitat.skeletal_fall.name": "骸骨の墓場",
|
||||
"cobblemon.habitat.snowy_burrow.name": "雪に覆われた巣穴",
|
||||
"cobblemon.habitat.snowy_grotto.name": "雪に覆われた洞窟",
|
||||
"cobblemon.habitat.snowy_thermal_vents.name": "雪に覆われた熱水噴出孔",
|
||||
"cobblemon.habitat.thermal_crevices.name": "熱の裂け目",
|
||||
"cobblemon.habitat.treasure_hoard.name": "秘宝の宝庫",
|
||||
"cobblemon.habitat.volcanic_plume.name": "火山噴出柱",
|
||||
"cobblemon.habitat.zen_garden.name": "思念の庭園",
|
||||
"cobblemon.subtitle.tm.use": "わざマシン使用済み",
|
||||
"cobblemon.subtitle.block.tm_machine.burn_loop": "わざマシンマシンでわざマシンをプリントする",
|
||||
"cobblemon.subtitle.block.tm_machine.start": "わざマシンマシンがわざマシンのプリントを開始しました",
|
||||
"cobblemon.subtitle.block.tm_machine.craft": "わざマシンマシンがわざマシンのプリントを完了しました",
|
||||
"cobblemon.subtitle.block.tm_machine.open": "わざマシンマシンの蓋が開きます",
|
||||
"cobblemon.subtitle.block.tm_machine.close": "わざマシンマシンの蓋が閉じます",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_insert": "わざマシンマシンに空のわざマシンをセットする",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_retrieve": "わざマシンをわざマシンマシンから入手",
|
||||
"cobblemon.subtitle.block.tm_machine.item_insert": "アイテムをわざマシンマシンに配置しました",
|
||||
"cobblemon.subtitle.block.tm_machine.item_retrieve": "わざマシンマシンからアイテムを取り出した",
|
||||
"cobblemon.ui.exp.number": "+%1$s §o経験値",
|
||||
"cobblemon.config.ui.award_experience_to_fainted_pokemon": "倒れたポケモンにも経験値を与える",
|
||||
"cobblemon.config.ui.award_experience_to_fainted_pokemon.tooltip": "バトル中ひんしになったポケモンは、ひんしになる前に倒すのに貢献した相手から経験値を獲得できるか。",
|
||||
"cobblemon.config.ui.award_experience_on_battle_loss": "戦闘敗北時の経験値",
|
||||
"cobblemon.config.ui.award_experience_on_battle_loss.tooltip": "バトルに負けた場合でも、倒した相手からポケモンは経験値を獲得できるか。ひんしになったポケモンが経験値を獲得するには、「倒れたポケモンにも経験値を与える」が有効になっている必要がある。",
|
||||
"cobblemon.config.ui.fossil_machine_alpha_chance": "化石マシンのオヤブン出現確率",
|
||||
"cobblemon.config.ui.fossil_machine_alpha_chance.tooltip": "化石マシンから入手できるポケモンがオヤブンになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.fossil_machine_shiny_chance.tooltip": "ふくげんマシンから入手できるポケモンが色違いになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.honey_slather_alpha_chance.tooltip": "ミツ塗りの木から入手できるポケモンがオヤブンになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.honey_slather_shiny_chance.tooltip": "ミツ塗りの木から入手できるポケモンが色違いになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.fossil_machine_shiny_chance": "化石マシンの色違い出現確率",
|
||||
"cobblemon.config.ui.honey_slather_alpha_chance": "ミツ塗りの木のオヤブン出現確率",
|
||||
"cobblemon.config.ui.honey_slather_shiny_chance": "ミツ塗りの木の色違い出現確率",
|
||||
"cobblemon.config.ui.data_monitor_alpha_rate": "データモニターのオヤブン出現確率",
|
||||
"cobblemon.config.ui.data_monitor_alpha_rate.tooltip": "データモニターから入手できるポケモンがオヤブンになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.data_monitor_shiny_rate": "データモニターの色違い出現確率",
|
||||
"cobblemon.config.ui.data_monitor_shiny_rate.tooltip": "データモニターから入手できるポケモンが色違いになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_min.tooltip": "出現するポケモンの最小固有サイズ倍率。",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_min": "ポケモンの最小固有サイズ",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_max": "ポケモンの最大固有サイズ",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_max.tooltip": "出現するポケモンの最大固有サイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_small_multiplier.tooltip": "当たり判定が0.5ブロック未満のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_small_multiplier": "小さいオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_medium_multiplier": "中くらいのオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_medium_multiplier.tooltip": "当たり判定が0.5ブロックから1.5ブロックの間のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_large_multiplier": "大きいオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_large_multiplier.tooltip": "当たり判定が1.5ブロックから10ブロックの間のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_extra_large_multiplier.tooltip": "当たり判定が10ブロック以上のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_extra_large_multiplier": "とても大きいオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.baby_pokemon_level_duration": "ベイビィポケモン期間レベル",
|
||||
"cobblemon.config.ui.baby_pokemon_level_duration.tooltip": "ポケモンが通常よりも小さく見える「ベイビィポケモン」とみなされるレベル数。",
|
||||
"cobblemon.config.ui.baby_pokemon_size_multiplier": "ベイビィポケモンの最小サイズ",
|
||||
"cobblemon.config.ui.baby_pokemon_size_multiplier.tooltip": "レベル1のポケモンに適用されるサイズ倍率。",
|
||||
"cobblemon.config.ui.minimum_riding_scale": "ライドするための最低限のポケモンスケール値",
|
||||
"cobblemon.config.ui.minimum_riding_scale.tooltip": "ポケモンに乗れなくなる限界のスケール。",
|
||||
"cobblemon.config.ui.unlock_all_move_dex_moves_by_default.tooltip": "この機能を有効にすると、わざマシンやレベルアップで覚える技が解放され、わざマシンマシンやポケモン図鑑の技一覧で確認できるようになります。",
|
||||
"cobblemon.config.ui.unlock_all_move_dex_moves_by_default": "全ての技をアンロック",
|
||||
"cobblemon.config.ui.infinite_tm_uses": "わざマシン無限化",
|
||||
"cobblemon.config.ui.infinite_tm_uses.tooltip": "わざマシンで技を教える際、わざマシンが消費されなくなります。",
|
||||
"advancements.cobblemon.use_healing_machine.description": "かいふく装置のチャージを待ち、使用して手持ちのポケモンを回復させる",
|
||||
"advancements.cobblemon.use_healing_machine": "てん てん てれれん",
|
||||
"advancements.cobblemon.plant_all_apricorn_sprouts.description": "あらゆる色のぼんぐりの新芽を植える",
|
||||
"advancements.cobblemon.plant_all_apricorn_sprouts": "ぼんぐりころころぼんぐりこ",
|
||||
"advancements.cobblemon.use_mint.description": "ミントを使ってポケモンのステータスの得意不得意を変える",
|
||||
"advancements.cobblemon.use_mint": "結果にコミント!",
|
||||
"advancements.cobblemon.brew_medicinal_brew.description": "クスリソウを煎じて、薬の基礎となるものを作る",
|
||||
"advancements.cobblemon.brew_medicinal_brew": "ネギらうおくすり",
|
||||
"advancements.cobblemon.brew_all_potions.description": "クスリソウを使って、ありとあらゆるアイテムを作成する",
|
||||
"advancements.cobblemon.brew_all_potions": "一番良いのを頼む",
|
||||
"advancements.cobblemon.use_exp_candy.description": "ポケモンにけいけんアメを使う",
|
||||
"advancements.cobblemon.use_exp_candy": "甘美な経験"
|
||||
}
|
||||
|
||||
@@ -5936,14 +5936,14 @@
|
||||
"block.cobblemon.red_apricorn": "红球果",
|
||||
"block.cobblemon.yellow_apricorn": "黄球果",
|
||||
"block.cobblemon.lectern": "讲台",
|
||||
"cobblemon.fishing_bait_effects.nature.tooltip": "%1$s%%-%2$s↑性格出现率",
|
||||
"cobblemon.fishing_bait_effects.iv.tooltip": "%1$s%%-%2$s个体值+%3$s",
|
||||
"cobblemon.fishing_bait_effects.ev.tooltip": "%1$s%%-%2$s基础点数出现率",
|
||||
"cobblemon.fishing_bait_effects.bite_time.tooltip": "%1$s%% - 上钩时间缩短 %3$s%%",
|
||||
"cobblemon.fishing_bait_effects.gender_chance.tooltip": "%1$s%%-%2$s性别出现率",
|
||||
"cobblemon.fishing_bait_effects.level_raise.tooltip": "%1$s%% - 等级 +%3$s",
|
||||
"cobblemon.fishing_bait_effects.nature.tooltip": "%1$s%% - %2$s↑性格出现率",
|
||||
"cobblemon.fishing_bait_effects.iv.tooltip": "%1$s%% - %2$s个体值+%3$s",
|
||||
"cobblemon.fishing_bait_effects.ev.tooltip": "%1$s%% - %2$s基础点数出现率",
|
||||
"cobblemon.fishing_bait_effects.bite_time.tooltip": "%1$s%% - 上钩时间缩短%3$s%%",
|
||||
"cobblemon.fishing_bait_effects.gender_chance.tooltip": "%1$s%% - %2$s性别出现率",
|
||||
"cobblemon.fishing_bait_effects.level_raise.tooltip": "%1$s%% - 等级+%3$s",
|
||||
"cobblemon.fishing_bait_effects.tera.tooltip": "%1$s%% - 吸引 %2$s 太晶属性",
|
||||
"cobblemon.fishing_bait_effects.shiny_reroll.tooltip": "%1$s%% - 异色概率 ×%3$s",
|
||||
"cobblemon.fishing_bait_effects.shiny_reroll.tooltip": "%1$s%% - 发光概率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.ha_chance.tooltip": "%1$s%% - 隐藏特性出现率",
|
||||
"cobblemon.fishing_bait_effects.pokemon_chance.tooltip": "%1$s%% - 上钩一只宝可梦",
|
||||
"cobblemon.fishing_bait_effects.friendship.tooltip": "%1$s%% - 亲密度 +%3$s",
|
||||
@@ -6179,7 +6179,7 @@
|
||||
"cobblemon.species.ironjugulis.desc": "它与超自然杂志曾报道过的宝可梦很相似。报道中的宝可梦是爱上机器人的三首恶龙所生的孩子。",
|
||||
"cobblemon.species.pecharunt.desc": "会让对手吃下能提升欲望和能力的毒粘糕,然后通过锁链控制对手。",
|
||||
"cobblemon.ability.teraformzero.desc": "太乐巴戈斯变为星晶形态时,蕴藏在它身上的力量会将天气和场地的影响全部归零。",
|
||||
"cobblemon.subtitle.pokemon.shiny_shine": "被捕获的异色宝可梦闪闪发光",
|
||||
"cobblemon.subtitle.pokemon.shiny_shine": "被捕获的发光宝可梦闪闪发光",
|
||||
"cobblemon.battle.heal.bagitemrevive": "%1$s 恢复了活力!",
|
||||
"cobblemon.battle.detailschange.noice": "%1$s的样子发生了变化!",
|
||||
"cobblemon.battle.detailschange.eiscue": "%1$s的样子发生了变化!",
|
||||
@@ -6206,9 +6206,9 @@
|
||||
"cobblemon.ability.hospitality": "款待",
|
||||
"cobblemon.ability.poisonpuppeteer": "毒傀儡",
|
||||
"cobblemon.ability.supersweetsyrup": "甘露之蜜",
|
||||
"cobblemon.subtitle.pokemon.wild_shiny_shine": "野生的异色宝可梦!",
|
||||
"cobblemon.subtitle.pokemon.owned_shiny_ambient": "周围的异色宝可梦闪闪发光",
|
||||
"cobblemon.subtitle.pokemon.shiny_ambient": "野生的异色宝可梦闪闪发光!",
|
||||
"cobblemon.subtitle.pokemon.wild_shiny_shine": "野生的发光宝可梦!",
|
||||
"cobblemon.subtitle.pokemon.owned_shiny_ambient": "周围的发光宝可梦闪闪发光",
|
||||
"cobblemon.subtitle.pokemon.shiny_ambient": "野生的发光宝可梦闪闪发光!",
|
||||
"cobblemon.battle.withdraw.self": "%1$s ,回来!",
|
||||
"cobblemon.battle.withdraw.other": "%1$s换下了%2$s!",
|
||||
"cobblemon.type.suffix": "%1$s 属性",
|
||||
@@ -6399,34 +6399,34 @@
|
||||
"cobblemon.pokerod.remove": "右键移除饵料",
|
||||
"item.cobblemon.galarica_nuts": "伽勒豆蔻枝",
|
||||
"item.cobblemon.npc_editor": "NPC的训练家证",
|
||||
"item.cobblemon.dragon_scale.tooltip": "在连接交换时携带,可使海刺龙进化为刺龙王",
|
||||
"item.cobblemon.link_cable.tooltip": "使需要通过交换进化的宝可梦进化",
|
||||
"item.cobblemon.dragon_scale.tooltip": "当海刺龙携带进行连接交换时,可使其进化为刺龙王",
|
||||
"item.cobblemon.link_cable.tooltip": "可使需要连接交换的宝可梦进化",
|
||||
"item.cobblemon.kings_rock.tooltip_2": "在交换时携带,可使蚊香君进化为蚊香蛙皇,呆呆兽进化为呆呆王",
|
||||
"item.cobblemon.metal_coat.tooltip_1": "携带后,钢属性的招式威力就会增强",
|
||||
"item.cobblemon.kings_rock.tooltip_1": "携带该道具的宝可梦造成伤害时,有概率使目标陷入畏缩状态",
|
||||
"item.cobblemon.metal_coat.tooltip_2": "在连接交换时携带,可使大岩蛇进化为大钢蛇,使飞天螳螂进化为巨钳螳螂",
|
||||
"item.cobblemon.upgrade.tooltip": "在连接交换时携带,可使多边兽进化为多边兽2型",
|
||||
"item.cobblemon.dubious_disc.tooltip": "在连接交换时携带,可使多边兽2型进化为多边兽乙型",
|
||||
"item.cobblemon.metal_coat.tooltip_2": "在连接交换时携带,可使大岩蛇进化为大钢蛇,飞天螳螂进化为巨钳螳螂",
|
||||
"item.cobblemon.upgrade.tooltip": "当多边兽携带进行连接交换时,可使其进化为多边兽2型",
|
||||
"item.cobblemon.dubious_disc.tooltip": "当多边兽2型携带进行连接交换时,可使其进化为多边兽乙型",
|
||||
"item.cobblemon.deep_sea_scale.tooltip_1": "大幅提升珍珠贝的特防",
|
||||
"item.cobblemon.deep_sea_scale.tooltip_2": "在连接交换时携带,可使珍珠贝进化为樱花鱼",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_2": "在连接交换时携带,可使珍珠贝进化为猎斑鱼",
|
||||
"item.cobblemon.electirizer.tooltip": "在连接交换时携带,可使电击兽进化为电击魔兽",
|
||||
"item.cobblemon.magmarizer.tooltip": "当鸭嘴火兽携带进行连接进化时,会使其进化为鸭嘴炎兽",
|
||||
"item.cobblemon.oval_stone.tooltip": "当小福蛋携带进行连接交换时,会使其进化为吉利蛋",
|
||||
"item.cobblemon.protector.tooltip": "当钻角犀兽携带进行连接交换时,会使其进化为超甲狂犀",
|
||||
"item.cobblemon.prism_scale.tooltip": "当丑丑鱼携带进行连接交换时,会使其进化为美纳斯",
|
||||
"item.cobblemon.sachet.tooltip": "当粉香香携带进行连接交换时,会使其进化为芳香精",
|
||||
"item.cobblemon.whipped_dream.tooltip": "当绵绵泡芙携带进行连接交换时,会使其进化为胖甜妮",
|
||||
"item.cobblemon.love_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的爱心形态",
|
||||
"item.cobblemon.berry_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的野莓形态",
|
||||
"item.cobblemon.flower_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的花朵形态",
|
||||
"item.cobblemon.ribbon_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的蝴蝶结形态",
|
||||
"item.cobblemon.cracked_pot.tooltip": "当对赝品来悲茶使用时,会使其进化为怖思壶",
|
||||
"item.cobblemon.unremarkable_teacup.tooltip": "当对斯魔茶(冒牌货的样子)使用时,会使其进化为来悲粗茶(凡作的样子)",
|
||||
"item.cobblemon.sweet_apple.tooltip": "当对啃果虫使用时,会使其进化为丰蜜龙",
|
||||
"item.cobblemon.tart_apple.tooltip": "当对啃果虫使用时,会使其进化为苹裹龙",
|
||||
"item.cobblemon.galarica_wreath.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,会使其进化为呆呆王(伽勒尔的样子)",
|
||||
"item.cobblemon.black_augurite.tooltip": "当对飞天螳螂使用,会使其进化为劈斧螳螂",
|
||||
"item.cobblemon.deep_sea_scale.tooltip_2": "当珍珠贝携带进行连接交换时,可使其进化为樱花鱼",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_2": "当珍珠贝携带进行连接交换时,可使其进化为猎斑鱼",
|
||||
"item.cobblemon.electirizer.tooltip": "当电击兽携带进行连接交换时,可使其进化为电击魔兽",
|
||||
"item.cobblemon.magmarizer.tooltip": "当鸭嘴火兽携带进行连接交换时,可使其进化为鸭嘴炎兽",
|
||||
"item.cobblemon.oval_stone.tooltip": "当小福蛋携带并处于白天时,可使其进化为吉利蛋",
|
||||
"item.cobblemon.protector.tooltip": "当钻角犀兽携带进行连接交换时,可使其进化为超甲狂犀",
|
||||
"item.cobblemon.prism_scale.tooltip": "当丑丑鱼携带进行连接交换时,可使其进化为美纳斯",
|
||||
"item.cobblemon.sachet.tooltip": "当粉香香携带进行连接交换时,可使其进化为芳香精",
|
||||
"item.cobblemon.whipped_dream.tooltip": "当绵绵泡芙携带进行连接交换时,可使其进化为胖甜妮",
|
||||
"item.cobblemon.love_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的爱心形态",
|
||||
"item.cobblemon.berry_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的野莓形态",
|
||||
"item.cobblemon.flower_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的花朵形态",
|
||||
"item.cobblemon.ribbon_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的蝴蝶结形态",
|
||||
"item.cobblemon.cracked_pot.tooltip": "当对赝品来悲茶使用时,可使其进化为怖思壶",
|
||||
"item.cobblemon.unremarkable_teacup.tooltip": "当对斯魔茶(冒牌货的样子)使用时,可使其进化为来悲粗茶(凡作的样子)",
|
||||
"item.cobblemon.sweet_apple.tooltip": "当对啃果虫使用时,可使其进化为丰蜜龙",
|
||||
"item.cobblemon.tart_apple.tooltip": "当对啃果虫使用时,可使其进化为苹裹龙",
|
||||
"item.cobblemon.galarica_wreath.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,可使其进化为呆呆王(伽勒尔的样子)",
|
||||
"item.cobblemon.black_augurite.tooltip": "当对飞天螳螂使用,可使其进化为劈斧螳螂",
|
||||
"item.cobblemon.moon_stone.tooltip": "进化特定宝可梦",
|
||||
"item.cobblemon.dawn_stone.tooltip": "进化特定宝可梦",
|
||||
"item.cobblemon.fire_stone.tooltip": "进化特定宝可梦",
|
||||
@@ -6480,8 +6480,8 @@
|
||||
"item.cobblemon.absorb_bulb.tooltip_2": "使用后消耗",
|
||||
"item.cobblemon.air_balloon.tooltip_1": "携带后,会浮在空中",
|
||||
"item.cobblemon.assault_vest.tooltip": "虽然携带后特防会提高,但会无法使出变化招式",
|
||||
"item.cobblemon.auspicious_armor.tooltip": "当对炭小侍使用时,会使其进化为红莲铠骑",
|
||||
"item.cobblemon.malicious_armor.tooltip": "当对炭小侍使用时,会使其进化为苍炎刃鬼",
|
||||
"item.cobblemon.auspicious_armor.tooltip": "当对炭小侍使用时,可使其进化为红莲铠骑",
|
||||
"item.cobblemon.malicious_armor.tooltip": "当对炭小侍使用时,可使其进化为苍炎刃鬼",
|
||||
"item.cobblemon.binding_band.tooltip": "携带后,绑紧招式的威力会变强",
|
||||
"item.cobblemon.black_belt.tooltip": "携带后,格斗属性的招式威力就会提高",
|
||||
"item.cobblemon.black_sludge.tooltip": "携带后,毒属性的宝可梦会缓缓回复HP。其他属性的话,HP则会减少",
|
||||
@@ -6532,7 +6532,7 @@
|
||||
"item.cobblemon.shed_shell.tooltip": "携带后,必定可以和后备的宝可梦进行替换",
|
||||
"item.cobblemon.shell_bell.tooltip": "携带后,攻击对手并造成伤害时,能回复少量HP",
|
||||
"item.cobblemon.shell_helmet": "硬壳头盔",
|
||||
"item.cobblemon.shell_helmet.tooltip": "当对盖盖虫使用时,会使其进化为骑士蜗牛",
|
||||
"item.cobblemon.shell_helmet.tooltip": "当对盖盖虫使用时,可使其进化为骑士蜗牛",
|
||||
"item.cobblemon.silver_powder.tooltip": "携带后,虫属性的招式威力就会提高",
|
||||
"item.cobblemon.soft_sand.tooltip": "携带后,地面属性的招式威力就会提高",
|
||||
"item.cobblemon.soothe_bell.tooltip": "携带后,会变得容易和训练家亲密",
|
||||
@@ -6604,13 +6604,13 @@
|
||||
"item.cobblemon.flying_gem.tooltip_1": "携带后,飞行属性的招式威力会增强一次",
|
||||
"item.cobblemon.flying_gem.tooltip_2": "使用后消耗",
|
||||
"block.cobblemon.big_root.tooltip": "携带后,吸取HP的招式可以比平时更多地回复自己的HP",
|
||||
"item.cobblemon.clover_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的幸运草形态",
|
||||
"item.cobblemon.clover_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的幸运草形态",
|
||||
"item.cobblemon.water_stone.tooltip": "进化特定宝可梦",
|
||||
"item.cobblemon.jolly_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为爽朗性格",
|
||||
"item.cobblemon.cell_battery.tooltip_1": "携带它的宝可梦如果受到电属性招式的伤害,攻击就会提高",
|
||||
"item.cobblemon.dragon_fang.tooltip": "携带后,龙属性的招式威力就会提高",
|
||||
"item.cobblemon.eject_button.tooltip_1": "携带它的宝可梦如果受到招式的伤害,就能逃脱战斗",
|
||||
"item.cobblemon.razor_fang.tooltip_2": "当天蝎携带在夜晚进行等级升级时,会使其进化为天蝎王",
|
||||
"item.cobblemon.razor_fang.tooltip_2": "当天蝎携带在夜晚进行等级升级时,可使其进化为天蝎王",
|
||||
"item.cobblemon.ring_target.tooltip": "携带后,原本因属性相克关系而无效的招式现在会变得能够击中自己",
|
||||
"item.cobblemon.wise_glasses.tooltip": "携带后,特殊招式的威力就会少量提高",
|
||||
"item.cobblemon.power_bracer.tooltip": "携带后,在战斗中获得经验值时,会获得8点攻击基础点数",
|
||||
@@ -6618,9 +6618,9 @@
|
||||
"item.cobblemon.x_special_defence.tooltip": "在战斗中使用时,会使目标的特防提升一级",
|
||||
"item.cobblemon.full_heal.tooltip": "治愈一只宝可梦的所有异常状态",
|
||||
"item.cobblemon.paralyze_heal.tooltip": "治愈一只宝可梦的麻痹状态",
|
||||
"item.cobblemon.reaper_cloth.tooltip": "当彷徨夜灵携带进行连接交换时,会使其进化为黑夜魔灵",
|
||||
"item.cobblemon.masterpiece_teacup.tooltip": "当对斯魔茶(高档货的样子)使用时,会使其进化为来悲粗茶(杰作的样子)",
|
||||
"item.cobblemon.galarica_cuff.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,会使其进化为呆壳兽(伽勒尔的样子)",
|
||||
"item.cobblemon.reaper_cloth.tooltip": "当彷徨夜灵携带进行连接交换时,可使其进化为黑夜魔灵",
|
||||
"item.cobblemon.masterpiece_teacup.tooltip": "当对斯魔茶(高档货的样子)使用时,可使其进化为来悲粗茶(杰作的样子)",
|
||||
"item.cobblemon.galarica_cuff.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,可使其进化为呆壳兽(伽勒尔的样子)",
|
||||
"item.cobblemon.ability_capsule.tooltip": "当对宝可梦使用后,会使其特性改变为另一种常见特性",
|
||||
"item.cobblemon.lonely_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为怕寂寞性格",
|
||||
"item.cobblemon.brave_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为勇敢性格",
|
||||
@@ -6636,13 +6636,13 @@
|
||||
"item.cobblemon.burn_heal.tooltip": "治愈一只宝可梦的灼伤状态",
|
||||
"item.cobblemon.dragon_gem.tooltip_2": "使用后消耗",
|
||||
"item.cobblemon.ground_gem.tooltip_1": "携带后,地面属性的招式威力会增强一次",
|
||||
"item.cobblemon.peat_block.tooltip": "当在满月对圈圈熊使用时,会使其进化为月月熊",
|
||||
"item.cobblemon.strawberry_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的草莓形态",
|
||||
"item.cobblemon.chipped_pot.tooltip": "当对真品来悲茶使用时,会使其进化为怖思壶",
|
||||
"item.cobblemon.peat_block.tooltip": "当在满月对圈圈熊使用时,可使其进化为月月熊",
|
||||
"item.cobblemon.strawberry_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的草莓形态",
|
||||
"item.cobblemon.chipped_pot.tooltip": "当对真品来悲茶使用时,可使其进化为怖思壶",
|
||||
"item.cobblemon.focus_band.tooltip": "携带后,即便受到可能会导致昏厥的招式,有时也能仅以1HP撑过去",
|
||||
"item.cobblemon.light_clay.tooltip": "携带后,使出像光墙和反射壁一样的保护招式时,效果会比平时持续得更长",
|
||||
"item.cobblemon.red_card.tooltip_1": "携带后,能让对自己造成伤害的对手退场",
|
||||
"item.cobblemon.medicinal_leek.tooltip_1": "能用来调制成药品",
|
||||
"item.cobblemon.medicinal_leek.tooltip_1": "可调制成药品",
|
||||
"item.cobblemon.remedy.tooltip": "使一只宝可梦回复20HP,同时小幅降低它的亲密度",
|
||||
"item.cobblemon.fine_remedy.tooltip": "使一只宝可梦回复60HP,同时小幅降低它的亲密度",
|
||||
"item.cobblemon.superb_remedy.tooltip": "使一只宝可梦回复120HP,同时小幅降低它的亲密度",
|
||||
@@ -6653,7 +6653,7 @@
|
||||
"item.cobblemon.ghost_gem.tooltip_1": "携带后,幽灵属性的招式威力会增强一次",
|
||||
"item.cobblemon.rock_gem.tooltip_1": "携带后,岩石属性的招式威力会增强一次",
|
||||
"item.cobblemon.psychic_gem.tooltip_2": "使用后消耗",
|
||||
"item.cobblemon.star_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的星星形态",
|
||||
"item.cobblemon.star_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的星星形态",
|
||||
"item.cobblemon.relaxed_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为悠闲性格",
|
||||
"item.cobblemon.quiet_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为冷静性格",
|
||||
"item.cobblemon.careful_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为慎重性格",
|
||||
@@ -6678,8 +6678,8 @@
|
||||
"item.cobblemon.bug_gem.tooltip_1": "携带后,虫属性的招式威力会增强一次",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_1": "大幅提升珍珠贝的特攻",
|
||||
"cobblemon.fishing.no_bite": "甚至连一口都没有。",
|
||||
"cobblemon.fishing_bait_effects.typing.tooltip": "%1$s%%-%2$s属性出现率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.egg_group.tooltip": "%1$s%%-%2$s蛋群出现率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.typing.tooltip": "%1$s%% - %2$s属性出现率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.egg_group.tooltip": "%1$s%% - %2$s蛋群出现率×%3$s",
|
||||
"cobblemon.egg_group.monster": "怪兽",
|
||||
"cobblemon.egg_group.water_1": "水中1",
|
||||
"cobblemon.egg_group.bug": "虫",
|
||||
@@ -6712,7 +6712,7 @@
|
||||
"cobblemon.ui.interact.ride": "骑乘",
|
||||
"cobblemon.ui.interact.request_already_expired": "该请求已过期!",
|
||||
"cobblemon.ui.pokedex.search.search_by": "搜索 %1$s 中",
|
||||
"cobblemon.ui.pokedex.search.type.species": "物种名称",
|
||||
"cobblemon.ui.pokedex.search.type.species": "宝可梦名称",
|
||||
"cobblemon.ui.pokedex.search.type.abilities": "特性",
|
||||
"cobblemon.ui.pokedex.search.type.drops": "掉落物",
|
||||
"cobblemon.cosmetic.held_logs.crimson": "绯红菌柄",
|
||||
@@ -6911,10 +6911,10 @@
|
||||
"cobblemon.config.ui.display_entity_name_label": "显示宝可梦的名字",
|
||||
"cobblemon.config.ui.display_entity_level_label": "显示宝可梦的等级",
|
||||
"cobblemon.config.ui.display_entity_labels_when_crouching_only.tooltip": "控制是否只在蹲下时显示宝可梦的标签。",
|
||||
"cobblemon.config.ui.shiny_rate": "异色概率",
|
||||
"cobblemon.config.ui.shiny_rate.tooltip": "生成的宝可梦为异色的概率。若设为0,则生成的宝可梦不会出现异色。该概率以1/x的形式计算。",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance": "异色粒子的显示距离",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance.tooltip": "宝可梦异色粒子效果开始显示的距离。",
|
||||
"cobblemon.config.ui.shiny_rate": "发光概率",
|
||||
"cobblemon.config.ui.shiny_rate.tooltip": "生成发光宝可梦的概率。若设为0,则发光宝可梦不会生成。该概率以1/x的形式计算。",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance": "发光粒子的显示距离",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance.tooltip": "宝可梦发光粒子效果开始显示的距离。",
|
||||
"cobblemon.config.ui.capture_calculator": "捕获计算器",
|
||||
"cobblemon.config.ui.player_damage_pokemon": "玩家攻击宝可梦",
|
||||
"cobblemon.config.ui.player_damage_pokemon.tooltip": "控制玩家是否可以攻击一般实体一样攻击宝可梦。",
|
||||
@@ -7073,7 +7073,7 @@
|
||||
"cobblemon.battle.block.aromaveil": "%1$s 正受到芳香幕的保护!",
|
||||
"cobblemon.species.mimikyu-busted.desc": "因正身就要暴露而很悲痛。绝不原谅折断了它脖子的对手,会向对方报仇。",
|
||||
"item.cobblemon.syrupy_apple": "蜜汁苹果",
|
||||
"item.cobblemon.syrupy_apple.tooltip": "当啃果虫使用时,会使其进化为裹蜜虫",
|
||||
"item.cobblemon.syrupy_apple.tooltip": "当啃果虫使用时,可使其进化为裹蜜虫",
|
||||
"cobblemon.command.unlockablepcboxwallpaper.invalid-wallpaper": "无效的壁纸标识",
|
||||
"cobblemon.ui.pc.wallpaper": "壁纸",
|
||||
"cobblemon.ui.pc.filter": "筛选",
|
||||
@@ -8577,9 +8577,9 @@
|
||||
"cobblemon.ui.pokedex.info.form.dartrix-hisuibias": "洗翠趋异的样子",
|
||||
"block.cobblemon.potted_saccharine_sapling": "蜜露树苗盆栽",
|
||||
"item.cobblemon.saccharine_sapling": "蜜露树苗",
|
||||
"item.cobblemon.metal_alloy.tooltip": "当对铝钢龙使用时,会使其进化为铝钢桥龙",
|
||||
"item.cobblemon.metal_alloy.tooltip": "当对铝钢龙使用时,可使其进化为铝钢桥龙",
|
||||
"item.cobblemon.health_mochi": "体力粘糕",
|
||||
"item.cobblemon.scroll_of_waters.tooltip": "当对熊徒弟使用时,会使其进化为武道熊师(连击流)",
|
||||
"item.cobblemon.scroll_of_waters.tooltip": "当对熊徒弟使用时,可使其进化为武道熊师(连击流)",
|
||||
"item.cobblemon.potato_mochi": "马铃薯粘糕",
|
||||
"item.cobblemon.aprijuice_black": "黑球果汁",
|
||||
"item.cobblemon.health_mochi.tooltip": "提升宝可梦的HP基础点数4点",
|
||||
@@ -8592,7 +8592,7 @@
|
||||
"item.cobblemon.metal_alloy": "复合金属",
|
||||
"item.cobblemon.scroll_of_darkness": "恶之挂轴",
|
||||
"item.cobblemon.scroll_of_waters": "水之挂轴",
|
||||
"item.cobblemon.scroll_of_darkness.tooltip": "当对熊徒弟使用时,会使其进化为武道熊师(一击流)",
|
||||
"item.cobblemon.scroll_of_darkness.tooltip": "当对熊徒弟使用时,可使其进化为武道熊师(一击流)",
|
||||
"item.cobblemon.fried_rice": "炒饭",
|
||||
"item.cobblemon.candied_apple": "蜜饯苹果",
|
||||
"item.cobblemon.moomoo_milk": "哞哞鲜奶",
|
||||
@@ -8673,13 +8673,13 @@
|
||||
"item.cobblemon.ponigiri": "宝可饭团",
|
||||
"item.cobblemon.poke_puff.frosted": "珍奇 %s 宝芙蕾",
|
||||
"tooltip.cobblemon.poke_puff.nature.neutral": "中性",
|
||||
"item.cobblemon.health_candy.tooltip_1": "提升宝可梦HP的有效个体值1点",
|
||||
"item.cobblemon.brittle_candy.tooltip_1": "降低宝可梦防御的有效个体值1点",
|
||||
"item.cobblemon.numb_candy.tooltip_1": "降低宝可梦特攻的有效个体值1点",
|
||||
"item.cobblemon.health_candy.tooltip_1": "提升宝可梦的HP有效个体值1点",
|
||||
"item.cobblemon.brittle_candy.tooltip_1": "降低宝可梦的防御有效个体值1点",
|
||||
"item.cobblemon.numb_candy.tooltip_1": "降低宝可梦的特攻有效个体值1点",
|
||||
"cobblemon.ui.info.gender": "性别",
|
||||
"item.cobblemon.courage_candy.tooltip_1": "提升宝可梦特防的有效个体值1点",
|
||||
"item.cobblemon.courage_candy.tooltip_1": "提升宝可梦的特防有效个体值1点",
|
||||
"cobblemon.command.behaviouredit.non_scriptable": "您并没有看着一个可执行MoLang脚本的实体。",
|
||||
"cobblemon.command.pcsearch.tooltip.shiny": "这只宝可梦已经是异色了!",
|
||||
"cobblemon.command.pcsearch.tooltip.shiny": "这只是发光宝可梦!",
|
||||
"cobblemon.command.pcsearch.entry": "- %1$s %2$s",
|
||||
"block.cobblemon.campfire": "营火",
|
||||
"block.cobblemon.campfire_pot_black": "黑色营火锅",
|
||||
@@ -8711,20 +8711,20 @@
|
||||
"cobblemon.tooltip.poke_puff.friendship_effects": "亲密度影响",
|
||||
"item.cobblemon.health_candy": "元气糖果",
|
||||
"item.cobblemon.mighty_candy": "力量糖果",
|
||||
"item.cobblemon.mighty_candy.tooltip_1": "提升宝可梦攻击的有效个体值1点",
|
||||
"item.cobblemon.mighty_candy.tooltip_1": "提升宝可梦的攻击有效个体值1点",
|
||||
"item.cobblemon.tough_candy": "守护糖果",
|
||||
"item.cobblemon.tough_candy.tooltip_1": "提升宝可梦防御的有效个体值1点",
|
||||
"item.cobblemon.tough_candy.tooltip_1": "提升宝可梦的防御有效个体值1点",
|
||||
"item.cobblemon.smart_candy": "知识糖果",
|
||||
"item.cobblemon.smart_candy.tooltip_1": "提升宝可梦特攻的有效个体值1点",
|
||||
"item.cobblemon.smart_candy.tooltip_1": "提升宝可梦的特攻有效个体值1点",
|
||||
"item.cobblemon.courage_candy": "心灵糖果",
|
||||
"item.cobblemon.quick_candy": "敏捷糖果",
|
||||
"item.cobblemon.quick_candy.tooltip_1": "提升宝可梦速度的有效个体值1点",
|
||||
"item.cobblemon.quick_candy.tooltip_1": "提升宝可梦的速度有效个体值1点",
|
||||
"item.cobblemon.sickly_candy": "虚弱糖果",
|
||||
"item.cobblemon.sickly_candy.tooltip_1": "降低宝可梦HP的有效个体值1点",
|
||||
"item.cobblemon.weak_candy.tooltip_1": "降低宝可梦攻击的有效个体值1点",
|
||||
"item.cobblemon.sickly_candy.tooltip_1": "降低宝可梦的HP有效个体值1点",
|
||||
"item.cobblemon.weak_candy.tooltip_1": "降低宝可梦的攻击有效个体值1点",
|
||||
"item.cobblemon.weak_candy": "软弱糖果",
|
||||
"item.cobblemon.coward_candy.tooltip_1": "降低宝可梦特防的有效个体值1点",
|
||||
"item.cobblemon.slow_candy.tooltip_1": "降低宝可梦速度的有效个体值1点",
|
||||
"item.cobblemon.coward_candy.tooltip_1": "降低宝可梦的特防有效个体值1点",
|
||||
"item.cobblemon.slow_candy.tooltip_1": "降低宝可梦的速度有效个体值1点",
|
||||
"item.cobblemon.brittle_candy": "脆弱糖果",
|
||||
"item.cobblemon.numb_candy": "迟钝糖果",
|
||||
"item.cobblemon.coward_candy": "胆怯糖果",
|
||||
@@ -9106,7 +9106,7 @@
|
||||
"item.cobblemon.eggant_berry": "子茄果",
|
||||
"cobblemon.entity.variable.look_at_entity_types.desc": "该实体将看向的实体类型。",
|
||||
"cobblemon.entity.variable.look_at_entity_types.name": "看向实体类型",
|
||||
"cobblemon.fishing_bait_effects.drops_reroll.tooltip": "%1$s%% - %3$s× 额外掉落",
|
||||
"cobblemon.fishing_bait_effects.drops_reroll.tooltip": "%1$s%% - %3$s×额外掉落",
|
||||
"cobblemon.requires_debug_keys": "必须在服务器上启用调试键才能使用此功能。",
|
||||
"cobblemon.ui.stats.blocks_traveled": "步数",
|
||||
"cobblemon.requires_permission": "你没有执行此操作的权限。",
|
||||
@@ -9213,5 +9213,131 @@
|
||||
"cobblemon.behaviour.defend_owner.desc": "在主人受到攻击时保护他们。",
|
||||
"stat.cobblemon.riding_land": "骑着宝可梦在陆地移动距离",
|
||||
"stat.cobblemon.riding_air": "骑着宝可梦在空中移动距离",
|
||||
"stat.cobblemon.riding_liquid": "骑着宝可梦在水域移动距离"
|
||||
"stat.cobblemon.riding_liquid": "骑着宝可梦在水域移动距离",
|
||||
"item.cobblemon.sweet_heart.tooltip": "非常甜腻的巧克力",
|
||||
"item.cobblemon.sweet_heart": "心形甜点",
|
||||
"item.cobblemon.technical_machine": "招式学习器",
|
||||
"item.cobblemon.blank_tm": "空白招式学习器",
|
||||
"block.cobblemon.deepslate_crystal_core": "深层水晶母岩",
|
||||
"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.ice_gem_block": "冰之宝石块",
|
||||
"block.cobblemon.fighting_gem_block": "格斗宝石块",
|
||||
"block.cobblemon.poison_gem_block": "毒之宝石块",
|
||||
"block.cobblemon.ground_gem_block": "地面宝石块",
|
||||
"block.cobblemon.flying_gem_block": "飞行宝石块",
|
||||
"block.cobblemon.psychic_gem_block": "超能力宝石块",
|
||||
"block.cobblemon.bug_gem_block": "虫之宝石块",
|
||||
"block.cobblemon.rock_gem_block": "岩石宝石块",
|
||||
"block.cobblemon.ghost_gem_block": "幽灵宝石块",
|
||||
"block.cobblemon.dragon_gem_block": "龙之宝石块",
|
||||
"block.cobblemon.dark_gem_block": "恶之宝石块",
|
||||
"block.cobblemon.steel_gem_block": "钢之宝石块",
|
||||
"block.cobblemon.fairy_gem_block": "妖精宝石块",
|
||||
"block.cobblemon.normal_gem_cluster": "一般宝石簇",
|
||||
"block.cobblemon.fire_gem_cluster": "火之宝石簇",
|
||||
"block.cobblemon.water_gem_cluster": "水之宝石簇",
|
||||
"block.cobblemon.electric_gem_cluster": "电之宝石簇",
|
||||
"block.cobblemon.grass_gem_cluster": "草之宝石簇",
|
||||
"block.cobblemon.ice_gem_cluster": "冰之宝石簇",
|
||||
"block.cobblemon.fighting_gem_cluster": "格斗宝石簇",
|
||||
"block.cobblemon.poison_gem_cluster": "毒之宝石簇",
|
||||
"block.cobblemon.ground_gem_cluster": "地面宝石簇",
|
||||
"block.cobblemon.flying_gem_cluster": "飞行宝石簇",
|
||||
"block.cobblemon.psychic_gem_cluster": "超能力宝石簇",
|
||||
"block.cobblemon.bug_gem_cluster": "虫之宝石簇",
|
||||
"block.cobblemon.rock_gem_cluster": "岩石宝石簇",
|
||||
"block.cobblemon.ghost_gem_cluster": "幽灵宝石簇",
|
||||
"block.cobblemon.dragon_gem_cluster": "龙之宝石簇",
|
||||
"block.cobblemon.dark_gem_cluster": "恶之宝石簇",
|
||||
"block.cobblemon.steel_gem_cluster": "钢之宝石簇",
|
||||
"block.cobblemon.fairy_gem_cluster": "妖精宝石簇",
|
||||
"cobblemon.item_class.technical_machine": "招式学习器",
|
||||
"block.cobblemon.damaged_monitor": "损坏的数据显示器",
|
||||
"block.cobblemon.tm_machine": "招式学习器机",
|
||||
"block.cobblemon.disc_shelf": "光盘架",
|
||||
"cobblemon.fishing_bait_effects.mark_chance.tooltip": "%1$s%% - 证章出现率+%3$s%%",
|
||||
"cobblemon.fishing_bait_effects.alpha_chance.tooltip": "%1$s%% - 头目宝可梦出现率",
|
||||
"cobblemon.fishing_bait_effects.size.tooltip": "%1$s%% - 体型%3$s%%",
|
||||
"cobblemon.technical_machine_effect_header": "招式学习器机信息:",
|
||||
"cobblemon.command.technicalmachine.invalid-tm": "无效招式学习器",
|
||||
"cobblemon.ui.generic.question_marks": "???",
|
||||
"cobblemon.container.tm_machine": "招式学习器机",
|
||||
"cobblemon.ui.edit.habitat": "栖息地编辑器",
|
||||
"cobblemon.ui.edit.habitat.mimic_id": "模仿方块ID",
|
||||
"cobblemon.ui.edit.habitat.level_range": "等级范围(最小—最大)",
|
||||
"cobblemon.ui.edit.habitat.mode": "模式:%s",
|
||||
"cobblemon.ui.edit.habitat.mode.activated": "已激活",
|
||||
"cobblemon.ui.edit.habitat.mode.natural": "自然",
|
||||
"cobblemon.ui.edit.habitat.trigger": "触发器:%s",
|
||||
"cobblemon.ui.edit.habitat.phase_number": "阶段数",
|
||||
"cobblemon.ui.edit.habitat.phase_order": "阶段顺序:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn_range": "生成范围(方块数)",
|
||||
"cobblemon.ui.edit.habitat.cancelled_range": "取消自然生成的范围(方块数)",
|
||||
"cobblemon.ui.edit.habitat.max_spawns": "最大生成数量(-1为无限)",
|
||||
"cobblemon.ui.edit.habitat.replace_spawns": "替换正常生成:%s",
|
||||
"cobblemon.ui.edit.habitat.influence_range": "影响范围(方块数)",
|
||||
"cobblemon.ui.edit.habitat.pool": "生成池:%s",
|
||||
"cobblemon.ui.edit.habitat.pool.custom": "自定义",
|
||||
"cobblemon.ui.edit.habitat.view_pool": "查看生成池",
|
||||
"cobblemon.ui.edit.habitat.edit_pool": "编辑生成池",
|
||||
"cobblemon.ui.edit.habitat.pool.title": "生成池编辑器",
|
||||
"cobblemon.ui.edit.habitat.pool.species": "宝可梦",
|
||||
"cobblemon.ui.edit.habitat.spawn.species_name": "宝可梦名称",
|
||||
"cobblemon.ui.edit.habitat.pool.levels": "等级",
|
||||
"cobblemon.ui.edit.habitat.pool.phases": "阶段",
|
||||
"cobblemon.ui.edit.habitat.pool.position": "位置",
|
||||
"cobblemon.ui.edit.habitat.pool.weight": "权重",
|
||||
"cobblemon.ui.edit.habitat.pool.bucket": "稀有度档位",
|
||||
"cobblemon.ui.edit.habitat.pool.add_spawn": "增加生成",
|
||||
"cobblemon.ui.edit.habitat.pool.back": "返回",
|
||||
"cobblemon.ui.edit.habitat.pool.select": "选择生成池",
|
||||
"cobblemon.ui.edit.habitat.spawn": "生成编辑器",
|
||||
"cobblemon.ui.edit.habitat.spawn.position_type": "位置类型:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn.bucket": "稀有度档位:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn.weight": "权重",
|
||||
"cobblemon.ui.edit.habitat.spawn.level_range": "等级范围(最小—最大)",
|
||||
"cobblemon.ui.edit.habitat.spawn.modifiers": "修饰词(例如:shiny gender=male)",
|
||||
"cobblemon.ui.edit.habitat.spawn.phases": "阶段(例如:1-3, 5)",
|
||||
"cobblemon.ui.edit.habitat.spawn.time_of_day": "时段",
|
||||
"cobblemon.ui.edit.habitat.spawn.time_of_day.value": "时段:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn.time_of_day.any": "所有",
|
||||
"cobblemon.ui.edit.habitat.spawn.min_light": "最低光照度(0-15,可选)",
|
||||
"cobblemon.ui.edit.habitat.spawn.max_light": "最高光照度(0-15, 可选)",
|
||||
"cobblemon.ui.edit.habitat.spawn.back": "返回",
|
||||
"cobblemon.ui.edit.habitat.validation.mimic": "模仿方块必须是被允许且有效的方块ID(查看 habitat_mimics.json)。",
|
||||
"cobblemon.ui.edit.habitat.validation.phases": "阶段数必须大于0。",
|
||||
"cobblemon.ui.edit.habitat.validation.level_range": "等级范围必须处于1到100之间,且最小值不能大于最大值。",
|
||||
"cobblemon.ui.edit.habitat.validation.spawn_range": "生成范围必须为0或更高。",
|
||||
"cobblemon.ui.edit.habitat.validation.cancelled_range": "被取消的自然生成范围必须为 -1(不取消)或在 0 到 64 之间。",
|
||||
"cobblemon.ui.edit.habitat.validation.max_spawns": "最大生成数必须是-1或更高。",
|
||||
"cobblemon.ui.edit.habitat.validation.influence_range": "影响范围必须为0或更高。",
|
||||
"cobblemon.ui.edit.habitat.validation.species": "必须为一个有效的宝可梦。",
|
||||
"cobblemon.ui.edit.habitat.validation.weight": "权重必须大于0。",
|
||||
"cobblemon.ui.edit.habitat.validation.modifiers": "修饰词的格式无效。",
|
||||
"cobblemon.ui.edit.habitat.validation.min_light": "最低光照度必须处于0到15之间。",
|
||||
"cobblemon.ui.edit.habitat.validation.max_light": "最高光照度必须处于0到15之间。",
|
||||
"cobblemon.ui.moves.learnset.tm.discovered": "发现了",
|
||||
"cobblemon.ui.moves.level": "等级提升",
|
||||
"cobblemon.ui.moves.egg": "蛋",
|
||||
"cobblemon.ui.moves.tm": "招式学习器",
|
||||
"cobblemon.ui.tm_machine.can_learn": "能学习",
|
||||
"cobblemon.ui.tm_machine.cannot_learn": "不能学",
|
||||
"cobblemon.ui.tm_machine.learned": "已学会",
|
||||
"cobblemon.tms.unknown_move": "未知招式",
|
||||
"cobblemon.tms.already_known": "%1$s 已经学会了 %2$s!",
|
||||
"cobblemon.tms.teach_move": "%1$s 学会了 %2$s!",
|
||||
"cobblemon.tms.cannot_learn": "%1$s 不能学习 %2$s!",
|
||||
"cobblemon.tms.unlock_tm": "你解锁了 %1$s 招式学习器!",
|
||||
"cobblemon.tms.new_tms_learned": "学会了新的招式学习器!",
|
||||
"cobblemon.tms.check_tmm": "查看招式学习器机",
|
||||
"cobblemon.ui.party.party_select_title": "更改同行队伍选中",
|
||||
"cobblemon.ui.party.party_select_description": "按下 %1$s/%2$s 或长按 %3$s 滑动鼠标滚轮。",
|
||||
"cobblemon.ui.category": "分类",
|
||||
"cobblemon.ui.pp": "PP",
|
||||
"cobblemon.ui.pokemon.alpha": "头目",
|
||||
"cobblemon.ui.edit.habitat.validation.phases_list": "阶段的格式必须使用有效的整数范围,例如:1-3或者1,3-5,6。"
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 242 B |
|
Before Width: | Height: | Size: 241 B |
|
Before Width: | Height: | Size: 459 B |
|
Before Width: | Height: | Size: 327 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 320 B |
|
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 272 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 309 B After Width: | Height: | Size: 316 B |
|
Before Width: | Height: | Size: 276 B After Width: | Height: | Size: 283 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 277 B After Width: | Height: | Size: 284 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 265 B After Width: | Height: | Size: 274 B |
@@ -8,19 +8,9 @@
|
||||
"texture": "cobblemon:textures/pokemon/0102_exeggcute/exeggcute_alola_bias.png",
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["alolan"],
|
||||
"model": "cobblemon:exeggcute_alola_bias.geo",
|
||||
"texture": "cobblemon:textures/pokemon/0102_exeggcute/exeggcute_alola_bias.png",
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "region-bias-alola"],
|
||||
"texture": "cobblemon:textures/pokemon/0102_exeggcute/exeggcute_alola_bias_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "alolan"],
|
||||
"texture": "cobblemon:textures/pokemon/0102_exeggcute/exeggcute_alola_bias_shiny.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |