forked from mirrors/cobblemon
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b79e73928a | ||
|
|
c89ea759a6 | ||
|
|
c6479525f9 | ||
|
|
2a7dababab | ||
|
|
7ec6e61d4a | ||
|
|
7735af5c11 | ||
|
|
18d25dcf04 | ||
|
|
e259dc18a2 | ||
|
|
7439436e93 | ||
|
|
1c51d5ca98 |
+2
-3
@@ -6,9 +6,8 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.transformation.requirements.template
|
||||
package com.cobblemon.mod.common.api.pokemon.transformation.requirement
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.TransformationRequirement
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -32,7 +31,7 @@ interface EntityQueryRequirement : TransformationRequirement {
|
||||
* Checks if the given [Pokemon] & [LivingEntity] satisfies the requirement.
|
||||
*
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @param queriedEntity The [LivingEntity] that can be compared in context of a [Level].
|
||||
* @param queriedEntity The [LivingEntity] that can be compared in context of a [net.minecraft.world.level.Level].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.transformation.requirement
|
||||
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* A [TransformationRequirement] that expects the [Pokemon] to have an owner.
|
||||
* It can be the [ServerPlayer] or the [NPCEntity] that owns it.
|
||||
*
|
||||
* Whenever an owner can't be resolved [TransformationRequirement.check] will never succeed.
|
||||
*
|
||||
* @author Polymeta
|
||||
* @since May 6th, 2025
|
||||
*/
|
||||
interface OwnerQueryRequirement : TransformationRequirement {
|
||||
override fun check(pokemon: Pokemon): Boolean {
|
||||
val owner = pokemon.getOwnerEntity() ?: return false
|
||||
return when (owner) {
|
||||
is ServerPlayer -> {
|
||||
this.checkPlayer(pokemon, owner)
|
||||
}
|
||||
is NPCEntity -> {
|
||||
this.checkNPC(pokemon, owner)
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] & [ServerPlayer] satisfies the requirement.
|
||||
*
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @param owner The [ServerPlayer] that owns this [Pokemon].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun checkPlayer(pokemon: Pokemon, owner: ServerPlayer): Boolean
|
||||
|
||||
/**
|
||||
* Checks if the given [Pokemon] & [NPCEntity] satisfies the requirement.
|
||||
* This method mainly exists as NPCs are different to players in a lot of ways (e.g., lack of advancements),
|
||||
* so they need to be handled differently, either by checking an NPC config or always returning true/false
|
||||
*
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @param owner The [NPCEntity] that owns this [Pokemon].
|
||||
* @return If the requirement was satisfied.
|
||||
*/
|
||||
fun checkNPC(pokemon: Pokemon, owner: NPCEntity): Boolean
|
||||
}
|
||||
@@ -127,7 +127,8 @@ data class MoveActionResponse(var moveName: String, var targetPnx: String? = nul
|
||||
// No PP or disabled or something
|
||||
return false
|
||||
}
|
||||
val availableTargets = (gimmickMove?.target ?: move.target).targetList(activeBattlePokemon)?.takeIf { it.isNotEmpty() } ?: return true
|
||||
val availableTargets = (if (gimmickID != null && validGimmickMove) gimmickMove.target else move.target)
|
||||
.targetList(activeBattlePokemon)?.takeIf { it.isNotEmpty() } ?: return true
|
||||
|
||||
val pnx = targetPnx ?: return false // If the targets list is non-null then they need to have specified a target
|
||||
val (_, targetPokemon) = activeBattlePokemon.actor.battle.getActorAndActiveSlotFromPNX(pnx)
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.cobblemon.mod.common.pokemon.Nature
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.transformation.form.TemporaryForm
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
@@ -44,6 +45,9 @@ open class BattlePokemon(
|
||||
val effectedPokemon = pokemon.clone()
|
||||
BattleCloneProperty.isBattleClone().apply(effectedPokemon)
|
||||
UncatchableProperty.uncatchable().apply(effectedPokemon)
|
||||
val shouldRevertForm = (effectedPokemon.form as? TemporaryForm)?.revertBeforeBattle ?: (effectedPokemon.form as? TemporaryForm)?.battleOnly ?: false
|
||||
if (shouldRevertForm)
|
||||
effectedPokemon.formProxy.server().revert()
|
||||
return BattlePokemon(
|
||||
originalPokemon = pokemon,
|
||||
effectedPokemon = effectedPokemon,
|
||||
@@ -51,13 +55,18 @@ open class BattlePokemon(
|
||||
)
|
||||
}
|
||||
|
||||
fun playerOwned(pokemon: Pokemon): BattlePokemon = BattlePokemon(
|
||||
originalPokemon = pokemon,
|
||||
effectedPokemon = pokemon,
|
||||
postBattleEntityOperation = { entity ->
|
||||
entity.effects.wipe()
|
||||
}
|
||||
)
|
||||
fun playerOwned(pokemon: Pokemon): BattlePokemon {
|
||||
val shouldRevertForm = (pokemon.form as? TemporaryForm)?.revertBeforeBattle ?: (pokemon.form as? TemporaryForm)?.battleOnly ?: false
|
||||
if (shouldRevertForm)
|
||||
pokemon.formProxy.server().revert()
|
||||
return BattlePokemon(
|
||||
originalPokemon = pokemon,
|
||||
effectedPokemon = pokemon,
|
||||
postBattleEntityOperation = { entity ->
|
||||
entity.effects.wipe()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val struct = QueryStruct(
|
||||
|
||||
@@ -14,7 +14,9 @@ import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.battles.ForcePassActionResponse
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.battles.PassActionResponse
|
||||
import com.cobblemon.mod.common.battles.ShowdownMoveset
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import java.util.UUID
|
||||
@@ -80,6 +82,10 @@ class ClientBattle(
|
||||
}
|
||||
}
|
||||
|
||||
fun pendingGimmick(gimmick: ShowdownMoveset.Gimmick): Boolean {
|
||||
return pendingActionRequests.none { (it.response as? MoveActionResponse)?.gimmickID == gimmick.id }
|
||||
}
|
||||
|
||||
fun getPokemonFromPNX(pnx: String): Pair<ClientBattleActor, ActiveClientBattlePokemon> {
|
||||
val actor = sides.flatMap { it.actors }.find { it.showdownId == pnx.substring(0, 2) }
|
||||
?: throw IllegalStateException("Invalid pnx: $pnx - unknown actor")
|
||||
|
||||
+15
-7
@@ -13,11 +13,11 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleGimmickButton.GimmickTile
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.math.toRGB
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
|
||||
@@ -30,7 +30,7 @@ import net.minecraft.sounds.SoundEvents
|
||||
* @author Segfault Guy
|
||||
* @since July 8th, 2023
|
||||
*/
|
||||
abstract class BattleGimmickButton(gimmick: ShowdownMoveset.Gimmick, val x: Float, val y: Float) {
|
||||
abstract class BattleGimmickButton(val gimmick: ShowdownMoveset.Gimmick, val x: Float, val y: Float) {
|
||||
|
||||
companion object {
|
||||
const val WIDTH = 36
|
||||
@@ -61,24 +61,32 @@ abstract class BattleGimmickButton(gimmick: ShowdownMoveset.Gimmick, val x: Floa
|
||||
var toggled = false
|
||||
private val sfx = SimpleSoundInstance.forUI(SoundEvents.ANVIL_LAND, 1.0F)
|
||||
private val texture = gimmick.id
|
||||
val selectable: Boolean
|
||||
get() {
|
||||
val battle = CobblemonClient.battle ?: return false
|
||||
return battle.pendingGimmick(gimmick)
|
||||
}
|
||||
|
||||
fun render(matrices: PoseStack, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
fun render(graphics: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
matrixStack = graphics.pose(),
|
||||
texture = cobblemonResource("textures/gui/battle/battle_gimmick_${texture}.png"),
|
||||
x = x * 2,
|
||||
y = y * 2,
|
||||
height = HEIGHT,
|
||||
width = WIDTH,
|
||||
vOffset = if (toggled || isHovered(mouseX.toDouble(), mouseY.toDouble())) HEIGHT else 0,
|
||||
vOffset = if ((toggled || isHovered(mouseX.toDouble(), mouseY.toDouble()) && selectable)) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2,
|
||||
scale = SCALE
|
||||
scale = SCALE,
|
||||
alpha = if (selectable) 1.0F else 0.5F
|
||||
)
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX >= x && mouseX <= x + XOFF && mouseY >= y && mouseY <= y + YOFF
|
||||
|
||||
fun toggle(): Boolean {
|
||||
if (!selectable)
|
||||
return toggled
|
||||
toggled = !toggled
|
||||
Minecraft.getInstance().soundManager.play(sfx)
|
||||
return toggled
|
||||
|
||||
+11
-11
@@ -74,7 +74,8 @@ class BattleMoveSelection(
|
||||
BattleGimmickButton.create(gimmick, this, backButton.x + xOff, backButton.y)
|
||||
}
|
||||
|
||||
val shiftButton = BattleShiftButton(x + 22.5F, Minecraft.getInstance().window.guiScaledHeight - 22F )
|
||||
val shiftButton = if (request.activePokemon.getFormat().battleType.slotsPerActor == 3 && (request.activePokemon.getPNX()[2] == 'a' || request.activePokemon.getPNX()[2] == 'c'))
|
||||
BattleShiftButton(x + 22.5F, Minecraft.getInstance().window.guiScaledHeight - 22F ) else null
|
||||
|
||||
open class MoveTile(
|
||||
val moveSelection: BattleMoveSelection,
|
||||
@@ -190,31 +191,30 @@ class BattleMoveSelection(
|
||||
}
|
||||
backButton.render(context, mouseX, mouseY, delta)
|
||||
gimmickButtons.forEach {
|
||||
it.render(context.pose(), mouseX, mouseY, delta)
|
||||
}
|
||||
if(this.request.activePokemon.getFormat().battleType.slotsPerActor == 3 && (request.activePokemon.getPNX()[2] == 'a' || request.activePokemon.getPNX()[2] == 'c')) {
|
||||
shiftButton.render(context, mouseX, mouseY, delta)
|
||||
it.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
shiftButton?.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
|
||||
override fun mousePrimaryClicked(mouseX: Double, mouseY: Double): Boolean {
|
||||
val move = moveTiles.find { it.isHovered(mouseX, mouseY) }
|
||||
val gimmick = gimmickButtons.find { it.isHovered(mouseX, mouseY) }
|
||||
if (move != null) {
|
||||
if(this.request.activePokemon.getFormat().battleType.pokemonPerSide == 1) {
|
||||
if (this.request.activePokemon.getFormat().battleType.pokemonPerSide == 1) {
|
||||
move.onClick()
|
||||
} else {
|
||||
battleGUI.changeActionSelection(BattleTargetSelection(battleGUI, request, move.move))
|
||||
return true
|
||||
} else if (move.selectable) {
|
||||
battleGUI.changeActionSelection(BattleTargetSelection(battleGUI, request, move.move, move.response.gimmickID, move.move.gimmickMove))
|
||||
playDownSound(Minecraft.getInstance().soundManager)
|
||||
return true
|
||||
}
|
||||
return true
|
||||
} else if (backButton.isHovered(mouseX, mouseY)) {
|
||||
playDownSound(Minecraft.getInstance().soundManager)
|
||||
battleGUI.changeActionSelection(null)
|
||||
} else if (gimmick != null) {
|
||||
} else if (gimmick != null && gimmick.selectable) {
|
||||
gimmickButtons.filter { it != gimmick }.forEach { it.toggled = false }
|
||||
moveTiles = if (gimmick.toggle()) gimmick.tiles else baseTiles
|
||||
} else if(shiftButton.isHovered(mouseX,mouseY)) {
|
||||
} else if (shiftButton?.isHovered(mouseX,mouseY) == true) {
|
||||
playDownSound(Minecraft.getInstance().soundManager)
|
||||
battleGUI.selectAction(request, ShiftActionResponse())
|
||||
}
|
||||
|
||||
+10
-8
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.battles.InBattleGimmickMove
|
||||
import com.cobblemon.mod.common.battles.InBattleMove
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
@@ -22,7 +23,6 @@ import com.cobblemon.mod.common.client.battle.ActiveClientBattlePokemon
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleSwitchPokemonSelection.Companion
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
@@ -41,9 +41,11 @@ import kotlin.math.floor
|
||||
import kotlin.math.sin
|
||||
|
||||
class BattleTargetSelection(
|
||||
battleGUI: BattleGUI,
|
||||
request: SingleActionRequest,
|
||||
val move: InBattleMove
|
||||
battleGUI: BattleGUI,
|
||||
request: SingleActionRequest,
|
||||
val move: InBattleMove,
|
||||
val gimmickID: String?,
|
||||
gimmickMove: InBattleGimmickMove?
|
||||
) : BattleActionSelection(
|
||||
battleGUI = battleGUI,
|
||||
request = request,
|
||||
@@ -80,10 +82,10 @@ class BattleTargetSelection(
|
||||
}
|
||||
|
||||
val targets = request.activePokemon.getAllActivePokemon()
|
||||
|
||||
val targetType = if (gimmickID != null && gimmickMove != null) gimmickMove.target else move.target
|
||||
val backButton = BattleBackButton(x + 9F, Minecraft.getInstance().window.guiScaledHeight - 22F)
|
||||
val selectableTargetList = move.target.targetList(request.activePokemon)
|
||||
val multiTargetList = if(selectableTargetList == null) request.activePokemon.getMultiTargetList(move.target) else null
|
||||
val selectableTargetList = targetType.targetList(request.activePokemon)
|
||||
val multiTargetList = if(selectableTargetList == null) request.activePokemon.getMultiTargetList(targetType) else null
|
||||
|
||||
val baseTiles = targets.mapIndexed { index, target ->
|
||||
val isAlly = target.isAllied(request.activePokemon)
|
||||
@@ -123,7 +125,7 @@ class BattleTargetSelection(
|
||||
private val isMultiTarget = multiTargetList?.firstOrNull { it.getPNX() == target.getPNX() } != null
|
||||
private val isCurrentPokemon = request.activePokemon.battlePokemon?.uuid == target.battlePokemon!!.uuid
|
||||
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget)
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget, targetSelection.gimmickID)
|
||||
val state = FloatingState()
|
||||
|
||||
open val selectable: Boolean get() = isMultiTarget || (responseTarget != null)
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -67,12 +68,12 @@ object TestCommand {
|
||||
try {
|
||||
//this.testCodecOutput(context)
|
||||
val player = context.source.entity as ServerPlayer
|
||||
player.party().forEach { it.currentHealth = it.hp / 2 }
|
||||
val npc = NPCEntity(player.level())
|
||||
npc.setPos(player.x, player.y, player.z)
|
||||
npc.npc = NPCClasses.getByName("standard")!!
|
||||
npc.initialize(50)
|
||||
player.level().addFreshEntity(npc)
|
||||
//player.party().forEach { it.currentHealth = it.hp / 2 }
|
||||
//val npc = NPCEntity(player.level())
|
||||
//npc.setPos(player.x, player.y, player.z)
|
||||
//npc.npc = NPCClasses.getByName("standard")!!
|
||||
//npc.initialize(50)
|
||||
//player.level().addFreshEntity(npc)
|
||||
// val evolutionEntity = GenericBedrockEntity(world = player.level())
|
||||
// evolutionEntity.apply {
|
||||
// category = cobblemonResource("evolution")
|
||||
@@ -126,6 +127,20 @@ object TestCommand {
|
||||
|
||||
// val player = context.source.entity as ServerPlayerEntity
|
||||
// player.giveItemStack(PokemonItem.from(PokemonSpecies.random(), "alolan"))
|
||||
val npcs = player.level().getEntities(player, player.boundingBox.inflate(20.0)) { it is NPCEntity }
|
||||
.map { NPCBattleActor(it as NPCEntity, it.getPartyForChallenge(listOf(player))!!, 0) }
|
||||
.sortedBy { player.distanceToSqr(it.entity) }
|
||||
|
||||
val playerTeam = player.party().toBattleTeam()
|
||||
val playerActor = PlayerBattleActor(player.uuid, playerTeam)
|
||||
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = BattleFormat.GEN_9_MULTI,
|
||||
side1 = BattleSide(playerActor, npcs[0]),
|
||||
side2 = BattleSide(npcs[1], npcs[2])
|
||||
).ifSuccessful {
|
||||
it.battlePartyStores.add(player.party())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error(e)
|
||||
}
|
||||
|
||||
@@ -1146,7 +1146,8 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
/** Revolves the [RegistryAccess] associated with this pokemon, if one exists. */
|
||||
val registryAccess: RegistryAccess
|
||||
@Throws(IllegalStateException::class)
|
||||
get() = this.getOwnerEntity()?.registryAccess()
|
||||
get() = this.entity?.registryAccess()
|
||||
?: this.getOwnerEntity()?.registryAccess()
|
||||
?: server()?.registryAccess()
|
||||
?: throw IllegalStateException("No registry access available")
|
||||
|
||||
|
||||
+2
-1
@@ -56,8 +56,9 @@ object CobblemonRequirementAdapter : RequirementAdapter {
|
||||
this.registerType(StructureRequirement.ADAPTER_VARIANT, StructureRequirement::class)
|
||||
this.registerType(AnyRequirement.ADAPTER_VARIANT, AnyRequirement::class)
|
||||
this.registerType(PropertyRangeRequirement.ADAPTER_VARIANT, PropertyRangeRequirement::class)
|
||||
this.registerType(PlayerHasAdvancementRequirement.ADAPTER_VARIANT, PlayerHasAdvancementRequirement::class)
|
||||
this.registerType(AdvancementRequirement.ADAPTER_VARIANT, AdvancementRequirement::class)
|
||||
this.registerType(HealthRequirement.ADAPTER_VARIANT, HealthRequirement::class)
|
||||
this.registerType(KeyItemRequirement.ADAPTER_VARIANT, KeyItemRequirement::class)
|
||||
}
|
||||
|
||||
override fun <T : TransformationRequirement> registerType(id: String, type: KClass<T>) {
|
||||
|
||||
+3
-1
@@ -39,6 +39,8 @@ import net.minecraft.resources.ResourceLocation
|
||||
open class TemporaryForm (
|
||||
/** Whether this form is triggered during a battle. */
|
||||
val battleOnly: Boolean = false,
|
||||
/** Whether this form has to be reverted before a battle begins. If null, [battleOnly] is used **/
|
||||
val revertBeforeBattle: Boolean? = null,
|
||||
/** Whether this form can be freely toggled after requirements are initially met. */
|
||||
val toggleable: Boolean = false,
|
||||
/** */
|
||||
@@ -83,7 +85,7 @@ open class TemporaryForm (
|
||||
*/
|
||||
override fun start(pokemon: Pokemon, context: ContextTrigger.Context?): Boolean {
|
||||
if (this.test(pokemon, context)) {
|
||||
return if (this.optional)
|
||||
return if (this.optional || this.toggleable)
|
||||
pokemon.formProxy.server().add(this)
|
||||
else {
|
||||
this.forceStart(pokemon)
|
||||
|
||||
+13
-8
@@ -10,22 +10,22 @@ package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.TransformationRequirement
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.OwnerQueryRequirement
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import kotlin.collections.iterator
|
||||
|
||||
/**
|
||||
* A [TransformationRequirement] that checks if the player has a certain [Advancement]
|
||||
* A [TransformationRequirement] that checks if the player has a certain [net.minecraft.advancements.Advancement]
|
||||
*
|
||||
* @param requiredAdvancement The [ResourceLocation] of the required advancement
|
||||
*
|
||||
* @author whatsy
|
||||
* @author whatsy, Polymeta
|
||||
*/
|
||||
class PlayerHasAdvancementRequirement(val requiredAdvancement: ResourceLocation) : EntityQueryRequirement {
|
||||
override fun check(pokemon: Pokemon, queriedEntity: LivingEntity): Boolean {
|
||||
val player = queriedEntity as? ServerPlayer ?: return false
|
||||
for (entry in player.advancements.progress) {
|
||||
class AdvancementRequirement(val requiredAdvancement: ResourceLocation) : OwnerQueryRequirement {
|
||||
override fun checkPlayer(pokemon: Pokemon, owner: ServerPlayer): Boolean {
|
||||
for (entry in owner.advancements.progress) {
|
||||
if (entry.key.id == requiredAdvancement && entry.value.isDone) {
|
||||
return true
|
||||
}
|
||||
@@ -33,6 +33,11 @@ class PlayerHasAdvancementRequirement(val requiredAdvancement: ResourceLocation)
|
||||
return false
|
||||
}
|
||||
|
||||
override fun checkNPC(pokemon: Pokemon, owner: NPCEntity): Boolean {
|
||||
//TODO some sort of config potentially on the NPC itself
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ADAPTER_VARIANT = "advancement"
|
||||
}
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.EntityQueryRequirement
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.EntityQueryRequirement
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.OwnerQueryRequirement
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.hasKeyItem
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* A [OwnerQueryRequirement] that checks if the player has a certain "key item". Key items are not real items,
|
||||
* but can be awarded (and removed) at free will of cobblemon or 3rd party mods.
|
||||
*
|
||||
* @property requiredKeyItem The key item the player needs to have, for example `cobblemon:z_ring` or `cobblemon:key_stone` for Z-Moves and Mega evolutions respectively
|
||||
*
|
||||
* @author Polymeta
|
||||
* @since May 6th, 2025
|
||||
*/
|
||||
class KeyItemRequirement(val requiredKeyItem: ResourceLocation) : OwnerQueryRequirement {
|
||||
override fun checkPlayer(pokemon: Pokemon, owner: ServerPlayer): Boolean {
|
||||
return owner.hasKeyItem(requiredKeyItem)
|
||||
}
|
||||
|
||||
override fun checkNPC(pokemon: Pokemon, owner: NPCEntity): Boolean {
|
||||
//TODO some sort of config potentially on the NPC itself
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ADAPTER_VARIANT = "key_item"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.spawning.condition.MoonPhase
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.EntityQueryRequirement
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.EntityQueryRequirement
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.level.levelgen.structure.Structure
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.TransformationRequirement
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.EntityQueryRequirement
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.EntityQueryRequirement
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
package com.cobblemon.mod.common.pokemon.transformation.requirements
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.transformation.requirements.template.EntityQueryRequirement
|
||||
import com.cobblemon.mod.common.api.pokemon.transformation.requirement.EntityQueryRequirement
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.level.Level
|
||||
|
||||
+20
-2
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
@@ -15,15 +16,27 @@ import com.google.gson.JsonSerializationContext
|
||||
import com.google.gson.JsonSerializer
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.RegistryOps
|
||||
import java.lang.reflect.Type
|
||||
import java.util.stream.Stream
|
||||
|
||||
class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSerializer<T> {
|
||||
val fallbackRegistry: RegistryOps<JsonElement> = RegistryOps.create(JsonOps.INSTANCE,
|
||||
HolderLookup.Provider.create(Stream.of(BuiltInRegistries.ITEM.asLookup())))
|
||||
|
||||
override fun deserialize(
|
||||
jElement: JsonElement,
|
||||
typeOfT: Type,
|
||||
context: JsonDeserializationContext
|
||||
): T {
|
||||
return JsonOps.INSTANCE.withDecoder(codec).apply(jElement).result().get().first as T
|
||||
val ops = if (server() != null) {
|
||||
server()!!.registryAccess().createSerializationContext(JsonOps.INSTANCE)
|
||||
} else {
|
||||
fallbackRegistry
|
||||
}
|
||||
return ops.withDecoder(codec).apply(jElement).result().get().first as T
|
||||
}
|
||||
|
||||
override fun serialize(
|
||||
@@ -31,6 +44,11 @@ class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSeri
|
||||
typeOfSrc: Type?,
|
||||
context: JsonSerializationContext?
|
||||
): JsonElement {
|
||||
return JsonOps.INSTANCE.withEncoder(codec).apply(src).result().get()
|
||||
val ops = if (server() != null) {
|
||||
server()!!.registryAccess().createSerializationContext(JsonOps.INSTANCE)
|
||||
} else {
|
||||
fallbackRegistry
|
||||
}
|
||||
return ops.withEncoder(codec).apply(src).result().get()
|
||||
}
|
||||
}
|
||||
@@ -520,7 +520,7 @@
|
||||
"description": "The form's nested temporary forms",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"type": "object"
|
||||
},
|
||||
"_permanentOnly": "This field is applicable to permanent forms only"
|
||||
},
|
||||
|
||||
@@ -322,6 +322,8 @@
|
||||
{
|
||||
"name": "Mega",
|
||||
"primaryType": "rock",
|
||||
"variant": "temporary",
|
||||
"toggleable": true,
|
||||
"secondaryType": "flying",
|
||||
"maleRatio": 0.875,
|
||||
"height": 21,
|
||||
@@ -329,6 +331,18 @@
|
||||
"pokedex": [
|
||||
"cobblemon.species.aerodactyl-mega.desc"
|
||||
],
|
||||
"requirements": [
|
||||
{
|
||||
"variant": "held_item",
|
||||
"itemCondition": {
|
||||
"items": ["minecraft:glowstone"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"variant": "key_item",
|
||||
"requiredKeyItem": "cobblemon:key_stone"
|
||||
}
|
||||
],
|
||||
"labels": [
|
||||
"gen6",
|
||||
"mega",
|
||||
|
||||
Reference in New Issue
Block a user