forked from mirrors/cobblemon
Compare commits
1
Commits
1.7.2
...
moves-tooltips
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1986cb480b |
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves
|
||||
|
||||
enum class MoveEffectiveness(val showdownId: Int, val multiplier: Double) {
|
||||
NORMAL(0, 1.0),
|
||||
WEAKNESS(1, 2.0),
|
||||
RESISTANCE(2, 0.5),
|
||||
IMMUNITY(3, 0.0);
|
||||
|
||||
companion object {
|
||||
fun of(showdownId: Int): MoveEffectiveness {
|
||||
return entries.find { it.showdownId == showdownId }
|
||||
?: throw IllegalArgumentException("Unknown MoveEffectiveness: $showdownId")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves
|
||||
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
|
||||
object TypeChart {
|
||||
private val movesEffectiveness = mutableMapOf<ElementalType, MutableMap<ElementalType, MoveEffectiveness>>()
|
||||
|
||||
fun load() {
|
||||
movesEffectiveness.clear()
|
||||
|
||||
val typeChartJson = ShowdownService.service.getTypeChart()
|
||||
typeChartJson.keySet().forEach { type ->
|
||||
val defenderType = ElementalTypes.get(type) ?: return@forEach
|
||||
|
||||
val moveTypes = typeChartJson.get(type).asJsonObject.get("damageTaken").asJsonObject
|
||||
moveTypes.keySet().forEach innerLoop@ {
|
||||
val moveType = ElementalTypes.get(it) ?: return@innerLoop
|
||||
val moveEffectiveness = moveTypes.get(it).asInt
|
||||
|
||||
val defenderMap = movesEffectiveness.getOrPut(moveType) { mutableMapOf() }
|
||||
defenderMap[defenderType] = MoveEffectiveness.of(moveEffectiveness)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMoveEffectiveness(moveType: ElementalType, defenderTypes: List<ElementalType?>): Double {
|
||||
var multiplier = 1.0
|
||||
defenderTypes.filterNotNull().forEach {
|
||||
multiplier *= getMoveEffectiveness(moveType, it).multiplier
|
||||
}
|
||||
|
||||
return multiplier
|
||||
}
|
||||
|
||||
private fun getMoveEffectiveness(moveType: ElementalType, defenderType: ElementalType): MoveEffectiveness {
|
||||
return movesEffectiveness[moveType]?.get(defenderType) ?: throw IllegalArgumentException("Unknown effectiveness type: $moveType $defenderType")
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.api.drop.ItemDropMethod
|
||||
import com.cobblemon.mod.common.api.entity.EntityDimensionsAdapter
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.TypeChart
|
||||
import com.cobblemon.mod.common.api.moves.adapters.MoveTemplateAdapter
|
||||
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffect
|
||||
import com.cobblemon.mod.common.api.pokemon.effect.adapter.ShoulderEffectAdapter
|
||||
@@ -125,6 +126,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
it.indicateSpeciesInitialized()
|
||||
// Reload this with the mod
|
||||
CobblemonHeldItemManager.load()
|
||||
TypeChart.load()
|
||||
Cobblemon.LOGGER.info("Loaded {} Pokémon species", this.speciesByIdentifier.size)
|
||||
this.observable.emit(this)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.battles.runner
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.runner.graal.GraalShowdownService
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
@@ -30,6 +31,7 @@ interface ShowdownService {
|
||||
fun getAbilityIds(): JsonArray
|
||||
fun getMoves(): JsonArray
|
||||
fun getItemIds(): JsonArray
|
||||
fun getTypeChart(): JsonObject
|
||||
fun registerSpecies()
|
||||
fun registerBagItems()
|
||||
fun indicateSpeciesInitialized() {}
|
||||
@@ -38,4 +40,4 @@ interface ShowdownService {
|
||||
companion object {
|
||||
val service: ShowdownService by lazy { GraalShowdownService() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URI
|
||||
@@ -152,6 +153,12 @@ class GraalShowdownService : ShowdownService {
|
||||
return gson.fromJson(arrayResult, JsonArray::class.java)
|
||||
}
|
||||
|
||||
override fun getTypeChart(): JsonObject {
|
||||
val getCobbledItemIdsFn = context.getBindings("js").getMember("getTypeChart")
|
||||
val arrayResult = getCobbledItemIdsFn.execute().asString()
|
||||
return gson.fromJson(arrayResult, JsonObject::class.java)
|
||||
}
|
||||
|
||||
override fun registerSpecies() {
|
||||
val receiveSpeciesDataFn = this.context.getBindings("js").getMember("receiveSpeciesData")
|
||||
val jsArray = this.context.eval("js", "new Array();")
|
||||
|
||||
+8
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.io.OutputStreamWriter
|
||||
@@ -123,6 +124,13 @@ class SocketShowdownService(val host: String = "localhost", val port: Int = 1846
|
||||
return gson.fromJson(response, JsonArray::class.java)
|
||||
}
|
||||
|
||||
override fun getTypeChart(): JsonObject {
|
||||
writer.write(">getTypeChart")
|
||||
writer.flush()
|
||||
val response = readMessage()
|
||||
return gson.fromJson(response, JsonObject::class.java)
|
||||
}
|
||||
|
||||
private fun sendSpeciesData(species: Species, form: FormData?) {
|
||||
writer.write(">receiveSpeciesData ${gson.toJson(PokemonSpecies.ShowdownSpecies(species, form))}\n")
|
||||
acknowledge()
|
||||
|
||||
+47
-7
@@ -11,12 +11,11 @@ package com.cobblemon.mod.common.client.gui.battle.subscreen
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.gold
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.api.moves.TypeChart
|
||||
import com.cobblemon.mod.common.api.text.*
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.battle.ActiveClientBattlePokemon
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.MoveCategoryIcon
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
@@ -24,12 +23,16 @@ import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.math.toRGB
|
||||
import com.google.common.collect.Lists
|
||||
import net.fabricmc.loader.impl.util.StringUtil
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.util.Mth.floor
|
||||
|
||||
class BattleMoveSelection(
|
||||
@@ -91,16 +94,16 @@ class BattleMoveSelection(
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(move.id, targetPnx)
|
||||
open val selectable: Boolean get() = !move.disabled
|
||||
|
||||
val targetPnx: String? get() = targetList?.let { targets ->
|
||||
val target: Targetable? get() = targetList?.let { targets ->
|
||||
return@let when {
|
||||
targets.isEmpty() -> null
|
||||
targets.size == 1 -> targets[0].getPNX()
|
||||
targets.size == 1 -> targets[0]
|
||||
else -> null // TODO: multi-battles
|
||||
}
|
||||
}
|
||||
val targetPnx: String? get() = target?.getPNX()
|
||||
|
||||
fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
|
||||
val selectConditionOpacity = moveSelection.opacity * if (!selectable) 0.5F else 1F
|
||||
|
||||
blitk(
|
||||
@@ -173,6 +176,8 @@ class BattleMoveSelection(
|
||||
opacity = moveSelection.opacity,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawTooltip(context, mouseX, mouseY)
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX >= x && mouseX <= x + MOVE_WIDTH && mouseY >= y && mouseY <= y + MOVE_HEIGHT
|
||||
@@ -182,6 +187,41 @@ class BattleMoveSelection(
|
||||
moveSelection.playDownSound(Minecraft.getInstance().soundManager)
|
||||
moveSelection.battleGUI.selectAction(moveSelection.request, response)
|
||||
}
|
||||
|
||||
private fun drawTooltip(context: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
if (!isHovered(mouseX.toDouble(), mouseY.toDouble())) return
|
||||
|
||||
val textTooltip: MutableList<MutableComponent> = mutableListOf()
|
||||
for (descriptionLine in StringUtil.wrapLines(moveTemplate.description.string, 80).split("\n")) {
|
||||
textTooltip.add(Component.literal(descriptionLine).gray())
|
||||
}
|
||||
|
||||
textTooltip.add(Component.literal(""))
|
||||
|
||||
if (moveTemplate.power > 0) textTooltip.add(lang("ui.power").append(String.format(": %d", moveTemplate.power.toInt())))
|
||||
if (moveTemplate.accuracy > 0) textTooltip.add(lang("ui.accuracy").append(String.format(": %d%%", moveTemplate.accuracy.toInt())))
|
||||
|
||||
if (moveTemplate.power > 0 && moveTemplate.target != MoveTarget.self && target is ActiveClientBattlePokemon) {
|
||||
val species = (target as ActiveClientBattlePokemon).battlePokemon?.species
|
||||
if (species != null) {
|
||||
val moveEffectiveness: Double = TypeChart.getMoveEffectiveness(elementalType, listOf(species.primaryType, species.secondaryType))
|
||||
|
||||
textTooltip.add(when {
|
||||
moveEffectiveness == 0.0 -> lang("battle.ui.effectiveness.immunity", moveEffectiveness).gray()
|
||||
moveEffectiveness < 1.0 -> lang("battle.ui.effectiveness.resistance", moveEffectiveness).gray()
|
||||
moveEffectiveness > 1.0 -> lang("battle.ui.effectiveness.super_effective", moveEffectiveness).yellow()
|
||||
else -> lang("battle.ui.effectiveness.normal", moveEffectiveness).white()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
context.renderTooltip(
|
||||
Minecraft.getInstance().font,
|
||||
Lists.transform(textTooltip, Component::getVisualOrderText),
|
||||
mouseX,
|
||||
mouseY
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
|
||||
@@ -1268,6 +1268,7 @@
|
||||
"cobblemon.ui.status.psn": "PSN",
|
||||
"cobblemon.ui.status.slp": "SLP",
|
||||
"cobblemon.ui.status.tox": "PSN",
|
||||
|
||||
"cobblemon.battle.ui.fight": "Fight",
|
||||
"cobblemon.battle.ui.switch": "Switch",
|
||||
"cobblemon.battle.ui.capture": "Catch",
|
||||
@@ -1277,6 +1278,11 @@
|
||||
"cobblemon.battle.ui.hide_label": "Press %1$s to move around.",
|
||||
"cobblemon.battle.ui.actions_label": "You need to choose an action. Press %1$s.",
|
||||
|
||||
"cobblemon.battle.ui.effectiveness.normal": "%1$sx Normal",
|
||||
"cobblemon.battle.ui.effectiveness.super_effective": "%1$sx Super Effective",
|
||||
"cobblemon.battle.ui.effectiveness.resistance": "%1$sx Resistance",
|
||||
"cobblemon.battle.ui.effectiveness.immunity": "%1$sx Immunity",
|
||||
|
||||
"cobblemon.ui.evolve": "Evolve",
|
||||
"cobblemon.ui.evolution": "Evolution",
|
||||
"cobblemon.ui.evolve.hint": "%1$s seems ready to evolve!",
|
||||
|
||||
Reference in New Issue
Block a user