forked from mirrors/cobblemon
Compare commits
19
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53ef2cf098 | ||
|
|
024d9ededf | ||
|
|
0a7deedeea | ||
|
|
9d86fd4530 | ||
|
|
66b9a2a0b8 | ||
|
|
8e1b420b3a | ||
|
|
3f969b7003 | ||
|
|
0009c83331 | ||
|
|
f4c80cf77d | ||
|
|
562ed04c68 | ||
|
|
2175dd5b92 | ||
|
|
b8ec624ba1 | ||
|
|
11d6fd0637 | ||
|
|
68ece4cd96 | ||
|
|
0eebba6604 | ||
|
|
d0484c31ff | ||
|
|
658564f8c1 | ||
|
|
c95a44039e | ||
|
|
b0f0c20404 |
+8
@@ -9,8 +9,10 @@
|
||||
package com.cobblemon.mod.common.compat.lambdynamiclights;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.client.particle.MoveDynamicLights;
|
||||
import dev.lambdaurora.lambdynlights.api.DynamicLightsContext;
|
||||
import dev.lambdaurora.lambdynlights.api.DynamicLightsInitializer;
|
||||
import dev.lambdaurora.lambdynlights.api.behavior.DynamicLightBehaviorManager;
|
||||
import dev.lambdaurora.lambdynlights.api.entity.luminance.EntityLuminance;
|
||||
import dev.lambdaurora.lambdynlights.api.item.ItemLightSourceManager;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -33,6 +35,12 @@ public class LambDynamicLightsInitializer implements DynamicLightsInitializer {
|
||||
context.entityLightSourceManager().onRegisterEvent().register(ctx -> {
|
||||
ctx.register(EntityType.PLAYER, PlayerLuminance.INSTANCE);
|
||||
});
|
||||
|
||||
// Attach a monochrome dynamic light to each glowing particle. The light follows its particle and
|
||||
// reports isRemoved() when the particle dies, so the manager cleans it up. The cap on how many
|
||||
// particles per emitter may be lit at once is enforced at particle spawn, not here.
|
||||
final DynamicLightBehaviorManager behaviorManager = context.dynamicLightBehaviorManager();
|
||||
MoveDynamicLights.setSink(particle -> behaviorManager.add(new SnowstormParticleLight(particle)));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"removal", "UnstableApiUsage"})
|
||||
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.compat.lambdynamiclights;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.SnowstormParticle;
|
||||
import dev.lambdaurora.lambdynlights.api.behavior.DynamicLightBehavior;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
/**
|
||||
* A real, monochrome dynamic light attached to a single Cobblemon particle, so each glowing particle
|
||||
* lights the world around it like its own light source. The level is whatever the particle currently
|
||||
* emits ({@link SnowstormParticle#currentLightLevel()}); a particle emitting 0 contributes nothing.
|
||||
*
|
||||
* <p>How many of these exist per emitter is capped (by the maxLitParticlesPerEmitter config, enforced
|
||||
* at particle spawn, not here). This follows the particle as it moves and removes itself when it dies.</p>
|
||||
*
|
||||
* <p>Only instantiated by {@link LambDynamicLightsInitializer} (the LambDynamicLights entrypoint), so
|
||||
* it is never loaded unless LambDynamicLights is installed.</p>
|
||||
*/
|
||||
public final class SnowstormParticleLight implements DynamicLightBehavior {
|
||||
private static final int MAX_LUMINANCE = 15;
|
||||
|
||||
private final SnowstormParticle particle;
|
||||
private int prevX = Integer.MIN_VALUE;
|
||||
private int prevY = Integer.MIN_VALUE;
|
||||
private int prevZ = Integer.MIN_VALUE;
|
||||
private int prevLuminance = -1;
|
||||
/** Level cached each tick in hasChanged() so the per block lightAtPos call stays cheap and stable. */
|
||||
private double cachedLuminance;
|
||||
|
||||
public SnowstormParticleLight(SnowstormParticle particle) {
|
||||
this.particle = particle;
|
||||
this.cachedLuminance = Math.min(MAX_LUMINANCE, particle.currentLightLevel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double lightAtPos(BlockPos pos, double falloffRatio) {
|
||||
double lum = cachedLuminance;
|
||||
if (lum <= 0.0) return 0.0;
|
||||
double dx = pos.getX() + 0.5 - particle.getX();
|
||||
double dy = pos.getY() + 0.5 - particle.getY();
|
||||
double dz = pos.getZ() + 0.5 - particle.getZ();
|
||||
double dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
// Lose exactly 1 level per block so an authored level of N lights about N blocks, like vanilla
|
||||
// block light. We intentionally ignore the falloffRatio LambDynamicLights passes (15 / MAX_RADIUS,
|
||||
// about 1.94): applying it would compress the falloff into the mod's 7.75 block cap and make every
|
||||
// light reach only about half its level in blocks, looking dimmer than the number implies. The mod
|
||||
// still limits reach to MAX_RADIUS (about 7.75 blocks), so levels above 8 are clipped there.
|
||||
return Math.max(0.0, lum - dist);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicLightBehavior.BoundingBox getBoundingBox() {
|
||||
// Report only the emitting volume (the particle's own block); the API expands it by falloff.
|
||||
int x = (int) Math.floor(particle.getX());
|
||||
int y = (int) Math.floor(particle.getY());
|
||||
int z = (int) Math.floor(particle.getZ());
|
||||
return new DynamicLightBehavior.BoundingBox(x, y, z, x + 1, y + 1, z + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChanged() {
|
||||
int x = (int) Math.floor(particle.getX());
|
||||
int y = (int) Math.floor(particle.getY());
|
||||
int z = (int) Math.floor(particle.getZ());
|
||||
int lum = Math.min(MAX_LUMINANCE, particle.currentLightLevel());
|
||||
boolean changed = x != prevX || y != prevY || z != prevZ || lum != prevLuminance;
|
||||
if (changed) {
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
prevZ = z;
|
||||
prevLuminance = lum;
|
||||
cachedLuminance = lum;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemoved() {
|
||||
return !particle.isAlive();
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,26 @@ class BedrockParticle(
|
||||
var tinting: ParticleTinting = ExpressionParticleTinting(),
|
||||
var collision: ParticleCollision = ParticleCollision(),
|
||||
var environmentLighting: Boolean = false,
|
||||
/**
|
||||
* Block light level (0..15) each particle of this type emits into the world via LambDynamicLights.
|
||||
* A particle existing does not imply light: only particles whose resolved level is above 0 emit.
|
||||
* This is the flat level, used when [lightEmissionFrames] is empty.
|
||||
*/
|
||||
var lightEmission: Int = 0,
|
||||
/**
|
||||
* Optional light levels (0..15) indexed by the particle's current flipbook frame. When non empty it
|
||||
* overrides [lightEmission] so a particle can light differently per frame; frames beyond the array
|
||||
* clamp to its ends. Empty means use the flat [lightEmission].
|
||||
*/
|
||||
var lightEmissionFrames: List<Int> = emptyList(),
|
||||
var creationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var expirationEvents: MutableList<SimpleEventTrigger> = mutableListOf(),
|
||||
var timeline: EventTriggerTimeline = EventTriggerTimeline(mutableMapOf())
|
||||
) {
|
||||
/** True when this particle type emits block light at all, via the flat level or any per frame level. */
|
||||
val emitsLight: Boolean
|
||||
get() = lightEmission > 0 || lightEmissionFrames.any { it > 0 }
|
||||
|
||||
class ExpressionSet(
|
||||
val sizeX: Expression,
|
||||
val sizeY: Expression,
|
||||
@@ -113,6 +129,8 @@ class BedrockParticle(
|
||||
ParticleTinting.codec.fieldOf("tinting").forGetter { it.tinting },
|
||||
ParticleCollision.CODEC.fieldOf("collision").forGetter { it.collision },
|
||||
PrimitiveCodec.BOOL.fieldOf("environmentLighting").forGetter { it.environmentLighting },
|
||||
Codec.INT.optionalFieldOf("lightEmission", 0).forGetter { it.lightEmission },
|
||||
Codec.INT.listOf().optionalFieldOf("lightEmissionFrames", emptyList()).forGetter { it.lightEmissionFrames },
|
||||
EVENT_SET_CODEC.fieldOf("eventSet").forGetter {
|
||||
EventSet(
|
||||
it.creationEvents,
|
||||
@@ -121,7 +139,7 @@ class BedrockParticle(
|
||||
)
|
||||
}
|
||||
).apply(instance) {
|
||||
texture, materialStr, uvMode, expressionSet, motion, rotation, viewDirection, cameraMode, tinting, collision, environmentLighting, eventSet ->
|
||||
texture, materialStr, uvMode, expressionSet, motion, rotation, viewDirection, cameraMode, tinting, collision, environmentLighting, lightEmission, lightEmissionFrames, eventSet ->
|
||||
BedrockParticle(
|
||||
texture = texture,
|
||||
material = ParticleMaterial.valueOf(materialStr),
|
||||
@@ -139,6 +157,8 @@ class BedrockParticle(
|
||||
tinting = tinting,
|
||||
collision = collision,
|
||||
environmentLighting = environmentLighting,
|
||||
lightEmission = lightEmission,
|
||||
lightEmissionFrames = lightEmissionFrames,
|
||||
creationEvents = eventSet.creationEvents,
|
||||
expirationEvents = eventSet.expirationEvents,
|
||||
timeline = eventSet.timeline
|
||||
@@ -164,6 +184,8 @@ class BedrockParticle(
|
||||
ParticleTinting.writeToBuffer(buffer, tinting)
|
||||
collision.writeToBuffer(buffer)
|
||||
buffer.writeBoolean(environmentLighting)
|
||||
buffer.writeVarInt(lightEmission)
|
||||
buffer.writeCollection(lightEmissionFrames) { pb, level -> pb.writeVarInt(level) }
|
||||
buffer.writeCollection(creationEvents) { _, event -> event.encode(buffer) }
|
||||
buffer.writeCollection(expirationEvents) { _, event -> event.encode(buffer) }
|
||||
timeline.encode(buffer)
|
||||
@@ -186,6 +208,8 @@ class BedrockParticle(
|
||||
tinting = ParticleTinting.readFromBuffer(buffer)
|
||||
collision.readFromBuffer(buffer)
|
||||
environmentLighting = buffer.readBoolean()
|
||||
lightEmission = buffer.readVarInt()
|
||||
lightEmissionFrames = buffer.readList { it.readVarInt() }
|
||||
creationEvents = buffer.readList { SimpleEventTrigger("").also { it.decode(buffer) } }
|
||||
expirationEvents = buffer.readList { SimpleEventTrigger("").also { it.decode(buffer) } }
|
||||
timeline.decode(buffer)
|
||||
|
||||
@@ -75,4 +75,4 @@ object ParticleMaterials {
|
||||
|
||||
override fun toString() = "OPAQUE"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,10 @@ abstract class ParticleUVMode : CodecMapped {
|
||||
open var vSize: Expression = NumberExpression(8.0)
|
||||
|
||||
abstract fun get(moLangRuntime: MoLangRuntime, age: Double, maxAge: Double, uvDetails: UVDetails): UVDetails
|
||||
|
||||
/** The current flipbook frame index for a particle at this age (0 for static modes). Used to look
|
||||
* up per frame light levels (see [BedrockParticle.lightEmissionFrames]). */
|
||||
open fun frameAt(moLangRuntime: MoLangRuntime, age: Double, maxAge: Double): Int = 0
|
||||
}
|
||||
|
||||
enum class ParticleUVModeType {
|
||||
@@ -123,6 +127,18 @@ class AnimatedParticleUVMode(
|
||||
buffer.writeBoolean(loop)
|
||||
}
|
||||
|
||||
override fun frameAt(moLangRuntime: MoLangRuntime, age: Double, maxAge: Double): Int {
|
||||
val maxFrame = moLangRuntime.resolveInt(maxFrame) - 1
|
||||
if (maxFrame <= 0) return 0
|
||||
val frame = if (stretchToLifetime) {
|
||||
if (maxAge <= 0.0) 0 else ((age / maxAge) * maxFrame).toInt()
|
||||
} else {
|
||||
val fps = moLangRuntime.resolveDouble(fps)
|
||||
if (!loop && age * fps >= maxFrame) maxFrame else ((age * fps) % maxFrame).toInt()
|
||||
}
|
||||
return frame.coerceIn(0, maxFrame)
|
||||
}
|
||||
|
||||
override fun get(runtime: MoLangRuntime, age: Double, maxAge: Double, uvDetails: UVDetails): UVDetails {
|
||||
val maxFrame = runtime.resolveInt(maxFrame) - 1
|
||||
val stepU = runtime.resolveDouble(stepU)
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.cobblemon.mod.common.client.gui.tmmachine.TMMachineScreen
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
||||
import com.cobblemon.mod.common.client.render.SnowstormShaderBypassRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.color.AprijuiceItemColorProvider
|
||||
@@ -140,6 +141,9 @@ object CobblemonClient {
|
||||
PlatformEvents.CLIENT_PLAYER_LOGIN.subscribe { onLogin() }
|
||||
PlatformEvents.CLIENT_PLAYER_LOGOUT.subscribe { onLogout() }
|
||||
|
||||
// Redraws snowstorm particles so they match vanilla when a shaderpack is active.
|
||||
SnowstormShaderBypassRenderer.register()
|
||||
|
||||
this.registerBlockEntityRenderers()
|
||||
registerBlockRenderTypes()
|
||||
registerColors()
|
||||
|
||||
+55
-1
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.particle
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.snowstorm.BedrockParticleOptions
|
||||
import com.cobblemon.mod.common.particle.SnowstormParticleReader
|
||||
@@ -45,7 +46,60 @@ object BedrockParticleOptionsRepository {
|
||||
}
|
||||
|
||||
LOGGER.info("Loaded ${effects.size} particle effects")
|
||||
|
||||
loadLightConfig(resourceManager)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads particle light levels from a separate Cobblemon data location and merges them onto the
|
||||
* already loaded effects. These are kept out of the `.particle.json` on purpose: Snowstorm (the
|
||||
* Bedrock particle editor) rebuilds the components block on export and silently drops unknown
|
||||
* components, so a light field inside the particle file would be lost the next time it is saved.
|
||||
* A sidecar file is never touched by Snowstorm.
|
||||
*
|
||||
* Files live under `assets/<namespace>/dynamiclights/particles/` (any `.json` file), each a map of
|
||||
* effect id to its light config, e.g.:
|
||||
* ```json
|
||||
* {
|
||||
* "cobblemon:thunderbolt_actor": { "light_level": 14 },
|
||||
* "cobblemon:flamethrower_actor": { "light_levels": [0, 8, 14, 14, 8] }
|
||||
* }
|
||||
* ```
|
||||
* `light_level` is a flat level (0..15) every particle emits; the optional `light_levels` array gives
|
||||
* a level per flipbook frame and overrides the flat level. Entries for unknown effect ids are ignored.
|
||||
*/
|
||||
private fun loadLightConfig(resourceManager: ResourceManager) {
|
||||
// LambDynamicLights is the only thing that consumes these levels. If it isn't installed, don't
|
||||
// even read the sidecar files; the light config is never parsed, applied, or considered.
|
||||
val lambDynamicLightsInstalled = Cobblemon.implementation.isModInstalled("lambdynlights") ||
|
||||
Cobblemon.implementation.isModInstalled("lambdynamiclights")
|
||||
if (!lambDynamicLightsInstalled) return
|
||||
|
||||
var applied = 0
|
||||
val configPaths = listOf("dynamiclights/particles", "particle_light")
|
||||
for (configPath in configPaths) {
|
||||
resourceManager.listResources(configPath) { path -> path.endsWith(".json") }.forEach { identifier, resource ->
|
||||
try {
|
||||
resource.open().use { stream ->
|
||||
val json = String(stream.readAllBytes(), StandardCharsets.UTF_8)
|
||||
val root = GSON.fromJson(json, JsonObject::class.java)
|
||||
for ((key, value) in root.entrySet()) {
|
||||
val effect = effects[ResourceLocation.parse(key)] ?: continue
|
||||
val config = value.asJsonObject
|
||||
config.get("light_level")?.asInt?.let { effect.particle.lightEmission = it.coerceIn(0, 15) }
|
||||
config.getAsJsonArray("light_levels")?.let { arr ->
|
||||
effect.particle.lightEmissionFrames = arr.map { it.asInt.coerceIn(0, 15) }
|
||||
}
|
||||
applied++
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
LOGGER.error("Failed to load particle light config $identifier", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (applied > 0) LOGGER.info("Applied dynamic-light config to $applied particle effect(s)")
|
||||
}
|
||||
|
||||
fun getEffect(identifier: ResourceLocation): BedrockParticleOptions? = effects[identifier]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.particle
|
||||
|
||||
import com.cobblemon.mod.common.client.render.SnowstormParticle
|
||||
|
||||
/**
|
||||
* Bridge that lets the optional LambDynamicLights integration attach a dynamic light to individual
|
||||
* glowing particles without the common particle code referencing the LambDynamicLights API directly.
|
||||
*
|
||||
* Each particle whose resolved light level is above 0 (and that claims one of its emitter's limited
|
||||
* light slots) registers its own light through [sink]. When LambDynamicLights is installed its
|
||||
* entrypoint ([com.cobblemon.mod.common.compat.lambdynamiclights.LambDynamicLightsInitializer]) sets
|
||||
* [sink]; when it is absent [sink] stays null and the registration call does nothing, so there is no
|
||||
* hard dependency.
|
||||
*/
|
||||
object MoveDynamicLights {
|
||||
@JvmStatic
|
||||
var sink: GlowingParticleLightSink? = null
|
||||
}
|
||||
|
||||
/** Receives an individual glowing [SnowstormParticle] so a real dynamic light can be attached to it. */
|
||||
fun interface GlowingParticleLightSink {
|
||||
fun register(particle: SnowstormParticle)
|
||||
}
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.particle
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.function.LivingEntityMoLangFunctions
|
||||
@@ -374,4 +375,23 @@ class ParticleStorm(
|
||||
fun setInvisible() {
|
||||
particles.forEach { particle -> particle.invisible = true }
|
||||
}
|
||||
|
||||
/** How many of this emitter's live particles currently hold a dynamic light, capped by the
|
||||
* maxLitParticlesPerEmitter config. A particle existing does not imply a light. */
|
||||
var litParticleCount = 0
|
||||
private set
|
||||
|
||||
/** Claims one of this emitter's limited light slots for a particle. Returns true if a slot was
|
||||
* free (and reserved), false if the emitter is at the configured cap. A cap of 0 disables the
|
||||
* particle lights entirely. */
|
||||
fun reserveLightSlot(): Boolean {
|
||||
if (litParticleCount >= Cobblemon.config.maxLitParticlesPerEmitter) return false
|
||||
litParticleCount++
|
||||
return true
|
||||
}
|
||||
|
||||
/** Releases a previously reserved light slot (called when a lit particle is removed). */
|
||||
fun releaseLightSlot() {
|
||||
if (litParticleCount > 0) litParticleCount--
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render
|
||||
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* Detects whether a shaderpack is currently active, via Iris (Fabric/NeoForge) or OptiFine.
|
||||
*
|
||||
* Every reference here is reflective and fully guarded: Iris/OptiFine are optional and may be
|
||||
* absent at runtime, so we never reference their classes directly. If neither is present (or their
|
||||
* APIs ever change shape) the lookups fail silently during class init and [shadersActive] simply
|
||||
* returns `false`. The rest of the particle code relies on this contract staying safe under any loader — it
|
||||
* must work identically on Fabric and NeoForge and when no shader mod is installed at all.
|
||||
*
|
||||
* The reflective handles are resolved once; only the cheap boolean accessor is invoked per call.
|
||||
* Particle render types call this at most a handful of times per frame (once per [begin]), so the
|
||||
* cost is negligible.
|
||||
*/
|
||||
object ShaderCompat {
|
||||
|
||||
// Iris: net.irisshaders.iris.api.v0.IrisApi.getInstance().isShaderPackInUse()
|
||||
// getInstance() returns a stable singleton, so it is safe to cache.
|
||||
private val irisInstance: Any?
|
||||
private val irisIsShaderPackInUse: Method?
|
||||
|
||||
// OptiFine: net.optifine.Config.isShaders() (static)
|
||||
private val optifineIsShaders: Method?
|
||||
|
||||
init {
|
||||
var irisInst: Any? = null
|
||||
var irisMethod: Method? = null
|
||||
try {
|
||||
val irisApi = Class.forName("net.irisshaders.iris.api.v0.IrisApi")
|
||||
irisInst = irisApi.getMethod("getInstance").invoke(null)
|
||||
irisMethod = irisApi.getMethod("isShaderPackInUse")
|
||||
} catch (ignored: Throwable) {
|
||||
irisInst = null
|
||||
irisMethod = null
|
||||
}
|
||||
irisInstance = irisInst
|
||||
irisIsShaderPackInUse = irisMethod
|
||||
|
||||
var optifineMethod: Method? = null
|
||||
try {
|
||||
optifineMethod = Class.forName("net.optifine.Config").getMethod("isShaders")
|
||||
} catch (ignored: Throwable) {
|
||||
optifineMethod = null
|
||||
}
|
||||
optifineIsShaders = optifineMethod
|
||||
}
|
||||
|
||||
/**
|
||||
* `true` when Iris or OptiFine reports an active (compiled and enabled) shaderpack. Never throws;
|
||||
* any reflective failure is treated as "no shaders".
|
||||
*/
|
||||
fun shadersActive(): Boolean {
|
||||
val instance = irisInstance
|
||||
val irisMethod = irisIsShaderPackInUse
|
||||
if (instance != null && irisMethod != null) {
|
||||
try {
|
||||
if (irisMethod.invoke(instance) == true) return true
|
||||
} catch (ignored: Throwable) {}
|
||||
}
|
||||
|
||||
val optifineMethod = optifineIsShaders
|
||||
if (optifineMethod != null) {
|
||||
try {
|
||||
if (optifineMethod.invoke(null) == true) return true
|
||||
} catch (ignored: Throwable) {}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.ModAPI
|
||||
import com.cobblemon.mod.common.api.snowstorm.ParticleMaterial
|
||||
import com.cobblemon.mod.common.api.snowstorm.ParticleMaterials
|
||||
import com.cobblemon.mod.common.api.snowstorm.UVDetails
|
||||
import com.cobblemon.mod.common.client.particle.MoveDynamicLights
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.util.math.geometry.transformDirection
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
@@ -54,6 +55,15 @@ class SnowstormParticle(
|
||||
) : Particle(world, x, y, z) {
|
||||
companion object {
|
||||
const val MAXIMUM_DISTANCE_CHANGE_PER_TICK_FOR_FRICTION = 0.005
|
||||
|
||||
/**
|
||||
* Every live snowstorm particle, in spawn order. When a shaderpack is active we pull these out
|
||||
* of the vanilla [net.minecraft.client.particle.ParticleEngine] (see [getRenderType] returning
|
||||
* [NO_RENDER]) and redraw them after composite via [SnowstormShaderBypassRenderer] so the pack's
|
||||
* particle program can't alter their look. Ordered by insertion; particles use identity equality
|
||||
* so a LinkedHashSet is safe.
|
||||
*/
|
||||
val activeParticles: MutableSet<SnowstormParticle> = LinkedHashSet()
|
||||
}
|
||||
|
||||
val sprite = getSpriteFromAtlas()
|
||||
@@ -107,6 +117,10 @@ class SnowstormParticle(
|
||||
runtime.environment.setSimpleVariable("emitter_random_4", DoubleValue(Random.Default.nextDouble()))
|
||||
}
|
||||
|
||||
/** True once this particle has claimed one of its emitter's limited light slots. */
|
||||
var litSlot = false
|
||||
private set
|
||||
|
||||
init {
|
||||
setParticleSpeed(initialVelocity.x, initialVelocity.y, initialVelocity.z)
|
||||
roll = -storm.effect.particle.rotation.getInitialRotation(runtime).toFloat()
|
||||
@@ -127,6 +141,30 @@ class SnowstormParticle(
|
||||
}
|
||||
}
|
||||
storm.effect.particle.creationEvents.forEach { it.trigger(storm, this) }
|
||||
activeParticles.add(this)
|
||||
|
||||
// Give this particle its own dynamic light only when LambDynamicLights is present, the type
|
||||
// emits light, and the emitter still has a free light slot. The level comes from
|
||||
// currentLightLevel(); when the mod is absent the sink is null and this does nothing.
|
||||
val sink = MoveDynamicLights.sink
|
||||
if (sink != null && storm.effect.particle.emitsLight && storm.reserveLightSlot()) {
|
||||
litSlot = true
|
||||
sink.register(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The block light level (0..15) this particle emits right now. Uses the per frame array when the
|
||||
* type defines one (indexed by the current flipbook frame), otherwise the flat level. Invisible
|
||||
* particles emit nothing.
|
||||
*/
|
||||
fun currentLightLevel(): Int {
|
||||
if (invisible) return 0
|
||||
val particle = storm.effect.particle
|
||||
val frames = particle.lightEmissionFrames
|
||||
if (frames.isEmpty()) return particle.lightEmission
|
||||
val frame = particle.uvMode.frameAt(runtime, age / 20.0, lifetime / 20.0)
|
||||
return frames[frame.coerceIn(0, frames.size - 1)]
|
||||
}
|
||||
|
||||
override fun render(vertexConsumer: VertexConsumer, camera: Camera, tickDelta: Float) {
|
||||
@@ -496,10 +534,21 @@ class SnowstormParticle(
|
||||
runtime.environment.variable.setDirectly("particle_lifetime", DoubleValue(lifetime / 20.0))
|
||||
}
|
||||
|
||||
override fun getRenderType() = particleTextureSheet
|
||||
// Under an active shaderpack we suppress the vanilla ParticleEngine draw (it would be routed through
|
||||
// the pack's translucent particle program and mangled differently per pack) and instead redraw after
|
||||
// composite in SnowstormShaderBypassRenderer so the look matches vanilla under any pack. With no
|
||||
// shaders this is the normal material sheet, so the majority path is unchanged.
|
||||
override fun getRenderType() = if (Cobblemon.config.shaderParticleBypass && ShaderCompat.shadersActive()) NO_RENDER else particleTextureSheet
|
||||
|
||||
override fun remove() {
|
||||
super.remove()
|
||||
storm.particles.remove(this)
|
||||
activeParticles.remove(this)
|
||||
// Free our light slot so another particle of this emitter can light up. The registered behavior
|
||||
// reports isRemoved() via this particle's isAlive(), so the manager drops the light on its own.
|
||||
if (litSlot) {
|
||||
storm.releaseLightSlot()
|
||||
litSlot = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.platform.events.RenderEvent
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
import com.mojang.blaze3d.vertex.BufferUploader
|
||||
import com.mojang.blaze3d.vertex.Tesselator
|
||||
import net.minecraft.client.Minecraft
|
||||
import org.joml.Matrix4f
|
||||
|
||||
/**
|
||||
* Renders Cobblemon's snowstorm particles so they look like vanilla under any pack while a
|
||||
* shaderpack (Iris/OptiFine) is active.
|
||||
*
|
||||
* ## Why this exists
|
||||
* Iris/OptiFine replace the vanilla particle shader with the shaderpack's translucent particle
|
||||
* program for the duration of the world pass, and every pack composites that program differently —
|
||||
* which made our particles render too solid (Complementary), invisible (Photon), or still darkening
|
||||
* (Bliss) no matter how we tuned blend/alpha inside the vanilla [net.minecraft.client.particle.ParticleEngine].
|
||||
* The pack has final authority there; we cannot win.
|
||||
*
|
||||
* The one place a shaderpack does NOT intercept a draw is **after** `LevelRenderer.renderLevel`
|
||||
* returns: Iris only overrides shaders while `isRenderingWorld` is true, and it flips that off during
|
||||
* its final composite (injected at the RETURN of world rendering). So we:
|
||||
* 1. suppress the vanilla draw of these particles while shaders are active
|
||||
* ([SnowstormParticle.getRenderType] returns NO_RENDER), and
|
||||
* 2. redraw them here at [RenderEvent.Stage.POST_LEVEL] (after composite) with the exact vanilla GL
|
||||
* state from [com.cobblemon.mod.common.api.snowstorm.ParticleMaterials] and the unchanged
|
||||
* [SnowstormParticle.render] quad math.
|
||||
*
|
||||
* The main framebuffer's depth attachment still holds the full (opaque + translucent) world depth at
|
||||
* this point — Iris reuses Minecraft's main depth texture and the composite only copies colour — so
|
||||
* particles still occlude correctly behind terrain AND water/glass. They simply don't receive the
|
||||
* pack's lighting/fog/bloom, which is exactly the intended "looks like vanilla" result.
|
||||
*
|
||||
* When no shaderpack is active this renderer does nothing and particles draw normally through the
|
||||
* ParticleEngine, so the majority path (no shaders) is completely unchanged.
|
||||
*
|
||||
* @author Cobblemon
|
||||
*/
|
||||
object SnowstormShaderBypassRenderer {
|
||||
|
||||
// The world's camera view matrix for the current frame, captured at the late stage within the
|
||||
// level pass where Fabric/NeoForge still have the camera transform applied. POST_LEVEL fires after
|
||||
// that state is unwound, but the bypass draw still needs it because SnowstormParticle.render emits
|
||||
// vertices relative to the camera just like vanilla particles do.
|
||||
private val modelViewMatrix = Matrix4f()
|
||||
private var captured = false
|
||||
|
||||
fun register() {
|
||||
PlatformEvents.RENDER.subscribe { event ->
|
||||
when (event.stage) {
|
||||
RenderEvent.Stage.LAST -> {
|
||||
modelViewMatrix.set(RenderSystem.getModelViewMatrix())
|
||||
captured = true
|
||||
}
|
||||
RenderEvent.Stage.POST_LEVEL -> render(event)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun render(event: RenderEvent) {
|
||||
if (!Cobblemon.config.shaderParticleBypass || !ShaderCompat.shadersActive() || !captured) {
|
||||
captured = false
|
||||
return
|
||||
}
|
||||
|
||||
val visible = SnowstormParticle.activeParticles.filter { !it.invisible }
|
||||
if (visible.isEmpty()) {
|
||||
captured = false
|
||||
return
|
||||
}
|
||||
|
||||
val minecraft = Minecraft.getInstance()
|
||||
val camera = event.camera
|
||||
val partialTicks = event.tickCounter.getGameTimeDeltaPartialTick(false)
|
||||
val lightTexture = minecraft.gameRenderer.lightTexture()
|
||||
val tesselator = Tesselator.getInstance()
|
||||
|
||||
// Restore the world's camera view so the quads built relative to the camera by render()
|
||||
// land in the right place; projection is still the world's 3D projection at this point in the frame.
|
||||
val modelViewStack = RenderSystem.getModelViewStack()
|
||||
modelViewStack.pushMatrix()
|
||||
modelViewStack.set(modelViewMatrix)
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
|
||||
try {
|
||||
lightTexture.turnOnLightLayer()
|
||||
|
||||
// Group by the particle's own render type (ParticleMaterials.ALPHA/ADD/BLEND/OPAQUE). Calling
|
||||
// its begin() sets the IDENTICAL GL state vanilla would use, so the look matches the no shader path.
|
||||
for ((renderType, particles) in visible.groupBy { it.particleTextureSheet }) {
|
||||
val buffer = renderType.begin(tesselator, minecraft.textureManager) ?: continue
|
||||
for (particle in particles) {
|
||||
particle.render(buffer, camera, partialTicks)
|
||||
}
|
||||
val mesh = buffer.build() ?: continue
|
||||
BufferUploader.drawWithShader(mesh)
|
||||
}
|
||||
} finally {
|
||||
lightTexture.turnOffLightLayer()
|
||||
modelViewStack.popMatrix()
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
captured = false
|
||||
}
|
||||
|
||||
// Restore neutral GL state so nothing downstream (hand already drawn, GUI next) is affected.
|
||||
RenderSystem.depthMask(true)
|
||||
RenderSystem.disableBlend()
|
||||
RenderSystem.defaultBlendFunc()
|
||||
RenderSystem.enableCull()
|
||||
}
|
||||
}
|
||||
@@ -331,6 +331,13 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Interface, lang = "animate_battle_tiles", CLIENT)
|
||||
var animateBattleTiles = false
|
||||
|
||||
@CobblemonConfigField(Category.Interface, lang = "shader_particle_bypass", CLIENT)
|
||||
var shaderParticleBypass = true
|
||||
|
||||
@CobblemonConfigField(Category.Interface, lang = "max_lit_particles_per_emitter", CLIENT)
|
||||
@IntConstraint(min = 0, max = 256)
|
||||
var maxLitParticlesPerEmitter = 20
|
||||
|
||||
// Disabled as non-tenable for 1.7 until all the posers catch up with this property.
|
||||
// @CobblemonConfigField(Category.Riding, lang = "third_person_view_bobbing", CLIENT)
|
||||
var thirdPersonViewBobbing = true
|
||||
|
||||
@@ -363,6 +363,11 @@ object SnowstormParticleReader {
|
||||
ExpressionParticleTinting()
|
||||
}
|
||||
val environmentLighting = componentsJson.has("minecraft:particle_appearance_lighting")
|
||||
// Light levels are intentionally not read from the .particle.json. Snowstorm (the Bedrock
|
||||
// particle editor) rebuilds the components block on export and silently drops unknown components,
|
||||
// so a custom light field here would be lost the next time a file is saved. Light levels instead
|
||||
// live in a separate Cobblemon data file, merged onto the effect after load (see
|
||||
// BedrockParticleOptionsRepository.loadLightConfig).
|
||||
val collision = collisionJson?.let {
|
||||
var collides = true
|
||||
val radius = it.get("collision_radius")?.asString?.asExpression() ?: run {
|
||||
|
||||
@@ -32,6 +32,22 @@ data class RenderEvent(
|
||||
|
||||
/** Represents when a layer is rendered by [LevelRenderer.renderLevel]. Ordinal corresponds with its render order. */
|
||||
enum class Stage {
|
||||
TRANSLUCENT
|
||||
TRANSLUCENT,
|
||||
|
||||
/**
|
||||
* Fired after the world framebuffer writes are complete but before the level renderer tears
|
||||
* down its camera view transform. Direct draws at [POST_LEVEL] can reuse the matrix captured
|
||||
* here when they need to render after shaderpack composition.
|
||||
*/
|
||||
LAST,
|
||||
|
||||
/**
|
||||
* Fired after [LevelRenderer.renderLevel] has fully finished — on a shaderpack, this is after
|
||||
* Iris/OptiFine has composited the world to the main framebuffer and restored vanilla shaders.
|
||||
* Draws here are NOT intercepted by the shaderpack, so they render with vanilla shaders while
|
||||
* still depth testing against the full (opaque + translucent) world depth. Used to render
|
||||
* Cobblemon's snowstorm particles so they look like vanilla under shaders.
|
||||
*/
|
||||
POST_LEVEL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,742 @@
|
||||
{
|
||||
"cobblemon:absorb_actor": { "light_levels": [1, 2, 2, 3, 4, 2, 1, 1, 1] },
|
||||
"cobblemon:absorb_actorhit": { "light_levels": [1, 1, 1, 2, 4, 2, 1, 1, 1] },
|
||||
"cobblemon:absorb_actortrail": { "light_levels": [2, 1] },
|
||||
|
||||
"cobblemon:afterspark": { "light_levels": [2, 2, 1, 1] },
|
||||
|
||||
"cobblemon:ancientazureball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientazureball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientazureball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientazureball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientazureball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientazureball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientazureball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientcitrineball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientcitrineball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientcitrineball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientcitrineball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientcitrineball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientcitrineball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientcitrineball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientfeatherball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientfeatherball/battle/ancientfeatherballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:ancientfeatherball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientfeatherball/battle/sendflash": { "light_levels": [0, 1, 2, 3, 2, 2, 3, 3, 2, 2, 1, 0] },
|
||||
"cobblemon:ancientfeatherball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientfeatherball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:ancientfeatherball/casual/sendflash": { "light_levels": [0, 1, 2, 3, 2, 2, 3, 3, 2, 2, 1, 0] },
|
||||
|
||||
"cobblemon:ancientgigatonball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientgigatonball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientgigatonball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientgigatonball/battle/sendflash": { "light_levels": [0, 1, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientgigatonball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientgigatonball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientgigatonball/casual/sendflash": { "light_levels": [0, 1, 2, 3, 3, 2, 2, 3, 3, 2, 1, 0] },
|
||||
|
||||
"cobblemon:ancientgreatball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientgreatball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientgreatball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientgreatball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientgreatball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientgreatball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientgreatball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientheavyball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientheavyball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientheavyball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientheavyball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:ancientheavyball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientheavyball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientheavyball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 1, 0] },
|
||||
|
||||
"cobblemon:ancientivoryball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientivoryball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientivoryball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientivoryball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientivoryball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientivoryball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientivoryball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientjetball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientjetball/battle/ancientjetballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:ancientjetball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientjetball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 4, 4, 5, 4, 4, 3, 3, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientjetball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientjetball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:ancientjetball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 4, 5, 4, 3, 2, 1, 0] },
|
||||
|
||||
"cobblemon:ancientleadenball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientleadenball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientleadenball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientleadenball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0] },
|
||||
"cobblemon:ancientleadenball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientleadenball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientleadenball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 1, 0] },
|
||||
|
||||
"cobblemon:ancientoriginball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientoriginball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientoriginball/battle/ballsparks": { "light_levels": [3] },
|
||||
"cobblemon:ancientoriginball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 4, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientoriginball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientoriginball/casual/ballsparks": { "light_levels": [3] },
|
||||
"cobblemon:ancientoriginball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 4, 2, 2, 1, 1, 1, 1, 0, 0] },
|
||||
|
||||
"cobblemon:ancientpokeball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientpokeball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientpokeball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientpokeball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientpokeball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientpokeball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientpokeball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientroseateball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientroseateball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientroseateball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientroseateball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientroseateball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientroseateball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientroseateball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientslateball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientslateball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientslateball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientslateball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientslateball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientslateball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientslateball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientultraball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientultraball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientultraball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientultraball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:ancientultraball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientultraball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientultraball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 4, 2, 2, 2, 2, 1, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientverdantball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientverdantball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientverdantball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientverdantball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:ancientverdantball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientverdantball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ancientverdantball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ancientwingball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ancientwingball/battle/ancientwingballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:ancientwingball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientwingball/battle/sendflash": { "light_levels": [0, 1, 2, 3, 3, 3, 3, 4, 3, 3, 1, 0] },
|
||||
"cobblemon:ancientwingball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ancientwingball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:ancientwingball/casual/sendflash": { "light_levels": [0, 1, 2, 3, 3, 3, 4, 4, 3, 3, 1, 0] },
|
||||
|
||||
"cobblemon:aurorabeam_actor": { "light_levels": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4] },
|
||||
"cobblemon:aurorabeam_actoremit": { "light_levels": [2, 3, 5, 6] },
|
||||
"cobblemon:aurorabeam_actorfrost": { "light_levels": [2, 1, 1] },
|
||||
"cobblemon:aurorabeam_actorspray": { "light_levels": [3, 5, 6, 5, 3, 3, 1] },
|
||||
"cobblemon:aurorabeam_charge": { "light_levels": [1, 3, 3, 5, 6] },
|
||||
"cobblemon:aurorabeam_target": { "light_levels": [2, 2, 2, 3, 3, 2] },
|
||||
"cobblemon:aurorabeam_targetburst": { "light_levels": [3, 5, 6, 5, 3, 3, 1] },
|
||||
"cobblemon:aurorabeam_targetsparkle": { "light_levels": [4, 3, 2, 1] },
|
||||
|
||||
"cobblemon:azureball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:azureball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:azureball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:azureball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:azureball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:azureball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:azureball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:beastball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:beastball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:beastball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:beastball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0] },
|
||||
"cobblemon:beastball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:beastball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:beastball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0] },
|
||||
|
||||
"cobblemon:burn_actor": { "light_levels": [0, 2, 4, 3, 4, 4, 3] },
|
||||
"cobblemon:burn_actorresidual": { "light_levels": [0, 2, 1, 0, 0] },
|
||||
|
||||
"cobblemon:capturesparks": { "light_levels": [0, 1, 3, 1, 0, 0] },
|
||||
"cobblemon:capturestar": { "light_levels": [0, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, 0, 0] },
|
||||
|
||||
"cobblemon:cherishball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:cherishball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:cherishball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:cherishball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:cherishball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:cherishball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:cherishball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0] },
|
||||
|
||||
"cobblemon:citrineball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:citrineball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:citrineball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:citrineball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:citrineball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:citrineball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:citrineball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:daimonji1": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
|
||||
"cobblemon:daimonji2": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
|
||||
"cobblemon:daimonji3": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
|
||||
"cobblemon:daimonji4": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
|
||||
"cobblemon:diveball/ballsparkle": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:diveball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:diveball/battle/ballsparks": { "light_levels": [1, 2, 3, 3, 1, 0] },
|
||||
"cobblemon:diveball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 0] },
|
||||
"cobblemon:diveball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:diveball/casual/ballsparks": { "light_levels": [1, 2, 3, 3, 1, 0] },
|
||||
"cobblemon:diveball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 3, 3, 2, 2, 0] },
|
||||
|
||||
"cobblemon:dracometeor_accent": { "light_levels": [11] },
|
||||
"cobblemon:dracometeor_accenttrail": { "light_levels": [10, 8, 7, 7, 6, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_actoraurasparkle": { "light_levels": [5, 6, 7, 8, 7, 6] },
|
||||
"cobblemon:dracometeor_actorpulse": { "light_levels": [5, 5, 5, 5, 5, 5, 5, 5, 5, 5] },
|
||||
"cobblemon:dracometeor_actorpulseaura": { "light_levels": [10, 8, 7, 7, 6, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_bigburst": { "light_levels": [6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_bigring": { "light_levels": [5, 5, 5, 5, 5, 5, 5] },
|
||||
"cobblemon:dracometeor_burst": { "light_levels": [6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_meteortrail1": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_meteortrail2": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_meteortrail3": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_meteortrail4": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:dracometeor_ring": { "light_levels": [5, 5, 5, 5, 5, 5, 5] },
|
||||
|
||||
"cobblemon:dragonbreath_actor": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:dragonbreath_target": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
|
||||
"cobblemon:dragonclaw_aura": { "light_levels": [3, 3, 3, 4, 3, 3] },
|
||||
"cobblemon:dragonclaw_target": { "light_levels": [3, 4, 4, 4, 3, 3, 3] },
|
||||
|
||||
"cobblemon:dragonrage_actor": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:dragonrage_actorburst": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:dragonrage_actorring": { "light_levels": [3, 3, 3, 3, 3, 3, 3, 2] },
|
||||
"cobblemon:dragonrage_target": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:dragonrage_targetcover": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
|
||||
"cobblemon:drainpunch_actor": { "light_levels": [0, 1, 1, 3, 7, 3, 1, 1, 0] },
|
||||
"cobblemon:drainpunch_target": { "light_levels": [3, 2, 2, 1, 0, 0, 0, 0, 0] },
|
||||
"cobblemon:drainpunch_targetburst": { "light_levels": [0, 2, 5, 2, 0, 0, 0] },
|
||||
"cobblemon:drainpunch_targetring": { "light_levels": [1, 1, 1, 1, 1, 1] },
|
||||
|
||||
"cobblemon:dreamball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:dreamball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:dreamball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:dreamball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 4, 4, 5, 4, 4, 2, 1, 1, 1, 0, 0, 0] },
|
||||
"cobblemon:dreamball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:dreamball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:dreamball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 4, 4, 4, 1, 1, 0, 0] },
|
||||
|
||||
"cobblemon:duskball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:duskball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:duskball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:duskball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 4, 4, 5, 4, 4, 4, 3, 3, 2, 2, 1, 0] },
|
||||
"cobblemon:duskball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:duskball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:duskball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 5, 5, 4, 3, 2, 2, 1, 0] },
|
||||
|
||||
"cobblemon:eggbomb_targetfire": { "light_levels": [2, 2, 4, 6, 7, 7, 6, 4, 2, 2] },
|
||||
|
||||
"cobblemon:ember_actor": { "light_levels": [2, 2, 3, 4, 4, 3, 2, 2, 2] },
|
||||
"cobblemon:ember_fire": { "light_levels": [3, 6, 5, 3, 2] },
|
||||
"cobblemon:ember_firesparks": { "light_levels": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4] },
|
||||
"cobblemon:ember_froth": { "light_levels": [3, 6, 5, 3, 2] },
|
||||
"cobblemon:ember_impact": { "light_levels": [3, 6, 5, 3, 2] },
|
||||
"cobblemon:ember_impactlinger": { "light_levels": [3, 6, 5, 3, 2] },
|
||||
"cobblemon:ember_target": { "light_levels": [3, 4, 4, 3, 2, 2, 2] },
|
||||
"cobblemon:ember_targetlinger": { "light_levels": [3, 6, 5, 3, 2] },
|
||||
|
||||
"cobblemon:eruption_actor": { "light_levels": [6, 6, 7, 8, 9, 9, 8, 7, 6, 6] },
|
||||
"cobblemon:eruption_actorburst": { "light_levels": [6, 7, 8, 9, 9, 8, 7, 6, 6] },
|
||||
"cobblemon:eruption_actorcinder": { "light_levels": [8, 11, 10, 8, 6] },
|
||||
"cobblemon:eruption_actorlava": { "light_levels": [9] },
|
||||
"cobblemon:eruption_actorspume": { "light_levels": [6, 7, 8, 9, 9, 8, 7, 6, 6] },
|
||||
"cobblemon:eruption_target": { "light_levels": [11] },
|
||||
"cobblemon:eruption_targetburst": { "light_levels": [6, 7, 8, 9, 9, 8, 7, 6, 6] },
|
||||
"cobblemon:eruption_targetflame": { "light_levels": [6, 7, 8, 9, 9, 8, 7, 6, 6] },
|
||||
|
||||
"cobblemon:evo_bigsparkle": { "light_levels": [3, 4, 5, 6, 5, 4] },
|
||||
"cobblemon:evo_buildup": { "light_levels": [3, 4, 6] },
|
||||
"cobblemon:evo_flyingsparkles": { "light_levels": [6, 4, 4, 3] },
|
||||
"cobblemon:evo_godrays": { "light_levels": [8] },
|
||||
"cobblemon:evo_godrays_small": { "light_levels": [8] },
|
||||
"cobblemon:evo_implode": { "light_levels": [8, 6, 4, 3] },
|
||||
"cobblemon:evo_obscuring": { "light_levels": [3, 5, 7, 8, 9, 9] },
|
||||
"cobblemon:evo_particles": { "light_levels": [3] },
|
||||
"cobblemon:evo_smokeburst": { "light_levels": [11, 10, 9, 7, 5, 3] },
|
||||
"cobblemon:evo_sparkle": { "light_levels": [6, 4, 4, 3] },
|
||||
"cobblemon:evo_sparkleburst": { "light_levels": [6, 4, 4, 3] },
|
||||
"cobblemon:evo_sparklefetti": { "light_levels": [6, 6] },
|
||||
|
||||
"cobblemon:explosion_actorbigring": { "light_levels": [13] },
|
||||
"cobblemon:explosion_actorboom": { "light_levels": [15] },
|
||||
"cobblemon:explosion_actorfire": { "light_levels": [6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:explosion_actororbs": { "light_levels": [3] },
|
||||
"cobblemon:explosion_actorrelease": { "light_levels": [9] },
|
||||
"cobblemon:explosion_actorrings": { "light_levels": [5, 6, 6, 7, 8, 8, 8, 6, 5] },
|
||||
"cobblemon:explosion_burst_fire": { "light_levels": [13, 13, 13, 13, 13, 13, 13] },
|
||||
"cobblemon:explosion_burst_flash": { "light_levels": [15] },
|
||||
"cobblemon:explosion_charge_accretion": { "light_levels": [8] },
|
||||
"cobblemon:explosion_charge_light": { "light_levels": [8] },
|
||||
"cobblemon:explosion_target": { "light_levels": [15, 15, 15, 15, 15, 15, 15] },
|
||||
|
||||
"cobblemon:fastball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:fastball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 0] },
|
||||
"cobblemon:fastball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:fastball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0] },
|
||||
"cobblemon:fastball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 0] },
|
||||
"cobblemon:fastball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:fastball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0] },
|
||||
|
||||
"cobblemon:fireblast_actor1": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:fireblast_actor2": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:fireblast_actorshoot": { "light_levels": [5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:fireblast_target": { "light_levels": [5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:fireblast_targetcinder": { "light_levels": [7, 10, 9, 7, 5] },
|
||||
|
||||
"cobblemon:firefang_target": { "light_levels": [5, 5, 5, 5, 6, 4, 4, 4, 4, 4] },
|
||||
"cobblemon:firefang_targetburst": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:firefang_targetspark": { "light_levels": [6] },
|
||||
|
||||
"cobblemon:firepunch": { "light_levels": [5, 7, 7, 7, 7] },
|
||||
"cobblemon:firepunch_hand": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:firepunch_target": { "light_levels": [6, 5, 5, 5, 4, 4, 3, 3, 3] },
|
||||
"cobblemon:firepunch_targetburst": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:firepunch_targetlinger": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
|
||||
"cobblemon:firespin_actor": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:firespin_actorburst": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:firespin_actorcinder": { "light_levels": [4, 7, 6, 4, 2] },
|
||||
"cobblemon:firespin_actormiss": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:firespin_target": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:firespin_targetburst": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
|
||||
"cobblemon:flameburst_actor": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:flameburst_actorfling": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:flameburst_target": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:flameburst_targetcinders": { "light_levels": [5] },
|
||||
|
||||
"cobblemon:flamecharge_actor": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:flamecharge_actorcharge": { "light_levels": [2, 4, 4, 6, 8, 6, 4, 4, 2] },
|
||||
"cobblemon:flamecharge_actorcinder": { "light_levels": [4, 7, 6, 4, 2] },
|
||||
"cobblemon:flamecharge_actorspiral": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:flamecharge_target": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
"cobblemon:flamecharge_targetcover": { "light_levels": [2, 2, 3, 4, 5, 5, 4, 3, 2, 2] },
|
||||
|
||||
"cobblemon:flamethrower_actor": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:flamethrower_target": { "light_levels": [5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:flamethrower_target_linger": { "light_levels": [6, 6, 6, 5, 5, 4, 2] },
|
||||
"cobblemon:flamethrower_targetburst": { "light_levels": [5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:flamethrower_targetcinder": { "light_levels": [7, 10, 9, 7, 5] },
|
||||
|
||||
"cobblemon:flamewheel_actor": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:flamewheel_actoraura": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:flamewheel_actorboost": { "light_levels": [3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:flamewheel_actorcinder": { "light_levels": [5, 8, 7, 5, 3] },
|
||||
"cobblemon:flamewheel_target": { "light_levels": [3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:flamewheel_targetcover": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
|
||||
"cobblemon:friendball/ballsparkle": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:friendball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:friendball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:friendball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:friendball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:friendball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:friendball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 1, 1, 1, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:gigadrain_actor": { "light_levels": [1, 3, 4, 6, 7, 6, 4, 3, 1] },
|
||||
"cobblemon:gigadrain_actoraccent": { "light_levels": [1] },
|
||||
"cobblemon:gigadrain_actordrainaccent": { "light_levels": [1] },
|
||||
"cobblemon:gigadrain_actorhit": { "light_levels": [0, 1, 1, 3, 7, 3, 1, 1, 0] },
|
||||
"cobblemon:gigadrain_actorouter": { "light_levels": [1, 3, 4, 6, 7, 6, 4, 3, 1] },
|
||||
"cobblemon:gigadrain_actortrail": { "light_levels": [5, 0] },
|
||||
|
||||
"cobblemon:greatball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:greatball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:greatball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:greatball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 0] },
|
||||
"cobblemon:greatball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:greatball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:greatball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:healball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:healball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:healball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:healball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:healball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:healball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:healball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 0] },
|
||||
|
||||
"cobblemon:heavyball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:heavyball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:heavyball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:heavyball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0] },
|
||||
"cobblemon:heavyball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:heavyball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:heavyball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 1, 1, 1, 0, 0, 0] },
|
||||
|
||||
"cobblemon:hisuiafterspark": { "light_levels": [7, 5, 3, 3] },
|
||||
|
||||
"cobblemon:hisuicapturestar": { "light_levels": [4, 5, 5, 7, 7, 7, 7, 7, 7, 5, 5, 4, 3] },
|
||||
|
||||
"cobblemon:hisuisendspark": { "light_levels": [3, 4, 4, 4, 4, 4, 4, 3, 3] },
|
||||
|
||||
"cobblemon:hisuispark": { "light_levels": [5, 4, 4, 4, 3, 4, 4, 3, 3] },
|
||||
|
||||
"cobblemon:hisuitrail": { "light_levels": [3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3] },
|
||||
|
||||
"cobblemon:hooh_tailtrail": { "light_levels": [5, 2, 5, 2, 5, 2, 2, 5, 2, 2, 1] },
|
||||
|
||||
"cobblemon:hypnosis_actor": { "light_levels": [3, 3, 3, 3, 3, 4, 4, 4, 4] },
|
||||
"cobblemon:hypnosis_target": { "light_levels": [4, 5, 6, 5, 5, 4, 3, 2] },
|
||||
"cobblemon:hypnosis_targetimpact": { "light_levels": [4, 4, 4, 4, 4, 4, 4, 4] },
|
||||
|
||||
"cobblemon:icebeam_actor": { "light_levels": [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] },
|
||||
"cobblemon:icebeam_actoremit": { "light_levels": [2, 3, 4, 6] },
|
||||
"cobblemon:icebeam_actorfrost": { "light_levels": [3, 2, 2] },
|
||||
"cobblemon:icebeam_actorpilot": { "light_levels": [2] },
|
||||
"cobblemon:icebeam_actorsparkle": { "light_levels": [5, 4, 3, 2] },
|
||||
"cobblemon:icebeam_actorspray": { "light_levels": [5, 4, 3, 2] },
|
||||
"cobblemon:icebeam_target": { "light_levels": [5, 4, 3, 2] },
|
||||
"cobblemon:icebeam_targetbuild": { "light_levels": [2, 3, 5] },
|
||||
"cobblemon:icebeam_targetburst": { "light_levels": [4] },
|
||||
"cobblemon:icebeam_targetfrost": { "light_levels": [4] },
|
||||
|
||||
"cobblemon:impact_electric": { "light_levels": [6, 3, 0, 0, 4, 0, 0] },
|
||||
"cobblemon:impact_fire": { "light_levels": [2, 4, 4, 5, 6, 7, 4] },
|
||||
"cobblemon:impact_psychic": { "light_levels": [2, 2, 3, 4, 3, 4, 2] },
|
||||
|
||||
"cobblemon:kinesis_actorspiral": { "light_levels": [3, 4, 5, 4, 4, 3, 2, 1] },
|
||||
|
||||
"cobblemon:lavaplume_actor": { "light_levels": [5, 5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
"cobblemon:lavaplume_actorcinders": { "light_levels": [8] },
|
||||
"cobblemon:lavaplume_target": { "light_levels": [8] },
|
||||
"cobblemon:lavaplume_targetflame": { "light_levels": [5, 6, 7, 8, 8, 7, 6, 5, 5] },
|
||||
|
||||
"cobblemon:leechlife_actor": { "light_levels": [2, 3, 3, 4, 5, 5, 3, 2, 2] },
|
||||
"cobblemon:leechlife_actortrail": { "light_levels": [2, 3] },
|
||||
"cobblemon:leechlife_target": { "light_levels": [3, 3, 2, 3, 3, 3] },
|
||||
"cobblemon:leechlife_targetspark": { "light_levels": [4] },
|
||||
|
||||
"cobblemon:leechseed_target": { "light_levels": [2, 3, 3, 4, 5, 4, 3, 3, 1] },
|
||||
|
||||
"cobblemon:levelball/ballsparkle": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:levelball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:levelball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:levelball/battle/sendflash": { "light_levels": [0, 1, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0] },
|
||||
"cobblemon:levelball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:levelball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:levelball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 3, 2, 2, 2, 2, 2, 1, 0] },
|
||||
|
||||
"cobblemon:lightscreen_actorborder1": { "light_levels": [2, 2, 2, 3, 3, 4, 4, 3, 2, 2, 2, 2] },
|
||||
"cobblemon:lightscreen_actorborder2": { "light_levels": [2, 2, 2, 3, 3, 4, 4, 3, 2, 2, 2, 2] },
|
||||
|
||||
"cobblemon:loveball/ballsparkle": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:loveball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:loveball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:loveball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:loveball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:loveball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:loveball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:lucario_aura": { "light_levels": [6, 5, 4, 3, 3, 1] },
|
||||
"cobblemon:lucario_aura_sparks": { "light_levels": [2, 1, 1, 1, 1, 1] },
|
||||
|
||||
"cobblemon:lureball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:lureball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:lureball/battle/ballsparks": { "light_levels": [1, 2, 3, 3, 1, 0] },
|
||||
"cobblemon:lureball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 2, 3, 3, 2, 2, 2, 1, 0] },
|
||||
"cobblemon:lureball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:lureball/casual/ballsparks": { "light_levels": [1, 2, 3, 3, 1, 0] },
|
||||
"cobblemon:lureball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 2, 2, 1, 0] },
|
||||
|
||||
"cobblemon:luxuryball/ballsparkle": { "light_levels": [1, 2, 3, 2, 0] },
|
||||
"cobblemon:luxuryball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:luxuryball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:luxuryball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:luxuryball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:luxuryball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:luxuryball/casual/sendflash": { "light_levels": [0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 0] },
|
||||
|
||||
"cobblemon:magcargo_lava_bubble": { "light_levels": [6, 6, 6, 6, 6, 5, 4, 3, 2] },
|
||||
|
||||
"cobblemon:masterball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:masterball/battle/ballsendsparkle": { "light_levels": [2] },
|
||||
"cobblemon:masterball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:masterball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:masterball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:masterball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0] },
|
||||
"cobblemon:masterball/casual/sendflash": { "light_levels": [0, 1, 2, 3, 3, 3, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:megadrain_actor": { "light_levels": [2, 4, 4, 4, 5, 4, 4, 4, 2] },
|
||||
"cobblemon:megadrain_actoraccent": { "light_levels": [4] },
|
||||
"cobblemon:megadrain_actordrainaccent": { "light_levels": [4] },
|
||||
"cobblemon:megadrain_actorheal": { "light_levels": [5, 3] },
|
||||
"cobblemon:megadrain_actorhealbig": { "light_levels": [5, 3] },
|
||||
"cobblemon:megadrain_actorhealtimer": { "light_levels": [5, 3] },
|
||||
"cobblemon:megadrain_actorhit": { "light_levels": [2, 4, 4, 4, 5, 6, 4, 4, 2] },
|
||||
"cobblemon:megadrain_actortrail": { "light_levels": [8, 3] },
|
||||
|
||||
"cobblemon:metal_sparks": { "light_levels": [3] },
|
||||
|
||||
"cobblemon:moonball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:moonball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:moonball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:moonball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:moonball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:moonball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:moonball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:mysticalfire_actor": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:mysticalfire_actorbig": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:mysticalfire_actorburst": { "light_levels": [3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:mysticalfire_actormotilesparkle": { "light_levels": [6, 5, 4, 3] },
|
||||
"cobblemon:mysticalfire_actorshot": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:mysticalfire_actorsparkle": { "light_levels": [6, 5, 4, 3] },
|
||||
"cobblemon:mysticalfire_target": { "light_levels": [3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:mysticalfire_targetsparkle": { "light_levels": [6, 5, 4, 3] },
|
||||
|
||||
"cobblemon:nestball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:nestball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:nestball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:nestball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0] },
|
||||
"cobblemon:nestball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:nestball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:nestball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0] },
|
||||
|
||||
"cobblemon:netball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:netball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:netball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:netball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:netball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:netball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:netball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 1, 1, 1, 0] },
|
||||
|
||||
"cobblemon:paralysis_actor": { "light_levels": [1, 4, 1, 3, 1, 2, 4, 1, 1, 3] },
|
||||
"cobblemon:paralysis_actorresidual": { "light_levels": [3, 1, 4, 1] },
|
||||
"cobblemon:paralysis_passive": { "light_levels": [4, 1, 3, 1, 1, 4, 2, 1, 3, 1] },
|
||||
|
||||
"cobblemon:parkball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:parkball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:parkball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:parkball/battle/sendflash": { "light_levels": [0, 1, 2, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 2, 3, 2, 0] },
|
||||
"cobblemon:parkball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:parkball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:parkball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 4, 4, 4, 4, 3, 3, 3, 2, 0] },
|
||||
|
||||
"cobblemon:pokeball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:pokeball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:pokeball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:pokeball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:pokeball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:pokeball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:pokeball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:premierball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:premierball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:premierball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:premierball/battle/sendflash": { "light_levels": [0, 1, 3, 3, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:premierball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:premierball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:premierball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:protect_actor1": { "light_levels": [2, 3, 4, 6, 5, 4, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 2, 1, 2] },
|
||||
"cobblemon:protect_actor2": { "light_levels": [2, 3, 4, 6, 5, 4, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 2, 1, 2] },
|
||||
"cobblemon:protect_actor3": { "light_levels": [2, 3, 4, 6, 5, 4, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 2, 1, 2] },
|
||||
"cobblemon:protect_actor4": { "light_levels": [2, 3, 4, 6, 5, 4, 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 2, 1, 2] },
|
||||
"cobblemon:protect_actoreffect": { "light_levels": [4, 2] },
|
||||
"cobblemon:protect_actorresidual": { "light_levels": [4, 2] },
|
||||
"cobblemon:protect_block": { "light_levels": [2, 3, 4, 5, 5, 4, 3, 3, 2, 2, 2] },
|
||||
"cobblemon:protect_blockback": { "light_levels": [3] },
|
||||
"cobblemon:protect_blockchip": { "light_levels": [3, 4, 6, 4, 3, 3, 1] },
|
||||
"cobblemon:protect_blockend": { "light_levels": [2, 3, 4, 5, 4, 4, 3, 3, 2, 2, 2] },
|
||||
"cobblemon:protect-blockchip": { "light_levels": [3, 4, 6, 4, 3, 3, 1] },
|
||||
|
||||
"cobblemon:psybeam_actor": { "light_levels": [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] },
|
||||
"cobblemon:psybeam_actoremit": { "light_levels": [3, 4, 6, 8] },
|
||||
"cobblemon:psybeam_actorenergy": { "light_levels": [3, 3, 5, 7, 4, 6, 3, 2] },
|
||||
"cobblemon:psybeam_actorpilot": { "light_levels": [2] },
|
||||
"cobblemon:psybeam_actorspray": { "light_levels": [4, 6, 8, 6, 4, 4, 2] },
|
||||
"cobblemon:psybeam_charge": { "light_levels": [2, 4, 4, 6, 8] },
|
||||
"cobblemon:psybeam_target": { "light_levels": [3, 3, 3, 4, 4, 3] },
|
||||
"cobblemon:psybeam_targetburst": { "light_levels": [4, 6, 8, 6, 4, 4, 2] },
|
||||
"cobblemon:psybeam_targetsparkle": { "light_levels": [4, 5, 6, 5, 5, 4, 3, 2] },
|
||||
|
||||
"cobblemon:psychic_actor": { "light_levels": [1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 5, 4, 4, 4, 4, 5, 3] },
|
||||
"cobblemon:psychic_actordots": { "light_levels": [1, 3, 3, 5, 7, 5, 3, 3, 1] },
|
||||
"cobblemon:psychic_impact": { "light_levels": [2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3] },
|
||||
"cobblemon:psychic_impactdots": { "light_levels": [2, 3, 4, 4, 4, 5, 5, 5, 5, 5, 6, 3] },
|
||||
"cobblemon:psychic_target": { "light_levels": [3, 4, 5, 4, 4, 3, 2, 1] },
|
||||
|
||||
"cobblemon:quickball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:quickball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:quickball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:quickball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 3, 3, 3, 3, 2, 0] },
|
||||
"cobblemon:quickball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:quickball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0, 0] },
|
||||
"cobblemon:quickball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 4, 3, 3, 2, 0] },
|
||||
|
||||
"cobblemon:reflect_actorborder1": { "light_levels": [2, 2, 2, 3, 3, 4, 4, 3, 2, 2, 2, 2] },
|
||||
"cobblemon:reflect_actorborder2": { "light_levels": [2, 2, 2, 3, 3, 4, 4, 3, 2, 2, 2, 2] },
|
||||
|
||||
"cobblemon:repeatball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:repeatball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 0] },
|
||||
"cobblemon:repeatball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:repeatball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0] },
|
||||
"cobblemon:repeatball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 0] },
|
||||
"cobblemon:repeatball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:repeatball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2, 0] },
|
||||
|
||||
"cobblemon:roseateball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:roseateball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:roseateball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:roseateball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:roseateball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:roseateball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:roseateball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:safariball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:safariball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:safariball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:safariball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:safariball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:safariball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:safariball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 3, 2, 3, 2, 1, 0] },
|
||||
|
||||
"cobblemon:seedbomb_target": { "light_levels": [1, 1, 2, 3, 4, 4, 3, 2, 1, 1] },
|
||||
"cobblemon:seedbomb_targetorbs": { "light_levels": [1, 3, 3, 5, 6, 5, 3, 3, 1] },
|
||||
|
||||
"cobblemon:shine_sparkle1": { "light_levels": [2] },
|
||||
"cobblemon:shine_sparkle2": { "light_levels": [2] },
|
||||
"cobblemon:shiny_glimmer": { "light_levels": [1, 1] },
|
||||
"cobblemon:shiny_magcargo_lava_bubble": { "light_levels": [6, 6, 6, 6, 6, 5, 4, 3, 2] },
|
||||
"cobblemon:shiny_ring": { "light_levels": [2] },
|
||||
"cobblemon:shiny_ring2": { "light_levels": [2] },
|
||||
"cobblemon:shiny_ring3": { "light_levels": [2] },
|
||||
"cobblemon:shiny_ring4": { "light_levels": [2] },
|
||||
"cobblemon:shiny_ring5": { "light_levels": [2] },
|
||||
"cobblemon:shiny_ring6": { "light_levels": [2] },
|
||||
"cobblemon:shiny_ring7": { "light_levels": [2] },
|
||||
"cobblemon:shiny_ring8": { "light_levels": [2] },
|
||||
"cobblemon:shiny_slugma_lava_bubble": { "light_levels": [5, 5, 5, 5, 5, 4, 3, 2, 1] },
|
||||
"cobblemon:shiny_sparkle_ambient": { "light_levels": [1, 1, 1, 1, 1, 1, 1] },
|
||||
"cobblemon:shiny_sparkle_ambient_wild": { "light_levels": [2] },
|
||||
|
||||
"cobblemon:slateball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:slateball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:slateball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:slateball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:slateball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:slateball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:slateball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:slugma_lava_bubble": { "light_levels": [5, 5, 5, 5, 5, 4, 3, 2, 1] },
|
||||
|
||||
"cobblemon:sportball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:sportball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:sportball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:sportball/battle/sendflash": { "light_levels": [0, 1, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0] },
|
||||
"cobblemon:sportball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:sportball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:sportball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 1, 2, 1, 0] },
|
||||
|
||||
"cobblemon:swordsdance_actor": { "light_levels": [4, 4, 4, 4, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4] },
|
||||
"cobblemon:swordsdance_sword2": { "light_levels": [4, 4, 4, 4, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4] },
|
||||
"cobblemon:swordsdance_sword3": { "light_levels": [4, 4, 4, 4, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4] },
|
||||
"cobblemon:swordsdance_sword4": { "light_levels": [4, 4, 4, 4, 5, 5, 4, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4] },
|
||||
|
||||
"cobblemon:synthesis_accretion": { "light_levels": [3] },
|
||||
"cobblemon:synthesis_sun": { "light_levels": [6] },
|
||||
"cobblemon:synthesis_sunlight": { "light_levels": [5] },
|
||||
|
||||
"cobblemon:tailflame_large": { "light_levels": [6, 6, 6, 6] },
|
||||
"cobblemon:tailflame_medium": { "light_levels": [5, 5, 5, 5] },
|
||||
"cobblemon:tailflame_small": { "light_levels": [4, 4, 4, 4] },
|
||||
|
||||
"cobblemon:thunder_actor": { "light_levels": [1, 15, 1, 12, 15] },
|
||||
"cobblemon:thunder_actorring": { "light_levels": [2, 13, 1, 15, 12, 15, 1, 14, 2, 13] },
|
||||
"cobblemon:thunder_actorsparks": { "light_levels": [4] },
|
||||
"cobblemon:thunder_target": { "light_levels": [0, 12, 0, 1, 0, 13, 13] },
|
||||
"cobblemon:thunder_targetboom": { "light_levels": [0, 2, 2, 2, 13, 12, 14, 1, 15] },
|
||||
"cobblemon:thunder_targetcloudspark": { "light_levels": [10] },
|
||||
"cobblemon:thunder_targetfire": { "light_levels": [15, 0, 0, 13, 12, 12, 13, 15, 1, 13] },
|
||||
"cobblemon:thunder_targetfloorsparks": { "light_levels": [4] },
|
||||
"cobblemon:thunder_targetglowcloud": { "light_levels": [14, 1, 14, 13, 0, 2, 0, 12] },
|
||||
"cobblemon:thunder_targetsparks": { "light_levels": [4] },
|
||||
|
||||
"cobblemon:thunderbolt_actor": { "light_levels": [0, 0, 1, 12, 2, 2, 0, 14, 1, 2, 11] },
|
||||
"cobblemon:thunderbolt_actorbolts": { "light_levels": [2, 0, 1, 15, 1, 14, 2, 0, 11, 2, 14] },
|
||||
"cobblemon:thunderbolt_actorsparks": { "light_levels": [2] },
|
||||
"cobblemon:thunderbolt_target": { "light_levels": [0, 13, 4, 2, 13, 11] },
|
||||
"cobblemon:thunderbolt_targetimpact": { "light_levels": [14, 1, 2, 5, 0, 13, 10] },
|
||||
"cobblemon:thunderbolt_targetsparks": { "light_levels": [2] },
|
||||
|
||||
"cobblemon:thunderfang_target": { "light_levels": [7, 0, 0, 0, 3, 7, 7, 0, 1, 7] },
|
||||
"cobblemon:thunderfang_targetimpact": { "light_levels": [7, 0, 0, 8, 0, 8, 7] },
|
||||
"cobblemon:thunderfang_targetspark": { "light_levels": [0] },
|
||||
|
||||
"cobblemon:thunderpunch": { "light_levels": [7, 0, 0, 7, 0] },
|
||||
"cobblemon:thunderpunch_hand": { "light_levels": [0] },
|
||||
"cobblemon:thunderpunch_target": { "light_levels": [0, 7, 8, 5, 0, 0, 7, 0, 7] },
|
||||
"cobblemon:thunderpunch_targetimpact": { "light_levels": [8, 0, 0, 7, 0, 7, 7] },
|
||||
"cobblemon:thunderpunch_targetlinger": { "light_levels": [0, 7, 0, 7, 6, 0] },
|
||||
"cobblemon:thunderpunch_targetsparks": { "light_levels": [0] },
|
||||
|
||||
"cobblemon:thundershock_actor": { "light_levels": [1, 1, 5, 3, 6, 1, 1, 6, 7, 1, 1] },
|
||||
"cobblemon:thundershock_actorbolts": { "light_levels": [1, 7, 5, 1, 1, 1, 5, 6, 1, 5, 1] },
|
||||
"cobblemon:thundershock_actorsparks": { "light_levels": [2] },
|
||||
"cobblemon:thundershock_target": { "light_levels": [2] },
|
||||
"cobblemon:thundershock_targetbolts": { "light_levels": [5, 1, 1, 5, 5, 1] },
|
||||
"cobblemon:thundershock_targetimpact": { "light_levels": [1, 1, 5, 1, 6, 1, 5] },
|
||||
|
||||
"cobblemon:thunderwave_actor": { "light_levels": [5, 6, 3, 0, 0, 0] },
|
||||
"cobblemon:thunderwave_impact1": { "light_levels": [2, 3, 0, 0, 5, 2, 4, 3] },
|
||||
"cobblemon:thunderwave_impact2": { "light_levels": [5, 0, 0, 5, 0, 0, 2, 0] },
|
||||
"cobblemon:thunderwave_impact3": { "light_levels": [2, 5, 0, 4, 0, 3] },
|
||||
"cobblemon:thunderwave_launch": { "light_levels": [0, 2, 0, 0, 4, 5] },
|
||||
"cobblemon:thunderwave_launch1": { "light_levels": [0, 0, 3, 2, 0, 3, 3, 0] },
|
||||
"cobblemon:thunderwave_launch2": { "light_levels": [0, 2, 2, 0, 0, 2, 0, 0] },
|
||||
"cobblemon:thunderwave_sparking": { "light_levels": [0, 3, 0, 4] },
|
||||
|
||||
"cobblemon:timerball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:timerball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:timerball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:timerball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:timerball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:timerball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:timerball/casual/sendflash": { "light_levels": [0, 1, 2, 2, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
|
||||
"cobblemon:ultraball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:ultraball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ultraball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ultraball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 0] },
|
||||
"cobblemon:ultraball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:ultraball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:ultraball/casual/sendflash": { "light_levels": [0, 1, 3, 3, 4, 2, 2, 2, 2, 1, 1, 1, 0] },
|
||||
|
||||
"cobblemon:verdantball/ballsparkle": { "light_levels": [4, 1, 1, 0] },
|
||||
"cobblemon:verdantball/battle/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:verdantball/battle/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:verdantball/battle/sendflash": { "light_levels": [0, 1, 2, 2, 3, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0] },
|
||||
"cobblemon:verdantball/casual/ballsendsparkle": { "light_levels": [4, 1, 4, 1, 4, 1, 1, 4, 1, 1, 0] },
|
||||
"cobblemon:verdantball/casual/ballsparks": { "light_levels": [1, 2, 3, 4, 4, 4, 3, 2, 1, 0] },
|
||||
"cobblemon:verdantball/casual/sendflash": { "light_levels": [0, 1, 3, 4, 4, 2, 2, 2, 2, 1, 1, 0] },
|
||||
|
||||
"cobblemon:wild_shiny_ring": { "light_levels": [1] },
|
||||
|
||||
"cobblemon:willowisp_actor": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:willowisp_actorappear": { "light_levels": [3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:willowisp_actorburst": { "light_levels": [3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:willowisp_actorcinder": { "light_levels": [4] },
|
||||
"cobblemon:willowisp_actorproj": { "light_levels": [3, 3, 4, 5, 6, 6, 5, 4, 3, 3] },
|
||||
"cobblemon:willowisp_actorwisp": { "light_levels": [5, 5, 5, 3, 3, 5, 6, 6, 5, 5, 5] },
|
||||
"cobblemon:willowisp_target": { "light_levels": [3, 4, 5, 6, 6, 5, 4, 3, 3] }
|
||||
}
|
||||
@@ -2539,6 +2539,10 @@
|
||||
"cobblemon.config.ui.summary_pokemon_follow_cursor.tooltip": "Whether or not Pokémon should follow the mouse cursor with their heads in the Summary screen.",
|
||||
"cobblemon.config.ui.animate_battle_tiles": "Animate Battle Tiles",
|
||||
"cobblemon.config.ui.animate_battle_tiles.tooltip": "Whether or not the battle portraits of Pokemon should be animated.",
|
||||
"cobblemon.config.ui.shader_particle_bypass": "Shader Particle Bypass",
|
||||
"cobblemon.config.ui.shader_particle_bypass.tooltip": "When enabled, Cobblemon particles are redrawn after shaderpack composition so Iris and OptiFine shaderpacks do not alter their appearance.",
|
||||
"cobblemon.config.ui.max_lit_particles_per_emitter": "Max Lit Particles Per Emitter",
|
||||
"cobblemon.config.ui.max_lit_particles_per_emitter.tooltip": "With LambDynamicLights installed, the most particles from a single effect that may emit real dynamic light at once. Higher looks better but costs more performance; 0 disables particle dynamic lights.",
|
||||
"cobblemon.config.ui.party_portrait_animations": "Party Portrait Animations",
|
||||
"cobblemon.config.ui.party_portrait_animations.never_animate": "Never Animate",
|
||||
"cobblemon.config.ui.party_portrait_animations.never_animate.tooltip": "No portraits animate",
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
import java.net.URI
|
||||
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
force(libs.fabric.loader)
|
||||
@@ -38,6 +40,7 @@ repositories {
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
maven(url = "https://api.modrinth.com/maven")
|
||||
maven(url = "https://maven.terraformersmc.com/")
|
||||
maven(url = "https://maven.gegy.dev") // LambDynamicLights + spruceui/pridelib (dev runtime)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -48,6 +51,35 @@ dependencies {
|
||||
isTransitive = false
|
||||
}
|
||||
modLocalRuntime(libs.fabric.debugutils)
|
||||
|
||||
// Shader-compat testing (DEV RUNTIME ONLY — never shipped, never a real dependency).
|
||||
// Lets `runClient` load Iris + Sodium so shaderpacks actually run, which is required to
|
||||
// exercise ParticleMaterials' depthMask branch (see ShaderCompat). isTransitive = false so
|
||||
// these don't drag in a second copy of Fabric API / FLK (already provided above). If you bump
|
||||
// these, keep the Iris<->Sodium pairing valid (Iris 1.8.x needs Sodium 0.6.x for MC 1.21.1).
|
||||
modLocalRuntime("maven.modrinth:iris:1.8.8+1.21.1-fabric") { isTransitive = false }
|
||||
modLocalRuntime("maven.modrinth:sodium:mc1.21.1-0.6.13-fabric") { isTransitive = false }
|
||||
// Iris bundles these as jar-in-jar in production, but loom doesn't add a mod's nested *libraries*
|
||||
// to the dev classpath, so the dev client crashes with NoClassDefFoundError (e.g. org.anarres.cpp
|
||||
// / glsl-transformer) when Iris loads a shaderpack. Supply them as plain dev-runtime libs.
|
||||
// Versions are taken verbatim from iris-1.8.8's META-INF/jars — keep them in lockstep if Iris is
|
||||
// bumped. localRuntime = dev runtime only, not remapped, not exported to the published jar.
|
||||
localRuntime("org.anarres:jcpp:1.4.14")
|
||||
localRuntime("io.github.douira:glsl-transformer:2.0.1")
|
||||
localRuntime("org.antlr:antlr4-runtime:4.13.1")
|
||||
|
||||
// Dynamic lighting (DEV RUNTIME ONLY). Cobblemon compiles against the LambDynamicLights API
|
||||
// (modCompileOnly, mojmap; see common/build.gradle.kts); this provides the running mod in dev so
|
||||
// runClient actually exercises the dynamic lights. Pinned to 4.1.6 to match that API and fabric
|
||||
// loader 0.17.2 (4.8.9 needs loader 0.18.4 or newer). Loom does not surface a mod's bundled
|
||||
// dependency mods to the dev run, so its four are listed explicitly (from gegy + Maven Central).
|
||||
// Bump all five together if LambDynamicLights is updated.
|
||||
modLocalRuntime("maven.modrinth:lambdynamiclights:4.1.6+1.21.1")
|
||||
modLocalRuntime("dev.lambdaurora.lambdynamiclights:lambdynamiclights-api:4.1.6+1.21.1")
|
||||
modLocalRuntime("dev.lambdaurora:spruceui:6.2.1+1.21")
|
||||
modLocalRuntime("dev.yumi.mc.core:yumi-mc-foundation:1.0.0-alpha.7+1.21.1")
|
||||
modLocalRuntime("io.github.queerbric:pridelib:1.2.1+1.21")
|
||||
|
||||
modImplementation(libs.fabric.loader)
|
||||
modApi(libs.fabric.api)
|
||||
modApi(libs.bundles.fabric)
|
||||
@@ -110,6 +142,57 @@ publishing {
|
||||
}
|
||||
|
||||
tasks {
|
||||
// Downloads the Complementary Unbound shaderpack into the dev client's shaderpacks/ folder and
|
||||
// enables Iris by default, so `runClient` comes up shader-ready with zero manual setup. Both
|
||||
// writes are idempotent: existing files are left untouched, so your in-game shader choice and
|
||||
// any pack you swap in are preserved across runs. Run dir is "runClient" (see platform-conventions).
|
||||
val setupShaderTesting by registering {
|
||||
group = "cobblemon"
|
||||
description = "Provisions the test shaderpacks + enables Iris for the dev runClient."
|
||||
// The four Iris packs we want particles to look correct under. Swap between them in-game
|
||||
// (Video Settings -> Shader Packs) to A/B the premultiplied-alpha fix in ParticleMaterials.
|
||||
// <filename> to <direct Modrinth CDN url>.
|
||||
//
|
||||
// VERSIONS ARE PINNED FOR MC 1.21.1. The newest releases of these packs reference the
|
||||
// BIOME_PALE_GARDEN uniform (Pale Garden is a 1.21.4 biome), which Iris cannot resolve on
|
||||
// 1.21.1 -> hard crash building the render pipeline ("Unknown variable: BIOME_PALE_GARDEN").
|
||||
// Each pin below was confirmed Pale-Garden-free by grepping the archive. If this project ever
|
||||
// targets >= 1.21.4, bump these to the latest versions.
|
||||
val packs = mapOf(
|
||||
"ComplementaryUnbound_r5.3.zip" to "https://cdn.modrinth.com/data/R6NEzAwj/versions/CVu3AGAd/ComplementaryUnbound_r5.3.zip",
|
||||
"ComplementaryReimagined_r5.3.zip" to "https://cdn.modrinth.com/data/HVnmMxH1/versions/71Hn3myZ/ComplementaryReimagined_r5.3.zip",
|
||||
"Bliss_v2.1.2_(Chocapic13_Shaders_edit).zip" to "https://cdn.modrinth.com/data/ZvMtQlho/versions/kC2Y8q1P/Bliss_v2.1.2_%28Chocapic13_Shaders_edit%29.zip",
|
||||
"photon_v1.1.zip" to "https://cdn.modrinth.com/data/lLqFfGNs/versions/6FdrBtKp/photon_v1.1.zip"
|
||||
)
|
||||
val shaderpacksDir = layout.projectDirectory.dir("runClient/shaderpacks")
|
||||
val irisProps = layout.projectDirectory.file("runClient/config/iris.properties")
|
||||
// Default the in-game selection to Complementary Unbound (the originally-reported pack); idempotent.
|
||||
val defaultPack = "ComplementaryUnbound_r5.3.zip"
|
||||
outputs.dir(shaderpacksDir)
|
||||
doLast {
|
||||
packs.forEach { (filename, url) ->
|
||||
val zip = shaderpacksDir.file(filename).asFile
|
||||
if (!zip.exists()) {
|
||||
zip.parentFile.mkdirs()
|
||||
logger.lifecycle("Downloading shaderpack -> ${zip.relativeTo(rootProject.projectDir)}")
|
||||
URI(url).toURL().openStream().use { input ->
|
||||
zip.outputStream().use { output -> input.copyTo(output) }
|
||||
}
|
||||
}
|
||||
}
|
||||
val props = irisProps.asFile
|
||||
if (!props.exists()) {
|
||||
props.parentFile.mkdirs()
|
||||
props.writeText("enableShaders=true\nshaderPack=$defaultPack\n")
|
||||
logger.lifecycle("Wrote ${props.relativeTo(rootProject.projectDir)} (Iris auto-enabled with $defaultPack).")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
named("runClient") {
|
||||
dependsOn(setupShaderTesting)
|
||||
}
|
||||
|
||||
// The AW file is needed in :fabric project resources when the game is run.
|
||||
val copyAccessWidener by registering(Copy::class) {
|
||||
from(loom.accessWidenerPath)
|
||||
|
||||
@@ -47,6 +47,7 @@ import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper
|
||||
@@ -158,22 +159,29 @@ class CobblemonFabricClient: ClientModInitializer, CobblemonClientImplementation
|
||||
ClientPlayConnectionEvents.DISCONNECT.register { _, client -> client.player?.let { PlatformEvents.CLIENT_PLAYER_LOGOUT.post(ClientPlayerEvent.Logout(it)) } }
|
||||
ItemTooltipCallback.EVENT.register { stack, context, type, lines -> PlatformEvents.CLIENT_ITEM_TOOLTIP.post(ItemTooltipEvent(stack, context, type, lines)) }
|
||||
|
||||
WorldRenderEvents.AFTER_TRANSLUCENT.register { context -> PlatformEvents.RENDER.post(
|
||||
RenderEvent(
|
||||
stage = RenderEvent.Stage.TRANSLUCENT,
|
||||
levelRenderer = context.worldRenderer(),
|
||||
poseStack = context.matrixStack() ?: PoseStack(),
|
||||
modelViewMatrix = context.positionMatrix(),
|
||||
projectionMatrix = context.projectionMatrix(),
|
||||
tickCounter = context.tickCounter(),
|
||||
camera = context.camera()
|
||||
)
|
||||
)
|
||||
}
|
||||
WorldRenderEvents.AFTER_TRANSLUCENT.register { context -> postRenderStage(RenderEvent.Stage.TRANSLUCENT, context) }
|
||||
// LAST captures the camera transform while it is still applied; POST_LEVEL fires after the level
|
||||
// (and any shaderpack composite) finishes, the only point a draw is NOT intercepted by Iris/OptiFine.
|
||||
WorldRenderEvents.LAST.register { context -> postRenderStage(RenderEvent.Stage.LAST, context) }
|
||||
WorldRenderEvents.END.register { context -> postRenderStage(RenderEvent.Stage.POST_LEVEL, context) }
|
||||
|
||||
CobblemonModelPredicateRegistry.registerPredicates()
|
||||
}
|
||||
|
||||
private fun postRenderStage(stage: RenderEvent.Stage, context: WorldRenderContext) {
|
||||
PlatformEvents.RENDER.post(
|
||||
RenderEvent(
|
||||
stage = stage,
|
||||
levelRenderer = context.worldRenderer(),
|
||||
poseStack = context.matrixStack() ?: PoseStack(),
|
||||
modelViewMatrix = context.positionMatrix(),
|
||||
projectionMatrix = context.projectionMatrix(),
|
||||
tickCounter = context.tickCounter(),
|
||||
camera = context.camera()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun registerLayer(modelLayer: ModelLayerLocation, supplier: Supplier<LayerDefinition>) {
|
||||
EntityModelLayerRegistry.registerModelLayer(modelLayer) { supplier.get() }
|
||||
}
|
||||
@@ -201,4 +209,4 @@ class CobblemonFabricClient: ClientModInitializer, CobblemonClientImplementation
|
||||
override fun <T : Entity> registerEntityRenderer(type: EntityType<out T>, factory: EntityRendererProvider<T>) {
|
||||
EntityRendererRegistry.register(type, factory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -74,6 +74,8 @@ object NeoForgeClientPlatformEventHandler {
|
||||
fun onRenderLevelStageEvent(event: RenderLevelStageEvent) {
|
||||
val stage = when (event.stage) {
|
||||
RenderLevelStageEvent.Stage.AFTER_PARTICLES -> RenderEvent.Stage.TRANSLUCENT
|
||||
RenderLevelStageEvent.Stage.AFTER_WEATHER -> RenderEvent.Stage.LAST
|
||||
RenderLevelStageEvent.Stage.AFTER_LEVEL -> RenderEvent.Stage.POST_LEVEL
|
||||
else -> return
|
||||
}
|
||||
|
||||
@@ -89,4 +91,4 @@ object NeoForgeClientPlatformEventHandler {
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user