mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-22 15:16:25 -04:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fa113f5ac | ||
|
|
8443b88c16 | ||
|
|
b71208299f | ||
|
|
136b5824b0 | ||
|
|
f9189b265f | ||
|
|
21c4d0233d |
@@ -2,7 +2,6 @@
|
||||
## [1.8.3 (MONTH xth, 2026)](#1-8-3)
|
||||
|
||||
### Additions
|
||||
- You can now drag to select multiple Pokémon inside the PC menu.
|
||||
|
||||
### Pokémon Added
|
||||
#### Generation 4
|
||||
|
||||
@@ -566,7 +566,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SwapPartyPokemonPacket.ID, SwapPartyPokemonPacket::decode, SwapPartyPokemonHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(MovePCPokemonPacket.ID, MovePCPokemonPacket::decode, MovePCPokemonHandler))
|
||||
list.add(PacketRegisterInfo(MovePCPokemonBatchPacket.ID, MovePCPokemonBatchPacket::decode, MovePCPokemonBatchHandler))
|
||||
list.add(PacketRegisterInfo(MovePartyPokemonPacket.ID, MovePartyPokemonPacket::decode, MovePartyPokemonHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(SwapPCPartyPokemonPacket.ID, SwapPCPartyPokemonPacket::decode, SwapPCPartyPokemonHandler))
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacke
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.UnlockPCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonBatchPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
@@ -271,34 +270,6 @@ open class PCStore(
|
||||
}
|
||||
}
|
||||
|
||||
fun moveBatch(moves: List<Triple<UUID, PCPosition, PCPosition>>): Boolean {
|
||||
if (moves.isEmpty() || moves.size > MovePCPokemonBatchPacket.MAX_MOVES) return false
|
||||
if (moves.map { it.second }.toSet().size != moves.size ||
|
||||
moves.map { it.third }.toSet().size != moves.size ||
|
||||
moves.map { it.first }.toSet().size != moves.size
|
||||
) return false
|
||||
if (moves.any { (_, source, target) -> !isValidPosition(source) || !isValidPosition(target) }) return false
|
||||
|
||||
val sourcePositions = moves.mapTo(mutableSetOf()) { it.second }
|
||||
val pokemonMoves = moves.map { (pokemonID, source, target) ->
|
||||
val pokemon = get(source)?.takeIf { it.uuid == pokemonID } ?: return false
|
||||
Triple(source, target, pokemon)
|
||||
}
|
||||
if (pokemonMoves.any { (_, target, _) -> get(target) != null && target !in sourcePositions }) return false
|
||||
|
||||
pokemonMoves.forEach { (source, _, _) -> setAtPosition(source, null) }
|
||||
pokemonMoves.forEach { (_, target, pokemon) -> setAtPosition(target, pokemon) }
|
||||
|
||||
pokemonMoves.forEach { (_, _, pokemon) ->
|
||||
sendPacketToObservers(RemoveClientPokemonPacket(this, pokemon.uuid))
|
||||
}
|
||||
pokemonMoves.forEach { (_, target, pokemon) ->
|
||||
sendPacketToObservers(SetPCPokemonPacket(uuid, target) { pokemon })
|
||||
}
|
||||
pcChangeObservable.emit(Unit)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun loadPositionFromNBT(nbt: CompoundTag): StoreCoordinates<PCPosition> {
|
||||
return StoreCoordinates(this, PCPosition(nbt.getShort(DataKeys.STORE_BOX).toInt(), nbt.getByte(DataKeys.STORE_SLOT).toInt()))
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ class BoxStorageSlot(
|
||||
|
||||
val grabbedSlot = parent.grabbedSlot
|
||||
return if (grabbedSlot == null) {
|
||||
val pokemon = getPokemon()
|
||||
pokemon == null || !parent.isInMultiSelection(pokemon, position)
|
||||
true
|
||||
} else {
|
||||
grabbedSlot.getPokemon() != getPokemon()
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ import net.minecraft.network.chat.Component
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import kotlin.isInitialized
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.FastColor
|
||||
|
||||
class PCGUI(
|
||||
val pc: ClientPC,
|
||||
@@ -130,55 +129,6 @@ class PCGUI(
|
||||
var selectPointerOffsetIncrement = false
|
||||
var displayOptions = false
|
||||
|
||||
private var dragStartX: Int? = null
|
||||
private var dragStartY: Int? = null
|
||||
private var dragEndX: Int? = null
|
||||
private var dragEndY: Int? = null
|
||||
private var selectionDragActive = false
|
||||
|
||||
data class SelectionArea(val left: Int, val top: Int, val right: Int, val bottom: Int)
|
||||
|
||||
private data class BoxGridBounds(val left: Int, val top: Int, val right: Int, val bottom: Int) {
|
||||
fun contains(x: Int, y: Int) = x in left..< right && y >= top && y < bottom
|
||||
}
|
||||
|
||||
private fun getBoxGridBounds(): BoxGridBounds {
|
||||
val left = storageWidget.x
|
||||
val top = storageWidget.y
|
||||
return BoxGridBounds(
|
||||
left,
|
||||
top,
|
||||
left + StorageWidget.SCREEN_WIDTH,
|
||||
top + StorageWidget.SCREEN_HEIGHT
|
||||
)
|
||||
}
|
||||
|
||||
fun getSelectionArea(): SelectionArea? {
|
||||
if (!selectionDragActive) return null
|
||||
val startX = dragStartX ?: return null
|
||||
val startY = dragStartY ?: return null
|
||||
val endX = dragEndX ?: return null
|
||||
val endY = dragEndY ?: return null
|
||||
val bounds = getBoxGridBounds()
|
||||
if (!bounds.contains(startX, startY)) return null
|
||||
|
||||
val columns = 6
|
||||
val rows = 5
|
||||
val slotPitch = StorageSlot.SIZE + StorageWidget.BOX_SLOT_PADDING
|
||||
val gridLeft = bounds.left + StorageWidget.BOX_SLOT_START_OFFSET_X
|
||||
val gridTop = bounds.top + StorageWidget.BOX_SLOT_START_OFFSET_Y + if (displayOptions) 5 else 0
|
||||
val startColumn = ((startX - gridLeft) / slotPitch).coerceIn(0, columns - 1)
|
||||
val endColumn = (((endX.coerceIn(bounds.left, bounds.right - 1)) - gridLeft) / slotPitch).coerceIn(0, columns - 1)
|
||||
val startRow = ((startY - gridTop) / slotPitch).coerceIn(0, rows - 1)
|
||||
val endRow = (((endY.coerceIn(bounds.top, bounds.bottom - 1)) - gridTop) / slotPitch).coerceIn(0, rows - 1)
|
||||
return SelectionArea(
|
||||
gridLeft + minOf(startColumn, endColumn) * slotPitch, // left
|
||||
gridTop + minOf(startRow, endRow) * slotPitch, // top
|
||||
gridLeft + (maxOf(startColumn, endColumn) * slotPitch) + StorageSlot.SIZE, // right
|
||||
gridTop + (maxOf(startRow, endRow) * slotPitch) + StorageSlot.SIZE // bottom
|
||||
)
|
||||
}
|
||||
|
||||
override fun renderBlurredBackground(delta: Float) {}
|
||||
|
||||
override fun renderMenuBackground(context: GuiGraphics) {}
|
||||
@@ -300,7 +250,7 @@ class PCGUI(
|
||||
configuration.showParty = isVisible
|
||||
wallpaperWidget.visible = !isVisible
|
||||
(it as IconButton).highlighted = !isVisible
|
||||
if (unseenWallpapers.isNotEmpty()) MarkPCBoxWallpapersSeenPacket(unseenWallpapers).sendToServer()
|
||||
if (!unseenWallpapers.isEmpty()) MarkPCBoxWallpapersSeenPacket(unseenWallpapers).sendToServer()
|
||||
}.also {
|
||||
it.visible = displayOptions
|
||||
optionButtons.add(it)
|
||||
@@ -365,20 +315,6 @@ class PCGUI(
|
||||
super.init()
|
||||
}
|
||||
|
||||
private fun renderSelectionBox(context: GuiGraphics, area: SelectionArea) {
|
||||
context.pose().pushPose()
|
||||
context.pose().translate(0.0, 0.0, 1500.0)
|
||||
val borderColor = FastColor.ARGB32.color(255, 205, 212, 255)
|
||||
val bgColor = FastColor.ARGB32.color(75, 133, 183, 230)
|
||||
val thickness = 1
|
||||
context.fill(area.left, area.top, area.right, area.bottom, bgColor)
|
||||
context.fill(area.left, area.top, area.right, area.top + thickness, borderColor)
|
||||
context.fill(area.left, area.bottom - thickness, area.right, area.bottom, borderColor)
|
||||
context.fill(area.left, area.top, area.left + thickness, area.bottom, borderColor)
|
||||
context.fill(area.right - thickness, area.top, area.right, area.bottom, borderColor)
|
||||
context.pose().popPose()
|
||||
}
|
||||
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val matrices = context.pose()
|
||||
renderBackground(context, mouseX, mouseY, delta)
|
||||
@@ -749,14 +685,12 @@ class PCGUI(
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
if (optionButtons.isNotEmpty() && displayOptions) {
|
||||
if (!optionButtons.isEmpty() && displayOptions) {
|
||||
for (button in optionButtons) button.showAlt = hasShiftDown()
|
||||
}
|
||||
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
|
||||
getSelectionArea()?.let { renderSelectionBox(context, it) }
|
||||
|
||||
// Item Tooltip
|
||||
if (pokemon != null) {
|
||||
val displayedItem = if (showCosmeticItem) pokemon.cosmeticItem else pokemon.heldItemNoCopy()
|
||||
@@ -778,20 +712,6 @@ class PCGUI(
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
storageWidget.clearPendingStorageSlotClick()
|
||||
selectionDragActive = false
|
||||
val clickX = mouseX.toInt()
|
||||
val clickY = mouseY.toInt()
|
||||
if (storageWidget.multiSelection == null && button == 0 &&
|
||||
getBoxGridBounds().contains(clickX, clickY) &&
|
||||
storageWidget.pastureWidget == null) {
|
||||
dragStartX = clickX
|
||||
dragStartY = clickY
|
||||
} else {
|
||||
dragStartX = null
|
||||
dragStartY = null
|
||||
}
|
||||
|
||||
// Trigger child component function as they will need to check the entire screen click area
|
||||
if (::boxNameWidget.isInitialized) boxNameWidget.mouseClicked(mouseX, mouseY, button)
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
@@ -820,43 +740,9 @@ class PCGUI(
|
||||
storageWidget.pastureWidget?.let { pasture ->
|
||||
if (pasture.pastureScrollList.isHovered) pasture.pastureScrollList.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
}
|
||||
if (button == 0 && storageWidget.pastureWidget == null) {
|
||||
val startX = dragStartX
|
||||
val startY = dragStartY
|
||||
if (startX != null && startY != null) {
|
||||
val offsetX = mouseX - startX
|
||||
val offsetY = mouseY - startY
|
||||
if (offsetX * offsetX + offsetY * offsetY >= 25.0) {
|
||||
selectionDragActive = true
|
||||
storageWidget.clearPendingStorageSlotClick()
|
||||
dragEndX = mouseX.toInt()
|
||||
dragEndY = mouseY.toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
|
||||
}
|
||||
|
||||
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
val handled = super.mouseReleased(mouseX, mouseY, button)
|
||||
if (button == 0) {
|
||||
if (selectionDragActive) {
|
||||
dragEndX = mouseX.toInt()
|
||||
dragEndY = mouseY.toInt()
|
||||
storageWidget.updateSelection()
|
||||
storageWidget.clearPendingStorageSlotClick()
|
||||
} else {
|
||||
storageWidget.completePendingStorageSlotClick(mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
dragStartX = null
|
||||
dragStartY = null
|
||||
dragEndX = null
|
||||
dragEndY = null
|
||||
selectionDragActive = false
|
||||
return handled
|
||||
}
|
||||
|
||||
override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
|
||||
val boxNameFocused = this::boxNameWidget.isInitialized && boxNameWidget.isFocused
|
||||
val filterFocused = this::filterWidget.isInitialized && filterWidget.isFocused
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
data class PCMultiSelection(
|
||||
private val grid: MutableList<MutableList<Pokemon?>> = mutableListOf(),
|
||||
val sourceBox: Int = 0,
|
||||
val sourceColumn: Int = 0,
|
||||
val sourceRow: Int = 0
|
||||
) {
|
||||
fun getHorizontalSize(): Int = grid.firstOrNull()?.size ?: 0
|
||||
fun getVerticalSize(): Int = grid.size
|
||||
|
||||
constructor(horizontalSize: Int, verticalSize: Int, sourceBox: Int, sourceColumn: Int, sourceRow: Int) : this(
|
||||
MutableList(verticalSize) { MutableList<Pokemon?>(horizontalSize) { null } },
|
||||
sourceBox,
|
||||
sourceColumn,
|
||||
sourceRow
|
||||
)
|
||||
|
||||
fun getPokemon(x: Int, y: Int): Pokemon? {
|
||||
return grid[y][x]
|
||||
}
|
||||
|
||||
fun setPokemon(x: Int, y: Int, pokemon: Pokemon?) {
|
||||
grid[y][x] = pokemon
|
||||
}
|
||||
|
||||
fun pokemonEntries(): List<Triple<Int, Int, Pokemon>> {
|
||||
return grid.flatMapIndexed { y, row ->
|
||||
row.mapIndexedNotNull { x, pokemon -> pokemon?.let { Triple(x, y, it) } }
|
||||
}
|
||||
}
|
||||
|
||||
fun getPokemonCount(): Int = pokemonEntries().size
|
||||
|
||||
}
|
||||
@@ -45,13 +45,11 @@ class ReleaseButton(
|
||||
vOffset = if (isHovered(mouseX.toDouble(), mouseY.toDouble())) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2
|
||||
)
|
||||
val pokemonCount = parent.multiSelection?.getPokemonCount() ?: 0
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = if (pokemonCount > 1)
|
||||
{ lang("ui.pc.release_all").bold() } else { lang("ui.pc.release").bold() },
|
||||
text = lang("ui.pc.release").bold(),
|
||||
x = x + (WIDTH / 2),
|
||||
y = y + 3.5,
|
||||
centered = true,
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.gui.ColourLibrary
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
@@ -55,17 +54,9 @@ open class StorageSlot(
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val selectionArea = parent.pcGui.getSelectionArea()
|
||||
if (selectionArea != null && parent.getSelectedPokemon(selectionArea).contains(this)) {
|
||||
val highlightColor = 0x40FFFFFF
|
||||
context.fill(x + 1, y, x + (SIZE - 1), y + SIZE, highlightColor)
|
||||
context.fill(x, y + 1, x + 1, y + (SIZE - 1), highlightColor)
|
||||
context.fill(x + SIZE - 1, y + 1, x + SIZE, y + (SIZE - 1), highlightColor)
|
||||
}
|
||||
if (shouldRender()) {
|
||||
renderSlot(context, x, y, delta)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun renderSlot(context: GuiGraphics, posX: Int, posY: Int, partialTicks: Float) {
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.storage.StorePosition
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyPosition
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCPosition
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
@@ -38,9 +39,8 @@ import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import java.util.UUID
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonBatchPacket.PCPokemonMove
|
||||
|
||||
class StorageWidget(
|
||||
pX: Int, pY: Int,
|
||||
@@ -77,13 +77,9 @@ class StorageWidget(
|
||||
|
||||
var displayConfirmRelease = false
|
||||
var screenLoaded = false
|
||||
var selectedPosition: PartyPosition? = null
|
||||
var selectedPosition: StorePosition? = null
|
||||
var grabbedSlot: GrabbedStorageSlot? = null
|
||||
|
||||
var multiSelection: PCMultiSelection? = null
|
||||
private val multiGrabbedSlots = mutableMapOf<UUID, GrabbedStorageSlot>()
|
||||
private var pendingStorageSlotClick: Button? = null
|
||||
|
||||
var box = 0
|
||||
set(value) {
|
||||
field =
|
||||
@@ -117,22 +113,16 @@ class StorageWidget(
|
||||
subKey = "ui.generic.yes",
|
||||
onPress = {
|
||||
if (canDeleteSelected() && displayConfirmRelease) {
|
||||
val selection = multiSelection
|
||||
if (selection != null) {
|
||||
selection.pokemonEntries().forEach { (column, row, pokemon) ->
|
||||
val position = PCPosition(
|
||||
selection.sourceBox,
|
||||
(selection.sourceRow + row) * 6 + selection.sourceColumn + column
|
||||
)
|
||||
CobblemonNetwork.sendToServer(ReleasePCPokemonPacket(pokemon.uuid, position))
|
||||
}
|
||||
} else {
|
||||
val position = selectedPosition ?: return@ReleaseConfirmButton
|
||||
val pokemon = getSelectedPokemon() ?: return@ReleaseConfirmButton
|
||||
val position = selectedPosition ?: return@ReleaseConfirmButton
|
||||
val pokemon = getSelectedPokemon() ?: return@ReleaseConfirmButton
|
||||
|
||||
CobblemonNetwork.sendToServer(ReleasePartyPokemonPacket(pokemon.uuid, position))
|
||||
val packet = when (position) {
|
||||
is PartyPosition -> ReleasePartyPokemonPacket(pokemon.uuid, position)
|
||||
is PCPosition -> ReleasePCPokemonPacket(pokemon.uuid, position)
|
||||
else -> return@ReleaseConfirmButton
|
||||
}
|
||||
|
||||
CobblemonNetwork.sendToServer(packet)
|
||||
playSound(CobblemonSounds.PC_RELEASE)
|
||||
resetSelected()
|
||||
displayConfirmRelease = false
|
||||
@@ -159,8 +149,9 @@ class StorageWidget(
|
||||
}
|
||||
|
||||
fun canDeleteSelected(): Boolean {
|
||||
multiSelection?.let { return it.pokemonEntries().isNotEmpty() }
|
||||
return party.filterNotNull().size > 1 && selectedPosition != null && grabbedSlot != null
|
||||
return !(selectedPosition is PartyPosition && party.filterNotNull().size <= 1)
|
||||
&& selectedPosition != null
|
||||
&& grabbedSlot != null
|
||||
}
|
||||
|
||||
fun setupStorageSlots() {
|
||||
@@ -179,7 +170,7 @@ class StorageWidget(
|
||||
parent = this,
|
||||
pc = pc,
|
||||
position = PCPosition(box, index),
|
||||
onPress = { pendingStorageSlotClick = it }
|
||||
onPress = { this.onStorageSlotClicked(it) }
|
||||
).also { widget ->
|
||||
this.addWidget(widget)
|
||||
this.boxSlots.add(widget)
|
||||
@@ -209,7 +200,7 @@ class StorageWidget(
|
||||
parent = this,
|
||||
party = party,
|
||||
position = PartyPosition(partyIndex),
|
||||
onPress = { pendingStorageSlotClick = it }
|
||||
onPress = { this.onStorageSlotClicked(it) }
|
||||
).also { widget ->
|
||||
this.addWidget(widget)
|
||||
this.partySlots.add(widget)
|
||||
@@ -219,115 +210,13 @@ class StorageWidget(
|
||||
|
||||
private fun getSelectedPokemon(): Pokemon? {
|
||||
val selectedPosition = this.selectedPosition ?: return null
|
||||
return party.get(selectedPosition)
|
||||
}
|
||||
|
||||
fun getSelectedPokemon(area: PCGUI.SelectionArea): List<BoxStorageSlot> {
|
||||
return boxSlots.filter { slot ->
|
||||
slot.x < area.right && slot.x + StorageSlot.SIZE > area.left &&
|
||||
slot.y < area.bottom && slot.y + StorageSlot.SIZE > area.top &&
|
||||
slot.getPokemon()?.let(pcGui.search::passes) == true
|
||||
return when (selectedPosition) {
|
||||
is PCPosition -> pc.get(selectedPosition)
|
||||
is PartyPosition -> party.get(selectedPosition)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun clearPendingStorageSlotClick() {
|
||||
pendingStorageSlotClick = null
|
||||
}
|
||||
|
||||
fun completePendingStorageSlotClick(mouseX: Double, mouseY: Double) {
|
||||
val button = pendingStorageSlotClick ?: return
|
||||
pendingStorageSlotClick = null
|
||||
if (button.isMouseOver(mouseX, mouseY)) {
|
||||
onStorageSlotClicked(button)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSelection() {
|
||||
val area = pcGui.getSelectionArea()
|
||||
if (area == null) {
|
||||
multiSelection = null
|
||||
return
|
||||
}
|
||||
|
||||
selectedPosition = null
|
||||
grabbedSlot = null
|
||||
pcGui.setPreviewPokemon(null)
|
||||
|
||||
val selectedSlots = getSelectedPokemon(area)
|
||||
if (selectedSlots.isEmpty()) {
|
||||
multiSelection = null
|
||||
return
|
||||
}
|
||||
|
||||
val minColumn = selectedSlots.minOf { it.position.slot % 6 }
|
||||
val maxColumn = selectedSlots.maxOf { it.position.slot % 6 }
|
||||
val minRow = selectedSlots.minOf { it.position.slot / 6 }
|
||||
val maxRow = selectedSlots.maxOf { it.position.slot / 6 }
|
||||
val selection = PCMultiSelection(maxColumn - minColumn + 1, maxRow - minRow + 1, box, minColumn, minRow)
|
||||
|
||||
selectedSlots.forEach { slot ->
|
||||
val pokemon = slot.getPokemon() ?: return@forEach
|
||||
val slotIndex = slot.position.slot
|
||||
val column = slotIndex % 6
|
||||
val row = slotIndex / 6
|
||||
if (column in minColumn..maxColumn && row in minRow..maxRow) {
|
||||
selection.setPokemon(column - minColumn, row - minRow, pokemon)
|
||||
}
|
||||
}
|
||||
playSound(CobblemonSounds.PC_GRAB)
|
||||
|
||||
multiSelection = selection
|
||||
}
|
||||
|
||||
private fun moveMultiSelectionTo(destination: PCPosition): Boolean {
|
||||
val selection = multiSelection ?: return false
|
||||
|
||||
val width = selection.getHorizontalSize()
|
||||
val height = selection.getVerticalSize()
|
||||
val destinationColumn = destination.slot % 6
|
||||
val destinationRow = destination.slot / 6
|
||||
if (destinationColumn + width > 6 || destinationRow + height > 5) return false
|
||||
|
||||
val moves = mutableListOf<PCPokemonMove>()
|
||||
val selectedSources = mutableSetOf<PCPosition>()
|
||||
for (row in 0 until height) {
|
||||
for (column in 0 until width) {
|
||||
val pokemon = selection.getPokemon(column, row) ?: continue
|
||||
val source = PCPosition(selection.sourceBox, (selection.sourceRow + row) * 6 + selection.sourceColumn + column)
|
||||
val target = PCPosition(destination.box, (destinationRow + row) * 6 + destinationColumn + column)
|
||||
selectedSources.add(source)
|
||||
moves.add(PCPokemonMove(pokemon.uuid, source, target))
|
||||
}
|
||||
}
|
||||
|
||||
if (moves.isEmpty()) return false
|
||||
|
||||
for (row in 0 until height) {
|
||||
for (column in 0 until width) {
|
||||
if (selection.getPokemon(column, row) == null) continue
|
||||
val target = PCPosition(destination.box, (destinationRow + row) * 6 + destinationColumn + column)
|
||||
val displacedPokemon = pc.get(target) ?: continue
|
||||
if (target in selectedSources) continue
|
||||
|
||||
val displacedSource = PCPosition(
|
||||
selection.sourceBox,
|
||||
(selection.sourceRow + row) * 6 + selection.sourceColumn + column
|
||||
)
|
||||
if (pc.get(displacedSource) != null && displacedSource !in selectedSources) return false
|
||||
moves.add(PCPokemonMove(displacedPokemon.uuid, target, displacedSource))
|
||||
}
|
||||
}
|
||||
|
||||
if (moves.map { it.newPosition }.toSet().size != moves.size) return false
|
||||
MovePCPokemonBatchPacket(moves).sendToServer()
|
||||
return true
|
||||
}
|
||||
|
||||
fun isInMultiSelection(pokemon: Pokemon, position: PCPosition): Boolean {
|
||||
val selection = multiSelection ?: return false
|
||||
return selection.sourceBox == position.box && selection.pokemonEntries().any { it.third == pokemon }
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val matrices = context.pose()
|
||||
// Party Label
|
||||
@@ -351,14 +240,11 @@ class StorageWidget(
|
||||
shadow = true
|
||||
)
|
||||
|
||||
val pokemonCount = multiSelection?.getPokemonCount() ?: 0
|
||||
|
||||
if (canDeleteSelected() && displayConfirmRelease) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = if (pokemonCount > 1)
|
||||
{ lang("ui.pc.release_all").bold() } else { lang("ui.pc.release").bold() },
|
||||
text = lang("ui.pc.release").bold(),
|
||||
x = x + 223,
|
||||
y = y + 119,
|
||||
centered = true
|
||||
@@ -422,7 +308,6 @@ class StorageWidget(
|
||||
slot.render(context, mouseX, mouseY, delta)
|
||||
val pokemon = slot.getPokemon()
|
||||
if (grabbedSlot == null && slot.isHovered(mouseX, mouseY)
|
||||
&& multiSelection == null
|
||||
&& pokemon != null && pokemon != pcGui.previewPokemon
|
||||
) {
|
||||
pcGui.setPreviewPokemon(pokemon, pcGui.isPreviewInParty ?: false)
|
||||
@@ -439,7 +324,6 @@ class StorageWidget(
|
||||
slot.render(context, mouseX, mouseY, delta)
|
||||
val pokemon = slot.getPokemon()
|
||||
if (grabbedSlot == null && slot.isHovered(mouseX, mouseY)
|
||||
&& multiSelection == null
|
||||
&& pokemon != null && pokemon != pcGui.previewPokemon
|
||||
) {
|
||||
pcGui.setPreviewPokemon(pokemon, pcGui.isPreviewInParty ?: true)
|
||||
@@ -451,31 +335,10 @@ class StorageWidget(
|
||||
pastureWidget?.render(context, mouseX, mouseY, delta)
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, 0.0, 1000.0)
|
||||
renderSelectedPokemon(context, mouseX, mouseY, delta)
|
||||
grabbedSlot?.render(context, mouseX, mouseY, delta)
|
||||
matrices.popPose()
|
||||
}
|
||||
|
||||
private fun renderSelectedPokemon(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
val selection = multiSelection
|
||||
if (selection == null) {
|
||||
grabbedSlot?.render(context, mouseX, mouseY, delta)
|
||||
return
|
||||
}
|
||||
|
||||
val slotOffset = StorageSlot.SIZE + BOX_SLOT_PADDING
|
||||
selection.pokemonEntries().forEach { (column, row, pokemon) ->
|
||||
val grabbed = multiGrabbedSlots.getOrPut(pokemon.uuid) {
|
||||
GrabbedStorageSlot(0, 0, this, pokemon)
|
||||
}
|
||||
grabbed.render(
|
||||
context,
|
||||
mouseX + column * slotOffset,
|
||||
mouseY + row * slotOffset,
|
||||
delta
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
if (displayConfirmRelease) {
|
||||
if (releaseYesButton.isHovered(pMouseX, pMouseY)) releaseYesButton.mouseClicked(pMouseX, pMouseY, pButton)
|
||||
@@ -508,55 +371,23 @@ class StorageWidget(
|
||||
else -> return
|
||||
}
|
||||
|
||||
val clickedPokemon = when (clickedPosition) {
|
||||
is PCPosition -> pc.get(clickedPosition)
|
||||
is PartyPosition -> party.get(clickedPosition)
|
||||
else -> null
|
||||
}
|
||||
|
||||
multiSelection?.let { selection ->
|
||||
when (clickedPosition) {
|
||||
is PCPosition -> {
|
||||
if (clickedPosition.box == selection.sourceBox &&
|
||||
clickedPosition.slot == selection.sourceRow * 6 + selection.sourceColumn
|
||||
) {
|
||||
resetSelected()
|
||||
} else if (moveMultiSelectionTo(clickedPosition)) {
|
||||
playSound(CobblemonSounds.PC_DROP)
|
||||
resetSelected()
|
||||
}
|
||||
}
|
||||
is PartyPosition -> {
|
||||
val selectedPokemon = selection.pokemonEntries().singleOrNull() ?: return
|
||||
val (column, row, pokemon) = selectedPokemon
|
||||
val source = PCPosition(
|
||||
selection.sourceBox,
|
||||
(selection.sourceRow + row) * 6 + selection.sourceColumn + column
|
||||
)
|
||||
if (pc.get(source) !== pokemon) return
|
||||
val packet = clickedPokemon?.let {
|
||||
SwapPCPartyPokemonPacket(it.uuid, clickedPosition, pokemon.uuid, source)
|
||||
} ?: MovePCPokemonToPartyPacket(pokemon.uuid, source, clickedPosition)
|
||||
packet.sendToServer()
|
||||
playSound(CobblemonSounds.PC_DROP)
|
||||
resetSelected()
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Reset release confirmation
|
||||
displayConfirmRelease = false
|
||||
|
||||
// Clicking on itself, so unselect position
|
||||
if (selectedPosition == clickedPosition) {
|
||||
if (this.selectedPosition != null && this.selectedPosition == clickedPosition) {
|
||||
if (grabbedSlot != null) playSound(CobblemonSounds.PC_DROP)
|
||||
resetSelected()
|
||||
return
|
||||
}
|
||||
|
||||
// Check for selecting a Pokémon
|
||||
val clickedPokemon = when(button) {
|
||||
is BoxStorageSlot -> pc.get(clickedPosition as PCPosition)
|
||||
is PartyStorageSlot -> party.get(clickedPosition as PartyPosition)
|
||||
else -> null
|
||||
}
|
||||
|
||||
val selectOverride = pcGui.configuration.selectOverride
|
||||
if (selectOverride != null) {
|
||||
selectOverride(pcGui, clickedPosition, clickedPokemon)
|
||||
@@ -589,44 +420,56 @@ class StorageWidget(
|
||||
}
|
||||
}
|
||||
|
||||
if (clickedPosition is PCPosition) {
|
||||
val column = clickedPosition.slot % 6
|
||||
val row = clickedPosition.slot / 6
|
||||
multiSelection = PCMultiSelection(1, 1, clickedPosition.box, column, row).also {
|
||||
it.setPokemon(0, 0, clickedPokemon)
|
||||
}
|
||||
playSound(CobblemonSounds.PC_GRAB)
|
||||
return
|
||||
} else if (clickedPosition is PartyPosition) {
|
||||
this.selectedPosition = clickedPosition
|
||||
this.pcGui.setPreviewPokemon(clickedPokemon, pcGui.isPreviewInParty ?: false)
|
||||
grabbedSlot = GrabbedStorageSlot(
|
||||
x = button.x,
|
||||
y = button.y,
|
||||
parent = this,
|
||||
pokemon = clickedPokemon
|
||||
)
|
||||
playSound(CobblemonSounds.PC_GRAB)
|
||||
}
|
||||
this.selectedPosition = clickedPosition
|
||||
this.pcGui.setPreviewPokemon(clickedPokemon, pcGui.isPreviewInParty ?: false)
|
||||
grabbedSlot = GrabbedStorageSlot(
|
||||
x = button.x,
|
||||
y = button.y,
|
||||
parent = this,
|
||||
pokemon = clickedPokemon
|
||||
)
|
||||
playSound(CobblemonSounds.PC_GRAB)
|
||||
|
||||
}
|
||||
} else {
|
||||
val sourcePosition = selectedPosition ?: return
|
||||
val selectedPokemon = party.get(sourcePosition) ?: return
|
||||
// Handle movement within the Box
|
||||
val selectedPokemon = when(this.selectedPosition) {
|
||||
is PCPosition -> pc.get(this.selectedPosition as PCPosition)
|
||||
is PartyPosition -> party.get(this.selectedPosition as PartyPosition)
|
||||
else -> null
|
||||
} ?: return
|
||||
|
||||
// Box to Box
|
||||
if (this.selectedPosition is PCPosition && clickedPosition is PCPosition) {
|
||||
val packet = clickedPokemon?.let { SwapPCPokemonPacket(it.uuid, clickedPosition, selectedPokemon.uuid, this.selectedPosition as PCPosition) }
|
||||
?: MovePCPokemonPacket(selectedPokemon.uuid, selectedPosition as PCPosition, clickedPosition)
|
||||
packet.sendToServer()
|
||||
playSound(CobblemonSounds.PC_DROP)
|
||||
resetSelected()
|
||||
}
|
||||
// Box to Party
|
||||
else if (this.selectedPosition is PCPosition && clickedPosition is PartyPosition) {
|
||||
val packet = clickedPokemon?.let { SwapPCPartyPokemonPacket(clickedPokemon.uuid, clickedPosition, selectedPokemon.uuid, this.selectedPosition as PCPosition) }
|
||||
?: MovePCPokemonToPartyPacket(selectedPokemon.uuid, this.selectedPosition as PCPosition, clickedPosition)
|
||||
packet.sendToServer()
|
||||
playSound(CobblemonSounds.PC_DROP)
|
||||
resetSelected()
|
||||
}
|
||||
// Party to Box
|
||||
if (clickedPosition is PCPosition) {
|
||||
else if (this.selectedPosition is PartyPosition && clickedPosition is PCPosition) {
|
||||
if (ServerSettings.preventCompletePartyDeposit && this.party.filterNotNull().size == 1 && clickedPokemon == null) {
|
||||
return
|
||||
}
|
||||
val packet = clickedPokemon?.let { SwapPCPartyPokemonPacket(selectedPokemon.uuid, sourcePosition, clickedPokemon.uuid, clickedPosition) }
|
||||
?: MovePartyPokemonToPCPacket(selectedPokemon.uuid, sourcePosition, clickedPosition)
|
||||
val packet = clickedPokemon?.let { SwapPCPartyPokemonPacket(selectedPokemon.uuid, this.selectedPosition as PartyPosition, clickedPokemon.uuid, clickedPosition) }
|
||||
?: MovePartyPokemonToPCPacket(selectedPokemon.uuid, this.selectedPosition as PartyPosition, clickedPosition)
|
||||
packet.sendToServer()
|
||||
playSound(CobblemonSounds.PC_DROP)
|
||||
resetSelected()
|
||||
}
|
||||
// Party to Party
|
||||
else if (clickedPosition is PartyPosition) {
|
||||
val packet = clickedPokemon?.let { SwapPartyPokemonPacket(it.uuid, clickedPosition, selectedPokemon.uuid, sourcePosition) }
|
||||
?: MovePartyPokemonPacket(selectedPokemon.uuid, sourcePosition, clickedPosition)
|
||||
else if (this.selectedPosition is PartyPosition && clickedPosition is PartyPosition) {
|
||||
val packet = clickedPokemon?.let { SwapPartyPokemonPacket(it.uuid, clickedPosition, selectedPokemon.uuid, this.selectedPosition as PartyPosition) }
|
||||
?: MovePartyPokemonPacket(selectedPokemon.uuid, selectedPosition as PartyPosition, clickedPosition)
|
||||
packet.sendToServer()
|
||||
playSound(CobblemonSounds.PC_DROP)
|
||||
resetSelected()
|
||||
@@ -637,8 +480,6 @@ class StorageWidget(
|
||||
fun resetSelected() {
|
||||
selectedPosition = null
|
||||
grabbedSlot = null
|
||||
multiSelection = null
|
||||
multiGrabbedSlots.clear()
|
||||
pcGui.setPreviewPokemon(null)
|
||||
}
|
||||
}
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://www.mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.server.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCPosition
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readPCPosition
|
||||
import com.cobblemon.mod.common.util.writePCPosition
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class MovePCPokemonBatchPacket(val moves: List<PCPokemonMove>) : NetworkPacket<MovePCPokemonBatchPacket> {
|
||||
override val id = ID
|
||||
|
||||
data class PCPokemonMove(
|
||||
val pokemonID: UUID,
|
||||
val oldPosition: PCPosition,
|
||||
val newPosition: PCPosition
|
||||
)
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeVarInt(moves.size)
|
||||
moves.forEach { move ->
|
||||
buffer.writeUUID(move.pokemonID)
|
||||
buffer.writePCPosition(move.oldPosition)
|
||||
buffer.writePCPosition(move.newPosition)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("move_pc_pokemon_batch")
|
||||
const val MAX_MOVES = 60
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): MovePCPokemonBatchPacket {
|
||||
val size = buffer.readVarInt()
|
||||
require(size in 1..MAX_MOVES) { "Invalid batch PC move size: $size" }
|
||||
return MovePCPokemonBatchPacket(
|
||||
List(size) {
|
||||
PCPokemonMove(
|
||||
pokemonID = buffer.readUUID(),
|
||||
oldPosition = buffer.readPCPosition(),
|
||||
newPosition = buffer.readPCPosition()
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://www.mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling.storage.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonBatchPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object MovePCPokemonBatchHandler : ServerNetworkPacketHandler<MovePCPokemonBatchPacket> {
|
||||
override fun handle(packet: MovePCPokemonBatchPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val pc = PCLinkManager.getPC(player) ?: return run { ClosePCPacket(null).sendToPlayer(player) }
|
||||
pc.moveBatch(packet.moves.map { Triple(it.pokemonID, it.oldPosition, it.newPosition) })
|
||||
}
|
||||
}
|
||||
@@ -1299,7 +1299,6 @@
|
||||
"cobblemon.ui.pc.filter.tooltip": "Format: pikachu shiny held_item lvl=1...",
|
||||
"cobblemon.ui.pc.options": "Options",
|
||||
"cobblemon.ui.pc.release": "Release",
|
||||
"cobblemon.ui.pc.release_all": "Release All",
|
||||
"cobblemon.ui.sort.name": "Sort by name",
|
||||
"cobblemon.ui.sort.level": "Sort by level",
|
||||
"cobblemon.ui.sort.pokedex_number": "Sort by Pokédex number",
|
||||
|
||||
@@ -855,7 +855,7 @@
|
||||
"advancements.cobblemon.obtain_berry.description": "地表に育ち多くの用途を持つ、きのみを手に入れる",
|
||||
"advancements.cobblemon.obtain_mutated_berry": "想定外の結果",
|
||||
"advancements.cobblemon.obtain_mutated_berry.description": "違う種類のきのみの木を隣り合わせに植えて突然変異を目撃する",
|
||||
"advancements.cobblemon.obtain_all_berries": "もぎもぎフルーツ",
|
||||
"advancements.cobblemon.obtain_all_berries": "もぎってナッツ",
|
||||
"advancements.cobblemon.obtain_all_berries.description": "Cobblemonに登場する全てのきのみを集める",
|
||||
"advancements.cobblemon.use_pasture": "みんなのポケモン牧場",
|
||||
"advancements.cobblemon.use_pasture.description": "ぼくじょうブロックを作りポケモンを放し飼いにする",
|
||||
@@ -6219,7 +6219,7 @@
|
||||
"cobblemon.egg_group.water_2": "水中②",
|
||||
"cobblemon.egg_group.ditto": "メタモン",
|
||||
"cobblemon.egg_group.dragon": "ドラゴン",
|
||||
"cobblemon.egg_group.undiscovered": "タマゴ未発見",
|
||||
"cobblemon.egg_group.undiscovered": "未発見",
|
||||
"cobblemon.trade.canceled.sender": "%1$s との交換リクエストをキャンセルしました。",
|
||||
"cobblemon.trade.canceled.receiver": "%1$s が交換リクエストをキャンセルしました...",
|
||||
"cobblemon.trade.sent": "%1$s との交換をリクエストしました。",
|
||||
@@ -6981,7 +6981,7 @@
|
||||
"cobblemon.mark.ribbon_contest_sinnoh_tough_3.desc": "スーパーコンテスト たくましさ部門 ウルトラランク 優勝!",
|
||||
"cobblemon.mark.ribbon_contest_sinnoh_tough_4": "パワフルリボンマスター",
|
||||
"cobblemon.mark.ribbon_contest_super_master_beauty": "うつくしさマスターリボン",
|
||||
"cobblemon.mark.ribbon_contest_super_master_beauty.title": "とうじきれいだった %1$s",
|
||||
"cobblemon.mark.ribbon_contest_super_master_beauty.title": "とうじからきれいな %1$s",
|
||||
"cobblemon.mark.ribbon_contest_super_master_beauty.desc": "コンテストで うつくしさを 発揮した ポケモンに 贈られる 記念リボン",
|
||||
"cobblemon.mark.ribbon_contest_super_master_cleverness": "かしこさマスターリボン",
|
||||
"cobblemon.mark.ribbon_contest_super_master_cleverness.title": "てんさいとよばれた %1$s",
|
||||
@@ -7002,7 +7002,7 @@
|
||||
"cobblemon.mark.ribbon_contest_super_master_coolness": "かっこよさマスターリボン",
|
||||
"cobblemon.mark.ribbon_contest_super_master_cuteness.desc": "コンテストで かわいさを 発揮した ポケモンに 贈られる 記念リボン",
|
||||
"cobblemon.mark.ribbon_contest_super_master_toughness": "たくましさマスターリボン",
|
||||
"cobblemon.mark.ribbon_contest_super_master_toughness.title": "ムキムキの %1$s",
|
||||
"cobblemon.mark.ribbon_contest_super_master_toughness.title": "むかしからムキムキの %1$s",
|
||||
"cobblemon.mark.ribbon_contest_super_master_toughness.desc": "コンテストで たくましさを 発揮した ポケモンに 贈られる 記念リボン",
|
||||
"cobblemon.mark.ribbon_contest_super_star": "コンテストスターリボン",
|
||||
"cobblemon.mark.ribbon_contest_super_star.title": "でんせつてきスターの %1$s",
|
||||
@@ -9243,7 +9243,7 @@
|
||||
"cobblemon.ui.moves.learnset.tm.discovered": "発見済み",
|
||||
"cobblemon.ui.moves.level": "レベルアップ",
|
||||
"cobblemon.ui.moves.egg": "タマゴ技",
|
||||
"cobblemon.ui.moves.tm": "わざマシン",
|
||||
"cobblemon.ui.moves.tm": "わざマシン",
|
||||
"cobblemon.ui.tm_machine.can_learn": "覚えられる",
|
||||
"cobblemon.ui.tm_machine.cannot_learn": "覚えられない",
|
||||
"cobblemon.ui.tm_machine.learned": "覚えている",
|
||||
@@ -9596,5 +9596,42 @@
|
||||
"cobblemon.config.ui.world_spawning_blocklist": "ワールドごとのスポーンブロックリスト",
|
||||
"cobblemon.config.ui.world_spawning_blocklist.tooltip": "ポケモンの出現ロジックを無効にするワールド。",
|
||||
"advancements.cobblemon.obtain_tm": "Show Me Your Moves!",
|
||||
"advancements.cobblemon.obtain_tm.description": "わざマシンを見つけるか、印刷する"
|
||||
"advancements.cobblemon.obtain_tm.description": "わざマシンを見つけるか、印刷する",
|
||||
"itemGroup.cobblemon.tm_item": "Cobblemon:わざマシン",
|
||||
"block.cobblemon.wistensu": "フジブヨウ",
|
||||
"block.cobblemon.lobaila": "ミゾグレン",
|
||||
"block.cobblemon.pauvillea": "フラビリア",
|
||||
"block.cobblemon.pomohana": "ポンノハナ",
|
||||
"block.cobblemon.voltaconia": "ボルトコニア",
|
||||
"block.cobblemon.verdroot": "ミノルート",
|
||||
"block.cobblemon.lucibell": "サイヴェル",
|
||||
"block.cobblemon.mistleaf": "ミストリーフ",
|
||||
"cobblemon.ui.pokedex.info.evolution_tree": "進化の流れ",
|
||||
"cobblemon.ui.pokedex.evolution.item_interact.tooltip": "%1$sが必要",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_species": "%1$sとのポケモン交換で進化",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_any_species": "ポケモン交換で進化",
|
||||
"cobblemon.ui.pokedex.evolution.shedder.tooltip": "予備のモンスターボールと手持ちの空きが必要",
|
||||
"cobblemon.ui.pokedex.evolution.or": "または",
|
||||
"cobblemon.ui.pokedex.evolution.one_of": "以下のいずれか:",
|
||||
"cobblemon.ui.pokedex.requirement.advancement.tooltip": "プレイヤーが進捗 %1$sを達成している必要あり",
|
||||
"cobblemon.ui.pokedex.requirement.battle_critical_hits.tooltip": "バトルで%1$s回急所に当てる",
|
||||
"cobblemon.ui.pokedex.requirement.biome.anticondition.tooltip": "%1$sバイオームでは進化出来ない",
|
||||
"cobblemon.ui.pokedex.requirement.biome.both.tooltip": "%2$sを除いた%1$sバイオームでのみ進化",
|
||||
"cobblemon.ui.pokedex.requirement.biome.tooltip": "%1$sバイオームでのみ進化",
|
||||
"cobblemon.ui.pokedex.requirement.blocks_traveled.tooltip": "%1$sブロック分旅をする",
|
||||
"cobblemon.ui.pokedex.requirement.damage_taken.tooltip": "バトルで倒れず%1$sダメージ受ける",
|
||||
"cobblemon.ui.pokedex.requirement.defeat.tooltip": "進化するためにはバトルで%1$sを倒す",
|
||||
"cobblemon.ui.pokedex.requirement.friendship.tooltip": "なかよし度%1$sが必要",
|
||||
"cobblemon.ui.pokedex.requirement.has_move.tooltip": "%1$sを覚える必要がある",
|
||||
"cobblemon.ui.pokedex.requirement.has_move_type.tooltip": "%1$sタイプの技を覚えておく必要がある",
|
||||
"cobblemon.ui.pokedex.requirement.held_item.tooltip": "%1$sを持っている必要がある",
|
||||
"cobblemon.ui.pokedex.requirement.level.tooltip.min": "レベル%1$sから進化",
|
||||
"cobblemon.ui.pokedex.requirement.party_member.tooltip": "レベルが%1$sから%2$sの間で進化",
|
||||
"cobblemon.ui.pokedex.requirement.pokemon_properties.tooltip": "%1$sでなければいけない",
|
||||
"cobblemon.ui.pokedex.requirement.properties.and": "%1$s と %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.level.tooltip.between": "レベルが%1$sから%2$sの間で進化",
|
||||
"cobblemon.ui.pokedex.requirement.moon_phase.tooltip": "月の満ち欠けが%1$sでなければいけない",
|
||||
"cobblemon.ui.pokedex.requirement.nature.toxtricity_amped": "性格が§aがんばりや§r、 §aゆうかん§r、 §aいじっぱり§r、 §aやんちゃ§r、 §aすなお§r、 §aわんぱく§r、 §aのうてんき§r、 §aせっかち§r、 §aようき§r、 §aむじゃき§r、 §aうっかりや§r、 §aなまいき§r、 §aきまぐれ§rのどれか",
|
||||
"cobblemon.ui.pokedex.requirement.nature.toxtricity_low_key": "性格が§aさみしがり§r、 §aずぶとい§r、 §aのんき§r、 §aおくびょう§r、 §aまじめ§r、 §aひかえめ§r、 §aおっとり§r、 §aれいせい§r、 §aてれや§r、 §aおだやか§r、 §a\tおとなしい§r、 §aしんちょう§rのどれか",
|
||||
"cobblemon.ui.pokedex.requirement.nickname.malamar": "ニックネームを§aDinnerbone§rか§aGrumm§rにする"
|
||||
}
|
||||
|
||||
@@ -9413,5 +9413,114 @@
|
||||
"cobblemon.ui.pokedex.info.form.tatsugiri-stretchymega": "Mega Tatsugiri Forma Estendida",
|
||||
"cobblemon.species.tatsugiri-stretchymega.desc": "Usando a energia da Mega Evolução, cria um prato onde repousar, permitindo com que se mova com mobilidade total até mesmo pelo ar.",
|
||||
"cobblemon.ui.pokedex.info.form.baxcalibur-mega": "Mega Baxcalibur",
|
||||
"cobblemon.species.baxcalibur-mega.desc": "A lâmina dorsal de Baxcalibur ficou ainda maior graças à Mega Evolução. Esse Pokémon dispara feixes do cabo localizado em seu peito."
|
||||
"cobblemon.species.baxcalibur-mega.desc": "A lâmina dorsal de Baxcalibur ficou ainda maior graças à Mega Evolução. Esse Pokémon dispara feixes do cabo localizado em seu peito.",
|
||||
"itemGroup.cobblemon.tm_item": "Cobblemon: Máquinas Técnicas",
|
||||
"block.cobblemon.pomohana": "Pomohana",
|
||||
"block.cobblemon.pauvillea": "Pa'uvillea",
|
||||
"block.cobblemon.lobaila": "Lobaila",
|
||||
"block.cobblemon.wistensu": "Wistensu",
|
||||
"block.cobblemon.voltaconia": "Voltaconia",
|
||||
"block.cobblemon.verdroot": "Verdroot",
|
||||
"block.cobblemon.lucibell": "Lucibell",
|
||||
"block.cobblemon.mistleaf": "Mistleaf",
|
||||
"cobblemon.ui.pokedex.info.evolution_tree": "Árvore Evolutiva",
|
||||
"cobblemon.ui.pokedex.evolution.item_interact.tooltip": "Precisa do item %1$s para evoluir",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_species": "Evolui quando trocado segurando %1$s",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_any_species": "Evolui quando trocado",
|
||||
"cobblemon.ui.pokedex.evolution.shedder.tooltip": "Também requer uma Pokébola extra e um espaço vazio na equipe",
|
||||
"cobblemon.ui.pokedex.evolution.or": "OU",
|
||||
"cobblemon.ui.pokedex.evolution.one_of": "Um de:",
|
||||
"cobblemon.ui.pokedex.requirement.advancement.tooltip": "Jogador precisa ter a conquista %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.battle_critical_hits.tooltip": "Precisa acertar %1$s acertos críticos em batalha",
|
||||
"cobblemon.ui.pokedex.requirement.biome.anticondition.tooltip": "Não pode estar no bioma %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.biome.both.tooltip": "Precisa estar no bioma %1$s e não no bioma %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.biome.tooltip": "Precisa estar no bioma %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.blocks_traveled.tooltip": "Precisa viajar %1$s blocos",
|
||||
"cobblemon.ui.pokedex.requirement.damage_taken.tooltip": "Precisa receber %1$s de dano em uma batalha sem desmaiar",
|
||||
"cobblemon.ui.pokedex.requirement.defeat.tooltip": "Precisa derrotar %1$s em batalha para evoluir",
|
||||
"cobblemon.ui.pokedex.requirement.friendship.tooltip": "Requer no mínimo %1$s de amizade",
|
||||
"cobblemon.ui.pokedex.requirement.has_move.tooltip": "Precisa conhecer o movimento %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.has_move_type.tooltip": "Precisa conhecer um movimento do tipo %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.held_item.tooltip": "Precisa estar segurando %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.level.tooltip.min": "Evolui ao ultrapassar o nível %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.level.tooltip.between": "Evoluiu entre os níveis %1$s e %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.moon_phase.tooltip": "Precisa evoluir na fase %1$s da lua",
|
||||
"cobblemon.ui.pokedex.requirement.nature.toxtricity_amped": "Precisa ter a natureza §aDestemida§r, §aValente§r, §aRígida§r, §aTeimosa§r, §aDócil§r, §aInquieta§r, §aRelaxada§r, §aApressada§r, §aAlegre§r, §aInguênua§r, §aImprudente§r, §aAtrevida§r, ou §aPeculiar§r",
|
||||
"cobblemon.ui.pokedex.requirement.nature.toxtricity_low_key": "Precisa ter a natureza §aSolitária§r, §aCorajosa§r, §aDescontraída§r, §aTímida§r, §aSéria§r, §aModesta§r, §aMansa§r, §aQuieta§r, §aAtrapalhada§r, §aCalma§r, §aGentil§r, ou §aCuidadosa§r",
|
||||
"cobblemon.ui.pokedex.requirement.negate.tooltip": "Não: %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.nickname.malamar": "Precisa se chamar §aDinnerbone§r ou §aGrumm§r",
|
||||
"cobblemon.ui.pokedex.requirement.party_member.anticondition.tooltip": "Equipe não pode ter um Pokémon com %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.party_member.tooltip": "Equipe precisa ter um Pokémon com %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.pokemon_properties.tooltip": "Precisa estar %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.properties.and": "%1$s e %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.properties.custom.cocoon_species": "Casulo %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.properties.held_item": "Segurando %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.properties.int_feature": "%1$s %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.properties.nature": "Natureza %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.properties.nickname": "Nomeado %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.properties.type": "Tipo %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.property_range.tooltip": "Requer %1$s entre %2$s e %3$s",
|
||||
"cobblemon.ui.pokedex.requirement.recoil.tooltip": "Precisa sofrer %1$s unidades de recuo em batalha",
|
||||
"cobblemon.ui.pokedex.requirement.stat_compare.tooltip": "Precisa ter seu %1$s acima de %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.stat_equal.tooltip": "Precisa ter seu %1$s igual ao seu %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.structure.anticondition.tooltip": "Não pode estar na estrutura %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.structure.both.tooltip": "Precisa estar na estrutura %1$s e não na estrutura %2$s",
|
||||
"cobblemon.ui.pokedex.requirement.structure.tooltip": "Precisa estar na estrutura %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.time_range.tooltip": "Precisa evoluir durante %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.use_move.tooltip": "Precisa usar o movimento %1$s em batalha",
|
||||
"cobblemon.ui.pokedex.requirement.weather.tooltip.raining": "Precisa estar na chuva para evoluir",
|
||||
"cobblemon.ui.pokedex.requirement.weather.tooltip.thundering": "Precisa estar em uma tempestade para evoluir",
|
||||
"cobblemon.ui.moon_phase.full_moon": "Lua Cheia",
|
||||
"cobblemon.ui.moon_phase.waning_gibbous": "Crescente Gibosa",
|
||||
"cobblemon.ui.moon_phase.third_quarter": "Quarto Crescente",
|
||||
"cobblemon.ui.moon_phase.waning_crescent": "Crescente",
|
||||
"cobblemon.ui.moon_phase.new_moon": "Lua Nova",
|
||||
"cobblemon.ui.moon_phase.waxing_crescent": "Minguante",
|
||||
"cobblemon.ui.moon_phase.first_quarter": "Quarto Minguante",
|
||||
"cobblemon.ui.moon_phase.waxing_gibbous": "Minguante Gibosa",
|
||||
"cobblemon.ui.time_range.any": "Qualquer",
|
||||
"cobblemon.ui.time_range.day": "Dia",
|
||||
"cobblemon.ui.time_range.night": "Noite",
|
||||
"cobblemon.ui.time_range.noon": "Meio-dia",
|
||||
"cobblemon.ui.time_range.midnight": "Meia-noite",
|
||||
"cobblemon.ui.time_range.dawn": "Alvorecer",
|
||||
"cobblemon.ui.time_range.dusk": "Entardecer",
|
||||
"cobblemon.ui.time_range.twilight": "Crepúsculo",
|
||||
"cobblemon.ui.time_range.morning": "Manhã",
|
||||
"cobblemon.ui.time_range.afternoon": "Tarde",
|
||||
"cobblemon.ui.time_range.predawn": "Pré-amanhecer",
|
||||
"cobblemon.ui.time_range.evening": "Tardinha",
|
||||
"cobblemon.subtitle.item.bright_powder.use": "Pó Brilhante ilumina",
|
||||
"cobblemon.config.ui.type_gem_max_connected": "Máximo de Blocos de Gema de Tipo Conectados",
|
||||
"cobblemon.config.ui.type_gem_min_growth": "Mínimo de Crescimento de Gema de Tipo",
|
||||
"cobblemon.config.ui.type_gem_growth_chance": "Chance de Crescimento de Gema de Tipo",
|
||||
"cobblemon.config.ui.type_gem_initial_expansion_cycles": "Cíclos de Expansão Iniciais de Gemas de Tipo",
|
||||
"cobblemon.battle.activate.ficklebeam": "%1$s vai com tudo neste próximo ataque!",
|
||||
"tag.item.cobblemon.oricorio_flowers": "Flores de Néctar",
|
||||
"tag.item.cobblemon.terrain_plants": "Plantas de Terreno",
|
||||
"tag.item.cobblemon.tall_flowers": "Flores Altas",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.bergmite_hisuibiome": "Hisuiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.bergmite_kalosbiome": "Kalosiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.cubone_alolabiome": "Alolano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.cubone_kantobiome": "Kantoniano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.dartrix_alolabiome": "Alolano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.dartrix_hisuibiome": "Hisuiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.dewott_hisuibiome": "Hisuiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.dewott_unovabiome": "Unovano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.exeggcute_alolabiome": "Alolano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.exeggcute_kantobiome": "Kantoniano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.goomy_hisuibiome": "Hisuiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.goomy_kalosbiome": "Kalosiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.koffing_galarbiome": "Galariano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.koffing_kantobiome": "Kantoniano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.mimejr_galarbiome": "Galariano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.mimejr_sinnohbiome": "Sinnohano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.petilil_hisuibiome": "Hisuiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.petilil_unovabiome": "Unovano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.pikachu_alolabiome": "Alolano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.pikachu_kantobiome": "Kantoniano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.quilava_hisuibiome": "Hisuiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.quilava_johtobiome": "Johtoniano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.rufflet_hisuibiome": "Hisuiano",
|
||||
"tag.worldgen.biome.cobblemon.evolution.regional.rufflet_unovabiome": "Unovano"
|
||||
}
|
||||
|
||||
@@ -9021,5 +9021,34 @@
|
||||
"cobblemon.config.ui.world_spawning_blocklist.tooltip": "Миры, в которых отключается принцип появления покемонов.",
|
||||
"advancements.cobblemon.obtain_tm.description": "Найдите или напечатайте ТМ",
|
||||
"cobblemon.species.victreebel-mega.desc": "В результате Мега эволюции объём кислоты у этого покемона увеличился, заполняя весь его рот. Если он не будет осторожен, кислота переполнится и выльется наружу.",
|
||||
"cobblemon.ui.pokedex.info.form.victreebel-mega": "Мега Виктрибелл"
|
||||
"cobblemon.ui.pokedex.info.form.victreebel-mega": "Мега Виктрибелл",
|
||||
"itemGroup.cobblemon.tm_item": "Технические машины",
|
||||
"block.cobblemon.pomohana": "Помохана",
|
||||
"block.cobblemon.pauvillea": "Па'увилия",
|
||||
"block.cobblemon.lobaila": "Лобалия",
|
||||
"block.cobblemon.wistensu": "Вистенсу",
|
||||
"block.cobblemon.voltaconia": "Вольтакония",
|
||||
"block.cobblemon.verdroot": "Вердрут",
|
||||
"block.cobblemon.lucibell": "Люсибель",
|
||||
"block.cobblemon.mistleaf": "Мистлиф",
|
||||
"cobblemon.ui.pokedex.info.evolution_tree": "Древо эволюции",
|
||||
"cobblemon.ui.pokedex.evolution.item_interact.tooltip": "Требуется %1$s для эволюции",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_species": "Эволюционирует при обмене с %1$s",
|
||||
"cobblemon.ui.pokedex.evolution.trade.tooltip.with_any_species": "Эволюционирует при обмене",
|
||||
"cobblemon.ui.pokedex.evolution.shedder.tooltip": "Также требует запасной покебол и свободное место в команде",
|
||||
"cobblemon.ui.pokedex.evolution.or": "ИЛИ",
|
||||
"cobblemon.ui.pokedex.evolution.one_of": "Один из:",
|
||||
"cobblemon.ui.pokedex.requirement.advancement.tooltip": "У игрока должно быть достижение %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.battle_critical_hits.tooltip": "Должен попасть %1$s критическими ударами в битве",
|
||||
"cobblemon.ui.pokedex.requirement.biome.anticondition.tooltip": "Не должен быть в %1$s биоме",
|
||||
"cobblemon.ui.pokedex.requirement.biome.both.tooltip": "Должен быть в %1$s биоме и не в %2$s биоме",
|
||||
"cobblemon.ui.pokedex.requirement.biome.tooltip": "Должен быть в %1$s биоме",
|
||||
"cobblemon.ui.pokedex.requirement.blocks_traveled.tooltip": "Должен пройти %1$s блоков",
|
||||
"cobblemon.ui.pokedex.requirement.damage_taken.tooltip": "Должен получить %1$s урона в битве без поражения",
|
||||
"cobblemon.ui.pokedex.requirement.defeat.tooltip": "Должен победить против %1$s в битве для эволюции",
|
||||
"cobblemon.ui.pokedex.requirement.friendship.tooltip": "Требует как минимум %1$s дружбы",
|
||||
"cobblemon.ui.pokedex.requirement.has_move.tooltip": "Должен знать приём %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.has_move_type.tooltip": "Должен знать приём %1$s типа",
|
||||
"cobblemon.ui.pokedex.requirement.held_item.tooltip": "Должен удерживать %1$s",
|
||||
"cobblemon.ui.pokedex.requirement.level.tooltip.min": "Эволюционирует начиная с %1$s уровня"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user