Compare commits

...
Author SHA1 Message Date
Kiritiop b4c40dad62 Merge branch 'item-2067' of gitlab.com:cable-mc/cobblemon into item-2067 2026-10-11 05:09:12 -04:00
Kiritiop a13ba8a03d Fixed Illusion, Imposter and Transform overwriting the party Pokémon's species and not copying the target's size 2026-10-11 09:07:19 +00:00
Kiritiop d8a683abb9 Manual rebase 2026-10-11 04:41:58 -04:00
Kiritiop 025d8d582a Merge branch 'item-2067' of gitlab.com:cable-mc/cobblemon into item-2067
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/entity/pokemon/PokemonServerDelegate.kt
2026-09-16 01:53:54 -04:00
Kiritiop 90d992d5f3 Rebase 2026-09-16 01:49:17 -04:00
Kiritiop d00c7d4c50 Reverted the ALPHA and SCALE_MODIFIER extractors, copying effectiveScale into the mock instead 2026-09-16 01:48:58 -04:00
Kiritiop e89ed83d5e Added a comment explaining why ALPHA is copied alongside SCALE_MODIFIER 2026-09-16 01:35:09 -04:00
Kiritiop b31b856eb4 Fixed Illusion, Imposter and Transform not copying the target's size and alpha status
Closes #2074
2026-09-16 05:12:20 +00:00
Kiritiop 84ff3d649c Fixed Illusion, Imposter and Transform overwriting the party Pokémon's species on the client
Closes #2067
2026-09-16 05:12:20 +00:00
Kiritiop 5a1bf68670 Fixed Illusion, Imposter and Transform not copying the target's size and alpha status
Closes #2074
2026-09-11 12:41:17 -04:00
Kiritiop 4d827958fd Fixed Illusion, Imposter and Transform overwriting the party Pokémon's species on the client
Closes #2067
2026-09-10 13:48:30 -04:00
6 changed files with 48 additions and 7 deletions
+3
View File
@@ -28,6 +28,9 @@
- Fixed the Pokédex evolution tree crashing with a stack overflow on evolutions that loop back on themselves.
- Fixed form-changing evolutions sometimes resolving to the source form in the Pokédex evolution tree.
- Broken datapack evolutions are now logged and skipped in the Pokédex evolution tree instead of crashing.
- Fixed Illusion, Imposter and Transform overwriting the species, form and EXP group of the owner's party Pokémon on the client, which made its level and HP display incorrectly and could leave the copied form showing in the party after battle
- Fixed Illusion, Imposter and Transform not copying the size and alpha status of the Pokémon they turn into, which made disguises keep their original size
### Developer
@@ -64,6 +64,8 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
const val SHINY_PARTICLE_COOLDOWN = 3.5F
}
var storedPokemon: Pokemon? = null
override val schedulingTracker: SchedulingTracker
get() = currentEntity.schedulingTracker
@@ -108,8 +110,18 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
if (this::currentEntity.isInitialized) {
if (data == PokemonEntity.SPECIES) {
val identifier = ResourceLocation.parse(currentEntity.entityData.get(PokemonEntity.SPECIES))
val species = PokemonSpecies.getByIdentifier(identifier)!! // TODO exception handling
val stored = storedPokemon
if (stored != null) {
val disguised = species != stored.species && currentEntity.battleId != null
if (disguised) {
if (currentEntity.pokemon === stored) currentEntity.pokemon = renderCopy(stored)
} else if (currentEntity.pokemon !== stored) {
currentEntity.pokemon = stored
}
}
currentPose = null
currentEntity.pokemon.species = PokemonSpecies.getByIdentifier(identifier)!! // TODO exception handling
currentEntity.pokemon.species = species
// force a model update - handles edge case where the PosableState's tracked PosableModel isn't updated until the LivingEntityRenderer render is run
currentModel = VaryingModelRepository.getPoser(identifier, this)
currentEntity.refreshRiding()
@@ -355,6 +367,22 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
pokemon.isClient = true
}
private fun renderCopy(source: Pokemon) = Pokemon().apply {
isClient = true
uuid = source.uuid
scaleModifier = source.scaleModifier
species = source.species
form = source.form
gender = source.gender
shiny = source.shiny
forcedAspects = source.forcedAspects
nickname = source.nickname
activeMark = source.activeMark
caughtBall = source.caughtBall
isAlpha = source.isAlpha
level = source.level
}
override fun addToStruct(struct: QueryStruct) {
super.addToStruct(struct)
struct.addFunctions(ClientMoLangFunctions.clientFunctions)
@@ -232,14 +232,15 @@ class PokemonServerDelegate : PokemonSideDelegate {
val trackedAspects = mock?.aspects ?: entity.pokemon.aspects
val trackedBall = mock?.pokeball ?: entity.pokemon.caughtBall.name.toString()
val trackedScaleModifier = mock?.scaleModifier ?: entity.pokemon.effectiveScale
val trackedAlpha = mock?.let { it.isAlpha == true } ?: entity.pokemon.isAlpha
entity.ownerUUID = entity.pokemon.getOwnerUUID()
entity.entityData.set(PokemonEntity.SPECIES, trackedSpecies)
if (entity.entityData.get(PokemonEntity.NICKNAME) != trackedNickname) {
entity.entityData.set(PokemonEntity.NICKNAME, trackedNickname)
}
if (entity.entityData.get(PokemonEntity.IS_ALPHA) != entity.pokemon.isAlpha) {
entity.entityData.set(PokemonEntity.IS_ALPHA, entity.pokemon.isAlpha)
if (entity.entityData.get(PokemonEntity.IS_ALPHA) != trackedAlpha) {
entity.entityData.set(PokemonEntity.IS_ALPHA, trackedAlpha)
}
entity.entityData.set(PokemonEntity.ASPECTS, trackedAspects)
entity.entityData.set(PokemonEntity.LABEL_LEVEL, entity.pokemon.level)
@@ -38,7 +38,8 @@ class IllusionEffect(
) : BattleEffect(), MocKEffect {
constructor(disguise: Pokemon) : this(
mock = disguise.createPokemonProperties(PokemonPropertyExtractor.ILLUSION),
// effectiveScale is used instead of scaleModifier so alpha sized disguises are copied without copying the alpha flag itself
mock = disguise.createPokemonProperties(PokemonPropertyExtractor.ILLUSION).also { it.scaleModifier = disguise.effectiveScale },
scale = disguise.form.baseScale * disguise.effectiveScale
)
@@ -35,7 +35,8 @@ class TransformEffect(
) : BattleEffect(), MocKEffect {
constructor(mimic: Pokemon, doCry: Boolean = true) : this(
mock = mimic.createPokemonProperties(PokemonPropertyExtractor.TRANSFORM),
// effectiveScale is used instead of scaleModifier so alpha sized targets are copied without copying the alpha flag itself
mock = mimic.createPokemonProperties(PokemonPropertyExtractor.TRANSFORM).also { it.scaleModifier = mimic.effectiveScale },
scale = mimic.form.baseScale * mimic.effectiveScale,
doCry = doCry
)
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
@@ -74,7 +75,7 @@ class SpawnPokemonPacket(
entity.ownerUUID,
entity.pokemon.uuid,
entity.pokemon.storeCoordinates.get()?.store?.uuid,
entity.pokemon.scaleModifier,
entity.entityData.get(PokemonEntity.SCALE_MODIFIER),
entity.exposedSpecies.resourceIdentifier,
entity.pokemon.gender,
entity.pokemon.shiny,
@@ -147,7 +148,13 @@ class SpawnPokemonPacket(
this@SpawnPokemonPacket.storageUUID?.let {
val storedPokemon = CobblemonClient.storage.locatePokemon(it, this@SpawnPokemonPacket.pokemonUUID)
if (storedPokemon != null) {
entity.pokemon = storedPokemon
(entity.delegate as? PokemonClientDelegate)?.storedPokemon = storedPokemon
val disguised = this@SpawnPokemonPacket.battleId != null &&
(storedPokemon.species.resourceIdentifier != this@SpawnPokemonPacket.speciesId ||
storedPokemon.form.formOnlyShowdownId() != this@SpawnPokemonPacket.formName)
if (!disguised) {
entity.pokemon = storedPokemon
}
}
}