forked from mirrors/cobblemon
Compare commits
29
Commits
main
...
evolution-tree
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dd92ca351 | ||
|
|
5359cc6c21 | ||
|
|
4421303d3b | ||
|
|
5b62f608da | ||
|
|
3840e9cdec | ||
|
|
5a2ac22bc2 | ||
|
|
7991662be6 | ||
|
|
8d41c7ae41 | ||
|
|
7768969186 | ||
|
|
0720ec3565 | ||
|
|
5d89d9beb6 | ||
|
|
8ee737ae53 | ||
|
|
886b960572 | ||
|
|
2d23e88ff3 | ||
|
|
aaa63ebc8a | ||
|
|
b35a82d89e | ||
|
|
8662d954e3 | ||
|
|
94ddfc8720 | ||
|
|
b9fcae2131 | ||
|
|
b848f2be3e | ||
|
|
f7019c943b | ||
|
|
c933eb2d71 | ||
|
|
09e9946eac | ||
|
|
082fcab8b0 | ||
|
|
7bdc8d03b1 | ||
|
|
485e4cfb22 | ||
|
|
4cd69c1b30 | ||
|
|
00148452aa | ||
|
|
598e08b8e6 |
@@ -10,7 +10,6 @@ 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
|
||||
@@ -55,6 +54,8 @@ 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)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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)
|
||||
}
|
||||
@@ -72,6 +72,40 @@ 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,6 +10,9 @@ 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
|
||||
@@ -40,6 +43,17 @@ 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 }
|
||||
@@ -49,4 +63,34 @@ 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())
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.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
|
||||
}
|
||||
+2
-2
@@ -21,7 +21,7 @@ import net.minecraft.world.entity.LivingEntity
|
||||
* @author Licious
|
||||
* @since March 21st, 2022
|
||||
*/
|
||||
interface EntityQueryRequirement : Requirement {
|
||||
abstract class 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 @@ interface EntityQueryRequirement : Requirement {
|
||||
* @param queriedEntity The [LivingEntity] that can be compared in context of a [Level].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean
|
||||
abstract fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean
|
||||
}
|
||||
+3
-3
@@ -23,7 +23,7 @@ import net.minecraft.world.entity.player.Player
|
||||
* @author Polymeta
|
||||
* @since May 6th, 2025
|
||||
*/
|
||||
interface OwnerQueryRequirement : Requirement {
|
||||
abstract class OwnerQueryRequirement : Requirement() {
|
||||
override fun check(pokemon: Pokemon): Boolean {
|
||||
val owner = pokemon.getOwnerEntity() ?: return false
|
||||
return when (owner) {
|
||||
@@ -44,7 +44,7 @@ interface OwnerQueryRequirement : Requirement {
|
||||
* @param owner The [Player] that owns this [Pokemon].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun checkPlayer(pokemon: Pokemon, owner: Player): Boolean
|
||||
abstract fun checkPlayer(pokemon: Pokemon, owner: Player): Boolean
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] & [NPCEntity] satisfies the requirement.
|
||||
@@ -55,5 +55,5 @@ interface OwnerQueryRequirement : Requirement {
|
||||
* @param owner The [NPCEntity] that owns this [Pokemon].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun checkNPC(pokemon: Pokemon, owner: NPCEntity): Boolean
|
||||
abstract fun checkNPC(pokemon: Pokemon, owner: NPCEntity): Boolean
|
||||
}
|
||||
+5
-2
@@ -11,6 +11,7 @@ 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..
|
||||
@@ -22,7 +23,7 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
* @author Licious
|
||||
* @since March 19th, 2022
|
||||
*/
|
||||
fun interface Requirement {
|
||||
abstract class Requirement {
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] satisfies the requirement.
|
||||
@@ -30,6 +31,8 @@ fun interface Requirement {
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun check(pokemon: Pokemon): Boolean
|
||||
abstract fun check(pokemon: Pokemon): Boolean
|
||||
|
||||
val pokedexIcon: ResourceLocation? = null
|
||||
val pokedexTooltip: String? = null
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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,6 +10,8 @@ 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
|
||||
|
||||
/**
|
||||
@@ -49,4 +51,25 @@ 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,6 +8,8 @@
|
||||
|
||||
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
|
||||
|
||||
/**
|
||||
@@ -42,4 +44,7 @@ enum class MoonPhase {
|
||||
fun ofWorld(world: Level): MoonPhase = VALUES[world.moonPhase]
|
||||
}
|
||||
|
||||
fun displayName(): MutableComponent {
|
||||
return lang("ui.moon_phase.${this.name.lowercase()}")
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -652,9 +652,9 @@ class FossilMultiblockStructure (
|
||||
|
||||
const val TICKS_PER_MINUTE = 1200
|
||||
const val MATERIAL_TO_START = 128
|
||||
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
|
||||
const val TIME_TO_TAKE = 100
|
||||
const val TIME_PER_STAGE = 100 / 8
|
||||
const val PROTECTION_TIME = 100
|
||||
|
||||
fun fromNbt(nbt: CompoundTag, registryLookup: HolderLookup.Provider, animAge: Int = -1, partialTicks: Float = 0f): FossilMultiblockStructure {
|
||||
val monitorPos = NbtUtils.readBlockPos(nbt, DataKeys.MONITOR_POS).get()
|
||||
|
||||
@@ -34,28 +34,27 @@ 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.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.gui.pokedex.widgets.*
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.widgets.evolutiontree.EvolutionTreeWidget
|
||||
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
|
||||
@@ -92,6 +91,10 @@ 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"),
|
||||
@@ -99,7 +102,8 @@ 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_moves.png"),
|
||||
cobblemonResource("textures/gui/pokedex/tab_evolution_tree.png"),
|
||||
)
|
||||
|
||||
val arrowUpIcon = cobblemonResource("textures/gui/pokedex/arrow_up.png")
|
||||
@@ -112,6 +116,8 @@ 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.
|
||||
*/
|
||||
@@ -130,6 +136,7 @@ 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"
|
||||
@@ -153,13 +160,29 @@ 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) {}
|
||||
@@ -178,7 +201,7 @@ class PokedexGUI private constructor(
|
||||
|
||||
//Info Widget
|
||||
if (::pokemonInfoWidget.isInitialized) removeWidget(pokemonInfoWidget)
|
||||
pokemonInfoWidget = PokemonInfoWidget(x + 180, y + 28) { newForm -> updateSelectedForm(newForm) }
|
||||
pokemonInfoWidget = PokemonInfoWidget(this, x + 180, y + 28) { newForm -> updateSelectedForm(newForm) }
|
||||
addRenderableWidget(pokemonInfoWidget)
|
||||
|
||||
setUpTabs()
|
||||
@@ -190,6 +213,10 @@ 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(),
|
||||
@@ -365,6 +392,14 @@ 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,
|
||||
@@ -400,7 +435,7 @@ class PokedexGUI private constructor(
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = tabSelectArrow,
|
||||
x = (x + 191.5F + (22F * tabInfoIndex)) / SCALE,
|
||||
x = (x + BASE_WIDTH / 2 + ICONS_ARROW_PADDING_AROUND + tabInfoIndex * ICONS_PADDING_BETWEEN) / SCALE,
|
||||
y = (y + 177) / SCALE,
|
||||
width = 12,
|
||||
height = 6,
|
||||
@@ -434,6 +469,7 @@ class PokedexGUI private constructor(
|
||||
val canDisplayEntry = true //selectedForm?.unlockForms
|
||||
|
||||
if (::pokemonInfoWidget.isInitialized
|
||||
&& pokemonInfoWidget.active
|
||||
&& !pokemonInfoWidget.suppressViewport
|
||||
&& pokemonInfoWidget.isWithinPortraitSpace(mouseX, mouseY)
|
||||
&& canDisplayEntry == true
|
||||
@@ -442,6 +478,12 @@ 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)
|
||||
@@ -453,14 +495,18 @@ 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) {
|
||||
if (isDragging && canDragRender && activeDragableElement == pokemonInfoWidget) {
|
||||
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)
|
||||
}
|
||||
@@ -551,6 +597,8 @@ class PokedexGUI private constructor(
|
||||
selectedForm = CobblemonClient.clientPokedexData.getEncounteredForms(newSelectedEntry).firstOrNull()
|
||||
|
||||
pokemonInfoWidget.setDexEntry(selectedEntry!!)
|
||||
pokemonNameWidget.update(selectedEntry!!)
|
||||
|
||||
displaytabInfoElement(tabInfoIndex)
|
||||
}
|
||||
|
||||
@@ -562,7 +610,7 @@ class PokedexGUI private constructor(
|
||||
|
||||
for (i in tabIcons.indices) {
|
||||
tabButtons.add(ScaledButton(
|
||||
x + 190.5F + (i * 22F),
|
||||
x + BASE_WIDTH / 2 + ICONS_PADDING_AROUND + i * ICONS_PADDING_BETWEEN,
|
||||
y + 181.5F,
|
||||
TAB_ICON_SIZE,
|
||||
TAB_ICON_SIZE,
|
||||
@@ -575,6 +623,8 @@ 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
|
||||
|
||||
@@ -626,6 +676,9 @@ 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) {
|
||||
@@ -700,6 +753,9 @@ 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)
|
||||
|
||||
+3
@@ -16,6 +16,8 @@ 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
|
||||
|
||||
@@ -36,6 +38,7 @@ 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
|
||||
|
||||
+72
-8
@@ -20,31 +20,95 @@ 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) {
|
||||
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,
|
||||
) {
|
||||
val poseStack = context.pose()
|
||||
val textWidth = Minecraft.getInstance().font.width(text.font(CobblemonResources.DEFAULT_LARGE))
|
||||
val tooltipWidth = textWidth + 6
|
||||
val textWidth = text.maxOf { Minecraft.getInstance().font.width(it.font(CobblemonResources.DEFAULT_LARGE)) }
|
||||
val tooltipPadding = 6
|
||||
val tooltipWidth = textWidth + tooltipPadding
|
||||
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 + 10
|
||||
tooltipTop + tooltipHeight * text.size - 1
|
||||
)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
)
|
||||
}
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class ScaledButton(
|
||||
var buttonX: Float,
|
||||
var buttonY: Float,
|
||||
buttonX: Float,
|
||||
buttonY: Float,
|
||||
val buttonWidth: Number,
|
||||
val buttonHeight: Number,
|
||||
var resource: ResourceLocation? = null,
|
||||
@@ -30,6 +30,18 @@ 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
|
||||
|
||||
|
||||
+27
-126
@@ -12,14 +12,13 @@ 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.entry.PokedexEntry
|
||||
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.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
|
||||
@@ -27,19 +26,14 @@ 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,
|
||||
@@ -135,13 +129,6 @@ 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 }
|
||||
}
|
||||
@@ -161,128 +148,42 @@ class EntriesScrollingWidget(val pX: Int, val pY: Int, val setPokedexEntry: (Pok
|
||||
hovered: Boolean,
|
||||
tickDelta: Float
|
||||
) {
|
||||
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()
|
||||
dexDataList.forEachIndexed { index, pokedexEntry ->
|
||||
val species = PokemonSpecies.getByIdentifier(pokedexEntry.speciesId)
|
||||
val discoveryLevel = discoveryLevelList[index]
|
||||
val firstVisibleForm = CobblemonClient.clientPokedexData.getEncounteredForms(dexData).firstOrNull()
|
||||
val shouldDrawMon = firstVisibleForm != null
|
||||
val firstVisibleForm = CobblemonClient.clientPokedexData.getEncounteredForms(pokedexEntry).firstOrNull()
|
||||
|
||||
if (species == null) {
|
||||
return@forEachIndexed
|
||||
}
|
||||
|
||||
val matrices = context.pose()
|
||||
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 startPosX = x + ((SCROLL_SLOT_SPACING + SCROLL_SLOT_SIZE) * index)
|
||||
val startPosY = y + SCROLL_SLOT_SPACING + 1
|
||||
|
||||
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")
|
||||
RenderablePokemon(species, aspectsToDraw)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
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
|
||||
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,
|
||||
)
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-65
@@ -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,8 +24,9 @@ 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.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
|
||||
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.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
|
||||
@@ -51,15 +52,13 @@ 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 pX: Int, val pY: Int, val updateForm: (PokedexForm) -> (Unit)) : SoundlessWidget(
|
||||
class PokemonInfoWidget(val parent: PokedexGUI, val pX: Int, val pY: Int, val updateForm: (PokedexForm) -> (Unit)) : SoundlessWidget(
|
||||
pX,
|
||||
pY,
|
||||
POKEMON_PORTRAIT_WIDTH,
|
||||
@@ -81,7 +80,6 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
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")
|
||||
|
||||
@@ -99,9 +97,6 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
|
||||
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 }
|
||||
}
|
||||
@@ -110,10 +105,6 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
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
|
||||
|
||||
@@ -194,7 +185,10 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
20,
|
||||
resource = buttonGenderMale,
|
||||
clickAction = {
|
||||
if (maleRatio > 0 && maleRatio < 1) gender = if (gender == Gender.MALE) Gender.FEMALE else Gender.MALE
|
||||
val maleRatio = parent.maleRatio
|
||||
if (maleRatio > 0 && maleRatio < 1) {
|
||||
parent.gender = if (parent.gender == Gender.MALE) Gender.FEMALE else Gender.MALE
|
||||
}
|
||||
updateAspects()
|
||||
}
|
||||
).apply { addWidget(this) }
|
||||
@@ -206,8 +200,8 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
20,
|
||||
buttonNone,
|
||||
clickAction = {
|
||||
if (seenShinyStates.size > 1) {
|
||||
shiny = !shiny
|
||||
if (parent.seenShinyStates.size > 1) {
|
||||
parent.shiny = !parent.shiny
|
||||
updateAspects()
|
||||
}
|
||||
}
|
||||
@@ -262,8 +256,7 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
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()
|
||||
@@ -276,37 +269,6 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
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,
|
||||
@@ -569,8 +531,6 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
|
||||
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
|
||||
@@ -596,23 +556,23 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
variationButtons.forEach { removeWidget(it.getWidget()) }
|
||||
variationButtons.clear()
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
val form = species.forms.find { it.name.equals(pokedexForm.displayForm, ignoreCase = true) } ?: species.standardForm
|
||||
maleRatio = form.maleRatio
|
||||
parent.maleRatio = form.maleRatio
|
||||
|
||||
val seenGenders = CobblemonClient.clientPokedexData.getSeenGenders(pokedexEntry, pokedexForm)
|
||||
val visibleGenders = seenGenders.filter { it != Gender.GENDERLESS }
|
||||
if (visibleGenders.isEmpty()) {
|
||||
gender = Gender.GENDERLESS
|
||||
parent.gender = Gender.GENDERLESS
|
||||
genderButton.visible = false
|
||||
genderButton.active = false
|
||||
} else {
|
||||
gender = visibleGenders.first()
|
||||
parent.gender = visibleGenders.first()
|
||||
genderButton.visible = true
|
||||
genderButton.active = visibleGenders.size > 1
|
||||
}
|
||||
@@ -691,8 +651,8 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
return
|
||||
}
|
||||
|
||||
genderButton.resource = if (gender == Gender.FEMALE) buttonGenderFemale else buttonGenderMale
|
||||
shinyButton.resource = if (shiny) buttonShiny else buttonNone
|
||||
genderButton.resource = if (parent.gender == Gender.FEMALE) buttonGenderFemale else buttonGenderMale
|
||||
shinyButton.resource = if (parent.shiny) buttonShiny else buttonNone
|
||||
|
||||
val species = currentEntry?.speciesId?.let { PokemonSpecies.getByIdentifier(it) }
|
||||
if (species != null) {
|
||||
@@ -701,12 +661,14 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
|
||||
updateType(species, form)
|
||||
|
||||
val aspects = mutableSetOf<String>()
|
||||
if (shiny) aspects.add(SHINY_ASPECT.aspect)
|
||||
val aspects = parent.aspects
|
||||
aspects.clear()
|
||||
|
||||
if (gender == Gender.FEMALE) {
|
||||
if (parent.shiny) aspects.add(SHINY_ASPECT.aspect)
|
||||
|
||||
if (parent.gender == Gender.FEMALE) {
|
||||
aspects.add("female")
|
||||
} else if (gender == Gender.MALE) {
|
||||
} else if (parent.gender == Gender.MALE) {
|
||||
aspects.add("male")
|
||||
}
|
||||
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
+552
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
* 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>
|
||||
}
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -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"
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
+1
-1
@@ -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())
|
||||
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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 = ""
|
||||
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
|
||||
+1
-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"
|
||||
}
|
||||
|
||||
+1
-1
@@ -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"
|
||||
}
|
||||
|
||||
@@ -1349,6 +1349,8 @@
|
||||
"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",
|
||||
@@ -1460,6 +1462,59 @@
|
||||
"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",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 242 B |
Binary file not shown.
|
After Width: | Height: | Size: 241 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 459 B |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 327 B |
Reference in New Issue
Block a user