forked from mirrors/cobblemon
Compare commits
51
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f52585386 | ||
|
|
9a2443f709 | ||
|
|
6d3ddece03 | ||
|
|
99a0e83962 | ||
|
|
7572530a36 | ||
|
|
7f9ed14be7 | ||
|
|
f3e6e5a94c | ||
|
|
325c4093eb | ||
|
|
2510b23401 | ||
|
|
d4b6f6e55e | ||
|
|
3d38dc2c99 | ||
|
|
6cc384abbb | ||
|
|
205ec6a228 | ||
|
|
943625056a | ||
|
|
06e0bbc502 | ||
|
|
d83d5cd3da | ||
|
|
6215f8afa5 | ||
|
|
b39068283f | ||
|
|
34c4cc1579 | ||
|
|
b2e1558e03 | ||
|
|
90bd717d7b | ||
|
|
34e64da0c6 | ||
|
|
7327ae14fd | ||
|
|
ae05be2ce2 | ||
|
|
5f2984a3d0 | ||
|
|
de41fdf871 | ||
|
|
af491f02a2 | ||
|
|
e40a3331e2 | ||
|
|
6dac494a0f | ||
|
|
246ddc7a54 | ||
|
|
f7c560db78 | ||
|
|
bae7ad5ce1 | ||
|
|
2e59fa4f68 | ||
|
|
474cf1c6db | ||
|
|
8cd46a5a49 | ||
|
|
382bf67866 | ||
|
|
c7d93ebfc5 | ||
|
|
002e68b599 | ||
|
|
2ac2a57e12 | ||
|
|
b84002d142 | ||
|
|
f96ea92a4c | ||
|
|
a1e10bf3b1 | ||
|
|
eccb4bb7af | ||
|
|
254d5e1343 | ||
|
|
a3cb3e8d9e | ||
|
|
69354fac58 | ||
|
|
d40f3599b9 | ||
|
|
531ed8b827 | ||
|
|
fc844fca9e | ||
|
|
23bfa090d2 | ||
|
|
87a36020f6 |
@@ -0,0 +1,9 @@
|
||||
- Some kind of particle effect for them? they're meant to have glowing eyes, so maybe some red particles on the eye locator
|
||||
--- global posers? stacked posers?
|
||||
--- red texture seems to be what some people wanted.
|
||||
|
||||
/- shoulder mounts part of it
|
||||
- omni boost
|
||||
- roar when player comes within reach, adjust levels
|
||||
|
||||
- Riding settings to control what the min scale is for a pokemon to be ridable.
|
||||
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"lastSavedVersion": "1.7.1",
|
||||
"maxPokemonLevel": 100,
|
||||
"maxPokemonFriendship": 255,
|
||||
"announceDropItems": true,
|
||||
"defaultDropItemMethod": "on-entity",
|
||||
"dropAfterDeathAnimation": false,
|
||||
"ambientPokemonCryTicks": 1080,
|
||||
"defaultKeyItems": [],
|
||||
"defaultBoxCount": 30,
|
||||
"pokemonSaveIntervalSeconds": 30,
|
||||
"storageFormat": "nbt",
|
||||
"preventCompletePartyDeposit": false,
|
||||
"mongoDBConnectionString": "mongodb://localhost:27017",
|
||||
"mongoDBDatabaseName": "cobblemon",
|
||||
"maxVerticalCorrectionBlocks": 64,
|
||||
"minimumLevelRangeMax": 10,
|
||||
"enableSpawning": true,
|
||||
"minimumDistanceBetweenEntities": 8.0,
|
||||
"maxNearbyBlocksHorizontalRange": 4,
|
||||
"maxNearbyBlocksVerticalRange": 2,
|
||||
"maxVerticalSpace": 8,
|
||||
"spawningZoneDiameter": 8,
|
||||
"spawningZoneHeight": 16,
|
||||
"ticksBetweenSpawnAttempts": 20.0,
|
||||
"minimumSpawningZoneDistanceFromPlayer": 16.0,
|
||||
"maximumSpawningZoneDistanceFromPlayer": 64.0,
|
||||
"maximumSpawnsPerPass": 8,
|
||||
"exportSpawnConfig": false,
|
||||
"savePokemonToWorld": true,
|
||||
"exportStarterConfig": false,
|
||||
"autoUpdateShowdown": true,
|
||||
"defaultFleeDistance": 32.0,
|
||||
"allowExperienceFromPvP": true,
|
||||
"experienceShareMultiplier": 0.5,
|
||||
"luckyEggMultiplier": 1.5,
|
||||
"allowSpectating": true,
|
||||
"experienceMultiplier": 2.0,
|
||||
"pokemonPerChunk": 1.0,
|
||||
"pokeSnackPokemonPerChunk": 2.0,
|
||||
"passiveStatuses": {
|
||||
"cobblemon:poison": "180-300",
|
||||
"cobblemon:poisonbadly": "180-300",
|
||||
"cobblemon:paralysis": "180-300",
|
||||
"cobblemon:frozen": "180-300",
|
||||
"cobblemon:sleep": "180-300",
|
||||
"cobblemon:burn": "180-300"
|
||||
},
|
||||
"infiniteHealerCharge": false,
|
||||
"maxHealerCharge": 6.0,
|
||||
"secondsToChargeHealingMachine": 900.0,
|
||||
"defaultFaintTimer": 300,
|
||||
"faintAwakenHealthPercent": 0.2,
|
||||
"healPercent": 0.05,
|
||||
"healTimer": 60,
|
||||
"baseApricornTreeGenerationChance": 0.1,
|
||||
"displayEntityLevelLabel": true,
|
||||
"displayEntityNameLabel": true,
|
||||
"displayNameForUnknownPokemon": false,
|
||||
"displayEntityLabelsWhenCrouchingOnly": false,
|
||||
"shinyRate": 8192.0,
|
||||
"shinyNoticeParticlesDistance": 24.0,
|
||||
"captureCalculator": "cobblemon",
|
||||
"playerDamagePokemon": true,
|
||||
"appleLeftoversChance": 0.025,
|
||||
"maxRootsInArea": 5,
|
||||
"bigRootPropagationChance": 0.1,
|
||||
"energyRootChance": 0.25,
|
||||
"maxDynamaxLevel": 10,
|
||||
"teraTypeRate": 20.0,
|
||||
"defaultPasturedPokemonLimit": 16,
|
||||
"pastureBlockUpdateTicks": 40,
|
||||
"pastureMaxWanderDistance": 64,
|
||||
"pastureMaxPerChunk": 4.0,
|
||||
"maxInsertedFossilItems": 2,
|
||||
"walkingInBattleAnimations": false,
|
||||
"battleWildMaxDistance": 12.0,
|
||||
"tradeMaxDistance": 12.0,
|
||||
"battlePvPMaxDistance": 32.0,
|
||||
"battleSpectateMaxDistance": 64.0,
|
||||
"maxPokedexScanningDetectionRange": 10.0,
|
||||
"hideUnimplementedPokemonInThePokedex": false,
|
||||
"summaryPokemonFollowCursor": true,
|
||||
"partyPortraitAnimations": "NEVER_ANIMATE",
|
||||
"pcProfileAnimations": "ANIMATE_SELECTED",
|
||||
"summaryProfileAnimations": "ANIMATE_SELECTED",
|
||||
"animateBattleTiles": false,
|
||||
"thirdPersonViewBobbing": true,
|
||||
"invertRoll": false,
|
||||
"invertPitch": false,
|
||||
"invertYaw": false,
|
||||
"xAxisSensitivity": 1.0,
|
||||
"yAxisSensitivity": 1.0,
|
||||
"swapXAndYAxes": false,
|
||||
"rightingDelay": -1.0,
|
||||
"disableRoll": false,
|
||||
"displayControlSeconds": 3,
|
||||
"infiniteRideStamina": false,
|
||||
"rememberRidingCamera": false,
|
||||
"enableDebugKeys": true,
|
||||
"despawnerNearDistance": 32.0,
|
||||
"despawnerFarDistance": 96.0,
|
||||
"despawnerMinAgeTicks": 600,
|
||||
"despawnerMaxAgeTicks": 3600
|
||||
}
|
||||
@@ -13,5 +13,6 @@ public interface ChannelDuck {
|
||||
void cobblemon$inverseAttenuation(float rolloffFactor);
|
||||
void cobblemon$clearFilters();
|
||||
|
||||
// void cobblemon$exponentialAttenuation(float rolloff, float refDistance, float maxDistance);
|
||||
void cobblemon$applyReverb(float decayTime, float gain, float diffusion, float density);
|
||||
void cobblemon$clearReverb();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.mixin;
|
||||
import com.cobblemon.mod.common.duck.ChannelDuck;
|
||||
import com.mojang.blaze3d.audio.Channel;
|
||||
import org.lwjgl.openal.AL10;
|
||||
import org.lwjgl.openal.AL11;
|
||||
import org.lwjgl.openal.EXTEfx;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -21,8 +22,10 @@ public abstract class ChannelMixin implements ChannelDuck {
|
||||
@Shadow
|
||||
private int source;
|
||||
|
||||
// Id of filter applied when sound is obstructed
|
||||
// Ids of effects applied to the channel
|
||||
private int cobblemon$lowPassFilterId = 0;
|
||||
private int cobblemon$reverbEffectId = 0;
|
||||
private int cobblemon$reverbSlotId = 0;
|
||||
|
||||
@Override
|
||||
public void cobblemon$applyLowPassFilter(float gain, float hfGain) {
|
||||
@@ -67,4 +70,54 @@ public abstract class ChannelMixin implements ChannelDuck {
|
||||
cobblemon$lowPassFilterId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cobblemon$applyReverb(float decayTime, float gain, float diffusion, float density) {
|
||||
// Clean up existing reverb first if it exists
|
||||
cobblemon$clearReverb();
|
||||
|
||||
// Create the effect object
|
||||
int effectId = EXTEfx.alGenEffects();
|
||||
if (!EXTEfx.alIsEffect(effectId)) {
|
||||
System.err.println("Failed to create OpenAL reverb effect");
|
||||
return;
|
||||
}
|
||||
|
||||
EXTEfx.alEffecti(effectId, EXTEfx.AL_EFFECT_TYPE, EXTEfx.AL_EFFECT_REVERB);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DECAY_TIME, decayTime);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_GAIN, gain);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DIFFUSION, diffusion);
|
||||
EXTEfx.alEffectf(effectId, EXTEfx.AL_REVERB_DENSITY, density);
|
||||
|
||||
// Create auxiliary effect slot and load effect into it
|
||||
int slotId = EXTEfx.alGenAuxiliaryEffectSlots();
|
||||
if (!EXTEfx.alIsAuxiliaryEffectSlot(slotId)) {
|
||||
System.err.println("Failed to create OpenAL auxiliary effect slot");
|
||||
EXTEfx.alDeleteEffects(effectId);
|
||||
return;
|
||||
}
|
||||
|
||||
EXTEfx.alAuxiliaryEffectSloti(slotId, EXTEfx.AL_EFFECTSLOT_EFFECT, effectId);
|
||||
|
||||
// Route source through the slot — send 0, no direct filter
|
||||
AL11.alSource3i(source, EXTEfx.AL_AUXILIARY_SEND_FILTER, slotId, 0, EXTEfx.AL_FILTER_NULL);
|
||||
|
||||
cobblemon$reverbEffectId = effectId;
|
||||
cobblemon$reverbSlotId = slotId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cobblemon$clearReverb() {
|
||||
if (cobblemon$reverbSlotId != 0) {
|
||||
// Detach source from slot
|
||||
AL11.alSource3i(source, EXTEfx.AL_AUXILIARY_SEND_FILTER,
|
||||
EXTEfx.AL_EFFECTSLOT_NULL, 0, EXTEfx.AL_FILTER_NULL);
|
||||
EXTEfx.alDeleteAuxiliaryEffectSlots(cobblemon$reverbSlotId);
|
||||
cobblemon$reverbSlotId = 0;
|
||||
}
|
||||
if (cobblemon$reverbEffectId != 0) {
|
||||
EXTEfx.alDeleteEffects(cobblemon$reverbEffectId);
|
||||
cobblemon$reverbEffectId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,8 @@ import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacke
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.aspects.MARK_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.ALPHA_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.CHARACTERISTIC_RAINBOW_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.COSMETIC_SLOT_ASPECT
|
||||
import com.cobblemon.mod.common.pokemon.aspects.GENDER_ASPECT
|
||||
@@ -319,6 +321,8 @@ object Cobblemon {
|
||||
GENDER_ASPECT.register()
|
||||
COSMETIC_SLOT_ASPECT.register()
|
||||
CHARACTERISTIC_RAINBOW_ASPECT.register()
|
||||
ALPHA_ASPECT.register()
|
||||
MARK_ASPECT.register()
|
||||
|
||||
SpeciesFeatures.types["choice"] = ChoiceSpeciesFeatureProvider::class.java
|
||||
SpeciesFeatures.types["flag"] = FlagSpeciesFeatureProvider::class.java
|
||||
|
||||
@@ -321,6 +321,8 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(MarkingsUpdatePacket.ID, MarkingsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideBoostsUpdatePacket.ID, RideBoostsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideStaminaUpdatePacket.ID, RideStaminaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(AlphaUpdatePacket.ID, AlphaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(ScaleModifierUpdatePacket.ID, ScaleModifierUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Evolution start
|
||||
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
@@ -37,6 +37,9 @@ object CobblemonSensors {
|
||||
@JvmField
|
||||
val POKEMON_DEFEND_OWNER = register("pokemon_owner_under_attack", ::DefendOwnerSensor)
|
||||
|
||||
@JvmField
|
||||
val ALPHA_LEVEL_MATCHING = register("alpha_level_matching", ::AlphaLevelMatchingSensor)
|
||||
|
||||
@JvmField
|
||||
val NEARBY_GROWABLE_CROPS = register("nearby_growable_crops", ::PokemonGrowableCropSensor)
|
||||
|
||||
|
||||
+19
-7
@@ -46,6 +46,9 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
): PokemonEntity? {
|
||||
var bestLeader: PokemonEntity? = null
|
||||
val (currentLeaderEntity, currentLeaderDefinition) = currentLeader ?: Pair(null, null)
|
||||
if (currentLeaderEntity?.pokemon?.isAlpha == true) { // don't swap to a new alpha leader (I worry about mons constantly swapping between alphas if more are close by...)
|
||||
return currentLeaderEntity
|
||||
}
|
||||
var bestTier = currentLeaderDefinition?.tier?.let { it + 1 } ?: 0 // Only upgrade to a higher tier leader
|
||||
var bestDistance = Float.MAX_VALUE
|
||||
nearbyEntities.findAll {
|
||||
@@ -53,6 +56,7 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
it != currentLeader &&
|
||||
it.pokemon.storeCoordinates.get()?.store !is PartyStore &&
|
||||
it.getHerdSize() < it.behaviour.herd.maxSize &&
|
||||
//!it.brain.hasMemoryValue(CobblemonMemories.HERD_LEADER) &&
|
||||
!it.brain.hasMemoryValue(CobblemonMemories.POKEMON_DROWSY)
|
||||
}.forEach { possibleLeader ->
|
||||
possibleLeader as PokemonEntity
|
||||
@@ -65,13 +69,21 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
val distance = entity.distanceTo(possibleLeader)
|
||||
if (bestMatchingHerdLeader.tier < bestTier) {
|
||||
return@forEach // No need to check further if this leader is worse than the best found so far
|
||||
} else if ((distance > bestDistance && !possibleLeaderIsAlreadyALeader) && bestMatchingHerdLeader.tier == bestTier) {
|
||||
return@forEach // No need to check further if this leader is farther than the best found so far, unless they are already a leader - I'd prefer to join a pack
|
||||
} else {
|
||||
bestLeader = possibleLeader
|
||||
bestDistance = distance
|
||||
bestTier = bestMatchingHerdLeader.tier
|
||||
} else if (bestMatchingHerdLeader.tier == bestTier) {
|
||||
if (possibleLeader.pokemon.isAlpha && bestLeader?.pokemon?.isAlpha == true) {
|
||||
if (entity.random.nextBoolean()) { // choose random alpha if multiple are present
|
||||
bestLeader = possibleLeader
|
||||
bestDistance = distance
|
||||
}
|
||||
return@forEach
|
||||
}
|
||||
if (distance > bestDistance && !possibleLeaderIsAlreadyALeader) {
|
||||
return@forEach // No need to check further if this leader is farther than the best found so far, unless they are already a leader - I'd prefer to join a pack
|
||||
}
|
||||
}
|
||||
bestLeader = possibleLeader
|
||||
bestDistance = distance
|
||||
bestTier = bestMatchingHerdLeader.tier
|
||||
}
|
||||
return bestLeader ?: currentLeaderEntity
|
||||
}
|
||||
@@ -124,4 +136,4 @@ class FindHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -65,9 +65,8 @@ class MaintainHerdLeaderTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
|
||||
val leader = instance.get(herdLeader).let(UUID::fromString).let(world::getEntity) as? PokemonEntity
|
||||
val currentLeaderDefinition = leader?.let { leader ->
|
||||
entity.behaviour.herd.toleratedLeaders.find { it.pokemon.matches(leader) }
|
||||
}
|
||||
val currentLeaderDefinition = leader?.let {
|
||||
entity.behaviour.herd.bestMatchLeader(entity, it) }
|
||||
if (leader == null || currentLeaderDefinition == null) {
|
||||
entity.brain.eraseMemory(CobblemonMemories.HERD_LEADER)
|
||||
return@Trigger true // No leader, so we erase the memory
|
||||
|
||||
@@ -70,6 +70,7 @@ class SpawnBait(
|
||||
val SHINY_REROLL = cobblemonResource("shiny_reroll")
|
||||
val DROPS_REROLL = cobblemonResource("drops_reroll")
|
||||
val HIDDEN_ABILITY_CHANCE = cobblemonResource("ha_chance")
|
||||
val ALPHA_CHANCE = cobblemonResource("alpha_chance")
|
||||
val POKEMON_CHANCE = cobblemonResource("pokemon_chance")
|
||||
val FRIENDSHIP = cobblemonResource("friendship")
|
||||
val RARITY_BUCKET = cobblemonResource("rarity_bucket")
|
||||
@@ -90,6 +91,7 @@ class SpawnBait(
|
||||
registerEffect(GENDER_CHANCE) { entity, effect -> FishingSpawnCause.alterGenderAttempt(entity, effect) }
|
||||
registerEffect(LEVEL_RAISE) { entity, effect -> FishingSpawnCause.alterLevelAttempt(entity, effect) }
|
||||
registerEffect(HIDDEN_ABILITY_CHANCE) { entity, _ -> FishingSpawnCause.alterHAAttempt(entity) }
|
||||
registerEffect(ALPHA_CHANCE) { entity, effect -> FishingSpawnCause.alterAlphaAttempt(entity) }
|
||||
registerEffect(FRIENDSHIP) { entity, effect -> FishingSpawnCause.alterFriendshipAttempt(entity, effect) }
|
||||
CobblemonEvents.BAIT_EFFECT_REGISTRATION.post(BaitEffectFunctionRegistryEvent()) { event ->
|
||||
event.functions.forEach { (type, function) -> registerEffect(type, function) }
|
||||
|
||||
@@ -27,7 +27,8 @@ class Mark(
|
||||
val replace: List<ResourceLocation>?,
|
||||
val group: String?,
|
||||
val chance: Float = 0F,
|
||||
val indexNumber: Int?
|
||||
val indexNumber: Int?,
|
||||
val aspects: List<String> = emptyList()
|
||||
): StringRepresentable {
|
||||
|
||||
companion object {
|
||||
@@ -42,7 +43,8 @@ class Mark(
|
||||
buffer.readNullable { buffer.readList { buffer.readResourceLocation() } },
|
||||
buffer.readNullable { buffer.readString() },
|
||||
buffer.readFloat(),
|
||||
buffer.readNullable { buffer.readInt() }
|
||||
buffer.readNullable { buffer.readInt() },
|
||||
buffer.readList { buffer.readString() }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -83,5 +85,6 @@ class Mark(
|
||||
buffer.writeNullable(group) { _, v -> buffer.writeString(v) }
|
||||
buffer.writeFloat(chance)
|
||||
buffer.writeNullable(indexNumber) { _, v -> buffer.writeInt(v) }
|
||||
buffer.writeCollection(aspects) { _, v -> buffer.writeString(v) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1803,6 +1803,7 @@ object MoLangFunctions {
|
||||
}
|
||||
map.put("nature") { StringValue(pokemon.nature.toString()) }
|
||||
map.put("is_wild") { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
|
||||
map.put("is_alpha") { DoubleValue(pokemon.isAlpha) }
|
||||
map.put("is_shiny") { DoubleValue(pokemon.shiny) }
|
||||
map.put("is_in_party") { DoubleValue(pokemon.storeCoordinates.get()?.store is PartyStore) }
|
||||
map.put("species") { pokemon.species.struct }
|
||||
@@ -2819,4 +2820,4 @@ object MoLangFunctions {
|
||||
}
|
||||
}
|
||||
|
||||
fun Either<ResourceLocation, ExpressionLike>.runScript(runtime: MoLangRuntime) = map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
|
||||
fun Either<ResourceLocation, ExpressionLike>.runScript(runtime: MoLangRuntime) = map({ CobblemonScripts.run(it, runtime) }, { it.resolve(runtime) })
|
||||
|
||||
@@ -132,6 +132,7 @@ open class PokemonProperties {
|
||||
props.gender = Gender.entries.toList().parsePropertyOfCollection(keyPairs, listOf("gender"), labelsOptional = true) { it.name.lowercase() }
|
||||
props.level = parseIntProperty(keyPairs, listOf("level", "lvl", "l"))?.coerceIn(1, Cobblemon.config.maxPokemonLevel)
|
||||
props.shiny = parseBooleanProperty(keyPairs, listOf("shiny", "s"))
|
||||
props.isAlpha = parseBooleanProperty(keyPairs, listOf("alpha", "is_alpha"))
|
||||
props.species = parseSpeciesIdentifier(keyPairs)
|
||||
props.form = parseForm(keyPairs)
|
||||
props.friendship = parseIntProperty(keyPairs, listOf("friendship"))?.coerceIn(0, Cobblemon.config.maxPokemonFriendship)
|
||||
@@ -368,6 +369,7 @@ open class PokemonProperties {
|
||||
var heldItem: String? = null
|
||||
var cosmeticItem: String? = null
|
||||
var scaleModifier: Float? = null
|
||||
var isAlpha: Boolean? = null
|
||||
|
||||
var minPerfectIVs: Int? = null
|
||||
var ivs: IVs? = null
|
||||
@@ -418,6 +420,7 @@ open class PokemonProperties {
|
||||
shiny?.let { pokemon.shiny = it }
|
||||
gender?.let { pokemon.gender = it }
|
||||
level?.let { pokemon.level = it }
|
||||
isAlpha?.let { pokemon.isAlpha = it }
|
||||
friendship?.also { pokemon.setFriendship(it) }
|
||||
fullness?.let { pokemon.currentFullness = it }
|
||||
pokeball?.let { PokeBalls.getPokeBall(it.asIdentifierDefaultingNamespace())?.let { pokeball -> pokemon.caughtBall = pokeball } }
|
||||
@@ -544,6 +547,7 @@ open class PokemonProperties {
|
||||
pokeball?.takeIf { it != pokemon.caughtBall.name.toString() }?.let { return false }
|
||||
nature?.takeIf { it != pokemon.nature.name.toString() }?.let { return false }
|
||||
ability?.takeIf { it != pokemon.ability.name }?.let { return false }
|
||||
isAlpha?.takeIf { it != pokemon.isAlpha }?.let { return false }
|
||||
status?.takeIf { it != pokemon.status?.status?.showdownName }?.let { return false }
|
||||
minPerfectIVs?.takeIf { pokemon.ivs.count { stat -> stat.value == IVs.MAX_VALUE } < it }?.let { return false }
|
||||
ivs?.forEach{ stat ->
|
||||
@@ -603,6 +607,7 @@ open class PokemonProperties {
|
||||
friendship?.takeIf { it != properties.friendship }?.let { return false }
|
||||
pokeball?.takeIf { it != properties.pokeball }?.let { return false }
|
||||
nature?.takeIf { it != properties.nature }?.let { return false }
|
||||
isAlpha?.takeIf { it != properties.isAlpha }?.let { return false }
|
||||
ability?.takeIf { it != properties.ability }?.let { return false }
|
||||
status?.takeIf { it != properties.status }?.let { return false }
|
||||
minPerfectIVs?.takeIf { it != properties.minPerfectIVs }?.let { return false }
|
||||
@@ -646,13 +651,13 @@ open class PokemonProperties {
|
||||
@JvmOverloads
|
||||
fun roll(pokemon: Pokemon, player: ServerPlayer? = null) {
|
||||
val baseTypes = pokemon.form.types.toList()
|
||||
var shinyRate = Cobblemon.config.shinyRate
|
||||
var shinyRate = config.shinyRate
|
||||
CobblemonEvents.SHINY_CHANCE_CALCULATION.post(ShinyChanceCalculationEvent(shinyRate, pokemon)) { event ->
|
||||
shinyRate = event.calculate(player)
|
||||
}
|
||||
if (this.shiny == null) pokemon.shiny = shinyRate.checkRate()
|
||||
if (this.teraType == null) pokemon.teraType =
|
||||
if (Cobblemon.config.teraTypeRate.checkRate()) {
|
||||
if (config.teraTypeRate.checkRate()) {
|
||||
var picked = TeraTypes.random(true)
|
||||
while (picked is ElementalTypeTeraType && picked.type in pokemon.types) {
|
||||
picked = TeraTypes.random(true)
|
||||
@@ -660,6 +665,11 @@ open class PokemonProperties {
|
||||
picked
|
||||
}
|
||||
else TeraTypes.forElementalType(baseTypes.random())
|
||||
isAlpha?.let { pokemon.isAlpha = it }
|
||||
if (this.scaleModifier == null) {
|
||||
pokemon.initializeScale()
|
||||
}
|
||||
pokemon.assignSizeMarks() // check size of mon and assign marks to it
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
@@ -682,6 +692,7 @@ open class PokemonProperties {
|
||||
pokeball?.let { nbt.putString(DataKeys.POKEMON_CAUGHT_BALL, it) }
|
||||
nature?.let { nbt.putString(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { nbt.putString(DataKeys.POKEMON_ABILITY, it) }
|
||||
isAlpha?.let { nbt.putBoolean(DataKeys.POKEMON_ALPHA, it) }
|
||||
status?.let { nbt.putString(DataKeys.POKEMON_STATUS_NAME, it) }
|
||||
minPerfectIVs?.let { nbt.putInt(DataKeys.POKEMON_MIN_PERFECT_IVS, it) }
|
||||
ivs?.let { nbt.put(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().get()) }
|
||||
@@ -717,6 +728,7 @@ open class PokemonProperties {
|
||||
pokeball = if (tag.contains(DataKeys.POKEMON_CAUGHT_BALL)) tag.getString(DataKeys.POKEMON_CAUGHT_BALL) else null
|
||||
nature = if (tag.contains(DataKeys.POKEMON_NATURE)) tag.getString(DataKeys.POKEMON_NATURE) else null
|
||||
ability = if (tag.contains(DataKeys.POKEMON_ABILITY)) tag.getString(DataKeys.POKEMON_ABILITY) else null
|
||||
isAlpha = if (tag.contains(DataKeys.POKEMON_ALPHA)) tag.getBoolean(DataKeys.POKEMON_ALPHA) else null
|
||||
status = if (tag.contains(DataKeys.POKEMON_STATUS_NAME)) tag.getString(DataKeys.POKEMON_STATUS_NAME) else null
|
||||
minPerfectIVs = if (tag.contains(DataKeys.POKEMON_MIN_PERFECT_IVS)) tag.getInt(DataKeys.POKEMON_MIN_PERFECT_IVS) else null
|
||||
ivs = if (tag.contains(DataKeys.POKEMON_IVS)) IVs.CODEC.decode(NbtOps.INSTANCE, tag.getCompound(DataKeys.POKEMON_IVS)).result().getOrNull()?.first else null
|
||||
@@ -753,6 +765,7 @@ open class PokemonProperties {
|
||||
pokeball?.let { json.addProperty(DataKeys.POKEMON_CAUGHT_BALL, it) }
|
||||
nature?.let { json.addProperty(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { json.addProperty(DataKeys.POKEMON_ABILITY, it) }
|
||||
isAlpha?.let { json.addProperty(DataKeys.POKEMON_ALPHA, it) }
|
||||
status?.let { json.addProperty(DataKeys.POKEMON_STATUS_NAME, it) }
|
||||
minPerfectIVs?.let { json.addProperty(DataKeys.POKEMON_MIN_PERFECT_IVS, it) }
|
||||
ivs?.let { json.add(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().get()) }
|
||||
@@ -788,6 +801,7 @@ open class PokemonProperties {
|
||||
pokeball = json.get(DataKeys.POKEMON_CAUGHT_BALL)?.asString
|
||||
nature = json.get(DataKeys.POKEMON_NATURE)?.asString
|
||||
ability = json.get(DataKeys.POKEMON_ABILITY)?.asString
|
||||
isAlpha = json.get(DataKeys.POKEMON_ALPHA)?.asBoolean
|
||||
status = json.get(DataKeys.POKEMON_STATUS_NAME)?.asString
|
||||
minPerfectIVs = json.get(DataKeys.POKEMON_MIN_PERFECT_IVS)?.asInt
|
||||
ivs = json.getAsJsonObject(DataKeys.POKEMON_IVS)?.let { IVs.CODEC.decode(JsonOps.INSTANCE, it).result().getOrNull()?.first }
|
||||
@@ -823,6 +837,7 @@ open class PokemonProperties {
|
||||
pokeball?.let { pieces.add("pokeball=$it") }
|
||||
nature?.let { pieces.add("nature=$it") }
|
||||
ability?.let { pieces.add("ability=$it") }
|
||||
isAlpha?.let { pieces.add("alpha=$it") }
|
||||
status?.let { pieces.add("status=$it") }
|
||||
minPerfectIVs?.let { pieces.add("min_perfect_ivs=$it") }
|
||||
ivs?.forEach{ stat ->
|
||||
|
||||
+9
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.ai.config.task.PollinateFlowerTaskConfig
|
||||
import com.cobblemon.mod.common.api.spawning.influence.SaccharineLogSlatheredInfluence
|
||||
import com.cobblemon.mod.common.block.entity.PokeSnackBlockEntity
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.particles.BlockParticleOption
|
||||
import net.minecraft.core.particles.ParticleOptions
|
||||
import net.minecraft.core.particles.ParticleTypes
|
||||
@@ -28,7 +29,14 @@ val aspectParticleMap: Map<String, ParticleData> = mapOf(
|
||||
ParticleTypes.BLOCK,
|
||||
CobblemonBlocks.POKE_SNACK.defaultBlockState()
|
||||
), 0.05, 3),
|
||||
PollinateFlowerTaskConfig.HAS_NECTAR_ASPECT to ParticleData.MinecraftParticle(ParticleTypes.FALLING_NECTAR, 0.075, 1)
|
||||
PollinateFlowerTaskConfig.HAS_NECTAR_ASPECT to ParticleData.MinecraftParticle(ParticleTypes.FALLING_NECTAR, 0.075, 1),
|
||||
// "alpha" to ParticleData.SnowstormParticle(
|
||||
// particle = cobblemonResource("alpha_eyes"),
|
||||
// chance = 1.0,
|
||||
// amount = 1,
|
||||
// locators = listOf("eye1", "eye2", "eye_left", "eye_right", "eye", "locator_eye_left", "locator_eye_right"),
|
||||
// cooldownMs = 1000L
|
||||
// )
|
||||
)
|
||||
|
||||
sealed class ParticleData {
|
||||
|
||||
+20
-1
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.detail
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.drop.DropTable
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
@@ -15,6 +16,10 @@ import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
|
||||
import com.cobblemon.mod.common.api.spawning.selection.SpawnSelectionData
|
||||
import com.cobblemon.mod.common.util.weightedSelection
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
|
||||
/**
|
||||
* A spawn detail that spawns a herd of Pokémon. This relies on the same [PokemonSpawnAction]s as
|
||||
@@ -53,6 +58,8 @@ class PokemonHerdSpawnDetail : SpawnDetail() {
|
||||
var isLeader: Boolean? = null
|
||||
var weight: Float = 1F
|
||||
var maxTimes = 10
|
||||
var isAlpha: Boolean? = null
|
||||
var heldItem: ResourceLocation? = null
|
||||
}
|
||||
|
||||
override fun isValid() = super.isValid() && herdablePokemon.all { it.pokemon.hasSpecies() && it.weight > 0F && it.maxTimes > 0 }
|
||||
@@ -109,13 +116,25 @@ class PokemonHerdSpawnDetail : SpawnDetail() {
|
||||
min..max
|
||||
} ?: level..level
|
||||
|
||||
herdable.pokemon.isAlpha = herdable.isAlpha
|
||||
|
||||
val heldItem = herdable.heldItem?.let { heldItemId ->
|
||||
val item = spawnablePosition.world.registryAccess().registryOrThrow(Registries.ITEM).get(heldItemId)
|
||||
if (item == Items.AIR) {
|
||||
LOGGER.error("Unable to find matching herd held item for ID: $heldItemId")
|
||||
null
|
||||
} else {
|
||||
ItemStack(item, 1)
|
||||
}
|
||||
}
|
||||
|
||||
return PokemonSpawnAction(
|
||||
spawnablePosition = spawnablePosition,
|
||||
bucket = bucket,
|
||||
detail = this,
|
||||
props = herdable.pokemon,
|
||||
drops = herdable.dropTable,
|
||||
heldItem = null,
|
||||
heldItem = heldItem,
|
||||
levelRange = levelRange
|
||||
).also {
|
||||
if (herdable.isLeader == true) {
|
||||
|
||||
+8
@@ -128,6 +128,14 @@ class FishingSpawnCause(
|
||||
|
||||
}
|
||||
|
||||
fun alterAlphaAttempt(pokemonEntity: PokemonEntity) {
|
||||
if (pokemonEntity.pokemon.isAlpha) {
|
||||
return
|
||||
}
|
||||
pokemonEntity.pokemon.isAlpha = true
|
||||
pokemonEntity.entityData.set(PokemonEntity.IS_ALPHA, true)
|
||||
}
|
||||
|
||||
fun alterFriendshipAttempt(pokemonEntity: PokemonEntity, effect: SpawnBait.Effect) {
|
||||
if (pokemonEntity.pokemon.friendship + effect.value > Cobblemon.config.maxPokemonFriendship)
|
||||
pokemonEntity.pokemon.setFriendship(Cobblemon.config.maxPokemonFriendship)
|
||||
|
||||
+22
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.spawning.influence
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnAction
|
||||
@@ -15,7 +16,9 @@ import com.cobblemon.mod.common.api.spawning.fishing.FishingSpawnCause
|
||||
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SaccharineLogBlockParticlesPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import kotlin.random.Random
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
@@ -51,6 +54,8 @@ class SaccharineLogSlatheredInfluence(val pos: BlockPos? = null) : SpawningInflu
|
||||
if (Math.random() <= HIDDEN_ABILITY_CHANCE) {
|
||||
FishingSpawnCause.alterHAAttempt(entity)
|
||||
}
|
||||
rollShiny(entity.pokemon)
|
||||
rollAlpha(entity.pokemon)
|
||||
|
||||
if (!activated) {
|
||||
val logPos = pos
|
||||
@@ -137,4 +142,21 @@ class SaccharineLogSlatheredInfluence(val pos: BlockPos? = null) : SpawningInflu
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun rollAlpha(pokemon: Pokemon) {
|
||||
val chance = Cobblemon.config.honeySlatherAlphaChance
|
||||
if (chance > 0 && Random.nextInt(chance) == 0) {
|
||||
pokemon.isAlpha = true
|
||||
}
|
||||
}
|
||||
|
||||
fun rollShiny(pokemon: Pokemon) {
|
||||
if (pokemon.shiny) {
|
||||
return
|
||||
}
|
||||
val chance = Cobblemon.config.honeySlatherShinyChance
|
||||
if (chance > 0 && Random.nextInt(chance) == 0) {
|
||||
pokemon.shiny = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -202,7 +202,7 @@ open class PlayerPartyStore(
|
||||
val shoulderEntity = if(isLeft) player.shoulderEntityLeft else player.shoulderEntityRight
|
||||
val pokemon = find { it.uuid == shoulderEntity.getCompound("Pokemon").getUUID(DataKeys.POKEMON_UUID) }
|
||||
// No longer valid if (in order): not in party, not the correct shoulder, no longer shoulder mountable
|
||||
if (pokemon == null || (pokemon.state as? ShoulderedState)?.isLeftShoulder != isLeft || !pokemon.form.shoulderMountable) {
|
||||
if (pokemon == null || (pokemon.state as? ShoulderedState)?.isLeftShoulder != isLeft || !pokemon.form.shoulderMountable || pokemon.isAlpha) {
|
||||
return false
|
||||
}
|
||||
player.updateShoulderNbt(pokemon)
|
||||
|
||||
@@ -282,9 +282,13 @@ object BattleBuilder {
|
||||
}
|
||||
playerActor.battleTheme = pokemonEntity.getBattleTheme()
|
||||
|
||||
val finalFormat = if (pokemonEntity.pokemon.isAlpha && BattleRules.WILD_ALPHA !in battleFormat.ruleSet) {
|
||||
BattleFormat.setBattleRules(battleFormat, battleFormat.ruleSet + BattleRules.WILD_ALPHA)
|
||||
} else battleFormat
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
BattleRegistry.startBattle(
|
||||
battleFormat = battleFormat,
|
||||
battleFormat = finalFormat,
|
||||
side1 = BattleSide(playerActor),
|
||||
side2 = BattleSide(wildActor)
|
||||
).ifSuccessful {
|
||||
|
||||
@@ -18,4 +18,5 @@ object BattleRules {
|
||||
const val CANCEL_MOD = "Cancel Mod"
|
||||
const val SLEEP_CLAUSE = "Sleep Clause"
|
||||
const val HP_PERCENTAGE_MOD = "HP Percentage Mod"
|
||||
const val WILD_ALPHA = "Wild Alpha"
|
||||
}
|
||||
+53
-11
@@ -8,16 +8,23 @@
|
||||
|
||||
package com.cobblemon.mod.common.battles.interpreter.instructions
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleContext
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.dispatch.ActionEffectInstruction
|
||||
import com.cobblemon.mod.common.battles.dispatch.GO
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.battles.dispatch.WaitDispatch
|
||||
import com.cobblemon.mod.common.battles.dispatch.UntilDispatch
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.chat.Component
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* Format: |-start|POKEMON|EFFECT
|
||||
@@ -26,25 +33,59 @@ import net.minecraft.network.chat.Component
|
||||
* @author Deltric
|
||||
* @since January 21st, 2022
|
||||
*/
|
||||
class StartInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
class StartInstruction(val message: BattleMessage): ActionEffectInstruction, InterpreterInstruction {
|
||||
override var future: CompletableFuture<*> = CompletableFuture.completedFuture(Unit)
|
||||
override var holds = mutableSetOf<String>()
|
||||
override val id = cobblemonResource("start")
|
||||
|
||||
override fun invoke(battle: PokemonBattle) {
|
||||
override fun preActionEffect(battle: PokemonBattle)
|
||||
{
|
||||
val pokemon = message.battlePokemon(0, battle) ?: return
|
||||
val effectID = message.effectAt(1)?.id ?: return
|
||||
|
||||
// skip adding contexts for every time the perish counter decrements
|
||||
if (!effectID.contains("perish")) {
|
||||
// don't need to add unique: showdown won't send -start instruction if volatile status is already present
|
||||
pokemon.contextManager.add(ShowdownInterpreter.getContextFromAction(message, BattleContext.Type.VOLATILE, battle))
|
||||
}
|
||||
|
||||
battle.dispatch{
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
GO
|
||||
}
|
||||
}
|
||||
|
||||
override fun runActionEffect(battle: PokemonBattle, runtime: MoLangRuntime) {
|
||||
battle.dispatch {
|
||||
val pokemon = message.battlePokemon(0, battle) ?: return@dispatch GO
|
||||
val effectID = message.effectAt(1)?.id ?: return@dispatch GO
|
||||
val actionEffect = ActionEffects.actionEffects[cobblemonResource("start_${effectID}")] ?: return@dispatch GO
|
||||
val providers = mutableListOf<Any>(battle)
|
||||
|
||||
pokemon.effectedPokemon.entity?.let { UsersProvider(it) }?.let(providers::add)
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
runtime = runtime,
|
||||
providers = providers,
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
this.future = actionEffect.run(context)
|
||||
holds = context.holds // Reference so future things can check on this action effect's holds
|
||||
future.thenApply { holds.clear() }
|
||||
return@dispatch GO
|
||||
}
|
||||
}
|
||||
|
||||
override fun postActionEffect(battle: PokemonBattle) {
|
||||
battle.dispatch {
|
||||
val pokemon = message.battlePokemon(0, battle) ?: return@dispatch GO
|
||||
val effectID = message.effectAt(1)?.id ?: return@dispatch GO
|
||||
val optionalEffect = message.effect()
|
||||
|
||||
val optionalPokemon = message.battlePokemonFromOptional(battle)
|
||||
val optionalPokemonName = optionalPokemon?.getName()
|
||||
val extraEffect = message.effectAt(2)?.typelessData ?: Component.literal("UNKOWN")
|
||||
|
||||
// skip adding contexts for every time the perish counter decrements
|
||||
if (!effectID.contains("perish")) {
|
||||
// don't need to add unique: showdown won't send -start instruction if volatile status is already present
|
||||
pokemon.contextManager.add(ShowdownInterpreter.getContextFromAction(message, BattleContext.Type.VOLATILE, battle))
|
||||
}
|
||||
battle.minorBattleActions[pokemon.uuid] = message
|
||||
|
||||
if (!message.hasOptionalArgument("silent")) {
|
||||
val lang = if (optionalEffect?.id == "reflecttype" && optionalPokemonName != null)
|
||||
battleLang("start.reflecttype", pokemon.getName(), optionalPokemonName)
|
||||
@@ -59,7 +100,8 @@ class StartInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
}
|
||||
battle.broadcastChatMessage(lang)
|
||||
}
|
||||
WaitDispatch(1F)
|
||||
//We check holds here so the chat msg + particle effect happen more concurrently, instead of sequentially
|
||||
UntilDispatch { "effects" !in holds}
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-4
@@ -38,6 +38,7 @@ import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import java.util.UUID
|
||||
import kotlin.math.ceil
|
||||
import kotlin.random.Random
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
@@ -124,7 +125,7 @@ class FossilMultiblockStructure (
|
||||
val ballType = (stack.item as PokeBallItem).pokeBall
|
||||
stack?.consume(1, player)
|
||||
|
||||
val pokemon = this.resultingFossil?.result?.create(player)
|
||||
val pokemon = this.resultingFossil?.result?.create(player)?.also(::rollShiny)?.also(::rollAlpha)
|
||||
|
||||
if(pokemon != null) {
|
||||
pokemon.caughtBall = ballType
|
||||
@@ -302,7 +303,7 @@ class FossilMultiblockStructure (
|
||||
override fun onTriggerEvent(state: BlockState?, world: ServerLevel?, pos: BlockPos?, random: RandomSource?) {
|
||||
// instantiate the pokemon as a new entity and spawn it at the location of the machine
|
||||
if(this.protectionTime <= 0) {
|
||||
val wildPokemon: Pokemon = if (hasCreatedPokemon) resultingFossil?.result?.create() ?: return else return
|
||||
val wildPokemon: Pokemon = if (hasCreatedPokemon) resultingFossil?.result?.create()?.also(::rollShiny)?.also(::rollAlpha) ?: return else return
|
||||
val direction = state?.getValue(HorizontalDirectionalBlock.FACING)?.opposite
|
||||
if(pos != null && direction != null && world != null) {
|
||||
val success = this.spawn(world, pos, direction, wildPokemon)
|
||||
@@ -327,7 +328,7 @@ class FossilMultiblockStructure (
|
||||
val tankTopEntity = world.getBlockEntity(tankBasePos.above()) as? MultiblockEntity
|
||||
val tankBaseBlockState = tankBaseEntity?.blockPos?.let { world.getBlockState(it) }
|
||||
val direction = if (tankBaseBlockState?.block == CobblemonBlocks.RESTORATION_TANK) tankBaseBlockState.getValue(HorizontalDirectionalBlock.FACING).opposite else Direction.UP
|
||||
val wildPokemon: Pokemon? = if (hasCreatedPokemon) resultingFossil?.result?.create() else null
|
||||
val wildPokemon: Pokemon? = if (hasCreatedPokemon) resultingFossil?.result?.create()?.also(::rollShiny)?.also(::rollAlpha) else null
|
||||
|
||||
monitorEntity?.multiblockStructure = null
|
||||
analyzerEntity?.multiblockStructure = null
|
||||
@@ -376,6 +377,24 @@ class FossilMultiblockStructure (
|
||||
}
|
||||
}
|
||||
|
||||
fun rollAlpha(pokemon: Pokemon) {
|
||||
val chance = Cobblemon.config.fossilMachineAlphaChance
|
||||
if (Random.nextInt(chance) == 0) {
|
||||
pokemon.isAlpha = true
|
||||
}
|
||||
}
|
||||
|
||||
fun rollShiny(pokemon: Pokemon) {
|
||||
if (pokemon.shiny) {
|
||||
return
|
||||
}
|
||||
|
||||
val chance = Cobblemon.config.fossilMachineShinyChance
|
||||
if (Random.nextInt(chance) == 0) {
|
||||
pokemon.shiny = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick(world: Level) {
|
||||
if (protectionTime > 0) protectionTime--
|
||||
if (protectionTime == 0) {
|
||||
@@ -672,4 +691,4 @@ class FossilMultiblockStructure (
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+41
-11
@@ -20,8 +20,6 @@ import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.aspect.aspectParticleMap
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
import com.cobblemon.mod.common.api.pokemon.aspect.ParticleData
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.scheduling.ScheduledTask
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnClient
|
||||
@@ -62,6 +60,8 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
const val BEAM_EXTEND_TIME = 0.2F
|
||||
const val POKEBALL_AIR_TIME = 0.5F
|
||||
const val SHINY_PARTICLE_COOLDOWN = 3.5F
|
||||
private const val ALPHA_EYE_PARTICLE_COOLDOWN_MS = 1000L
|
||||
private val ALPHA_MARK_ID = cobblemonResource("mark_alpha").toString()
|
||||
}
|
||||
|
||||
override val schedulingTracker: SchedulingTracker
|
||||
@@ -69,7 +69,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
|
||||
lateinit var currentEntity: PokemonEntity
|
||||
var phaseTarget: Entity? = null
|
||||
var entityScaleModifier = 1F
|
||||
var activeSendoutScale = 1F // The current scale used for the send-out animation
|
||||
|
||||
override fun getEntity() = currentEntity
|
||||
|
||||
@@ -89,6 +89,8 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
var sendOutOffset: Vec3? = null
|
||||
var playedSendOutSound: Boolean = false
|
||||
var playedThrowingSound: Boolean = false
|
||||
private var lastAlphaEyeParticle = 0L
|
||||
val eyeTrailPositions = mutableMapOf<String, ArrayDeque<Pair<Vec3, Long>>>() // List of eye locators that are tracking their position overtime for alpha eye trail rendering
|
||||
|
||||
val secondsSinceBeamEffectStarted: Float
|
||||
get() = (System.currentTimeMillis() - beamStartTime) / 1000F
|
||||
@@ -112,6 +114,8 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
// force a model update - handles edge case where the PosableState's tracked PosableModel isn't updated until the LivingEntityRenderer render is run
|
||||
currentModel = VaryingModelRepository.getPoser(identifier, this)
|
||||
currentEntity.refreshRiding()
|
||||
} else if (data == PokemonEntity.IS_ALPHA) {
|
||||
currentEntity.pokemon.isAlpha = currentEntity.entityData.get(PokemonEntity.IS_ALPHA)
|
||||
} else if (data == PokemonEntity.ASPECTS) {
|
||||
currentAspects = currentEntity.entityData.get(PokemonEntity.ASPECTS)
|
||||
currentEntity.pokemon.shiny = currentAspects.contains("shiny")
|
||||
@@ -130,7 +134,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
null
|
||||
} ?: return
|
||||
val primaryAnimation = PrimaryAnimation(animation)
|
||||
after(seconds = 3F) { entityScaleModifier = 0F }
|
||||
after(seconds = 3F) { activeSendoutScale = 0F }
|
||||
this.addPrimaryAnimation(primaryAnimation)
|
||||
}
|
||||
} else if (data == PokemonEntity.BEAM_MODE) {
|
||||
@@ -148,7 +152,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
// the duplicate particle effects.
|
||||
if (ballDone) {
|
||||
playedSendOutSound = false
|
||||
entityScaleModifier = 0F
|
||||
activeSendoutScale = 0F
|
||||
beamStartTime = System.currentTimeMillis()
|
||||
ballStartTime = System.currentTimeMillis()
|
||||
currentEntity.isInvisible = true
|
||||
@@ -259,7 +263,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
currentEntity.after(seconds = POKEBALL_AIR_TIME) {
|
||||
// Skip scaling task if the Pokémon is already being recalled
|
||||
if (scaleAnimTask == null || scaleAnimTask!!.expired) {
|
||||
scaleAnimTask = lerpOnClient(BEAM_SHRINK_TIME) { entityScaleModifier = it }
|
||||
scaleAnimTask = lerpOnClient(BEAM_SHRINK_TIME) { activeSendoutScale = it }
|
||||
currentEntity.isInvisible = false
|
||||
currentEntity.isSilent = false
|
||||
currentEntity.after(seconds = POKEBALL_AIR_TIME * 2) {
|
||||
@@ -276,7 +280,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
// Adding the ballDone check to here as well so that the send out sound doesn't play twice when putting pokemon into pasture block.
|
||||
if (ballDone) {
|
||||
playedSendOutSound = false
|
||||
entityScaleModifier = 0F
|
||||
activeSendoutScale = 0F
|
||||
currentEntity.isInvisible = false
|
||||
currentEntity.isSilent = false
|
||||
ballDone = false
|
||||
@@ -304,7 +308,7 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
)
|
||||
playedSendOutSound = true
|
||||
}
|
||||
scaleAnimTask = lerpOnClient(BEAM_SHRINK_TIME) { entityScaleModifier = it }
|
||||
scaleAnimTask = lerpOnClient(BEAM_SHRINK_TIME) { activeSendoutScale = it }
|
||||
currentEntity.after(seconds = BEAM_SHRINK_TIME * 2) {
|
||||
ballOffset = 0f
|
||||
ballRotOffset = 0f
|
||||
@@ -319,12 +323,12 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
ballRotOffset = 0f
|
||||
sendOutPosition = null
|
||||
afterOnClient(seconds = BEAM_EXTEND_TIME) {
|
||||
entityScaleModifier = 1F
|
||||
activeSendoutScale = 1F
|
||||
|
||||
// Cancel any ongoing scale animation tasks
|
||||
scaleAnimTask?.expire()
|
||||
scaleAnimTask = lerpOnClient(BEAM_SHRINK_TIME) {
|
||||
entityScaleModifier = (1 - it)
|
||||
activeSendoutScale = (1 - it)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,6 +482,32 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: use the aspect
|
||||
private fun spawnAlphaEyeParticles() {
|
||||
if (currentEntity.entityData.get(PokemonEntity.MARK) != ALPHA_MARK_ID) {
|
||||
return
|
||||
}
|
||||
|
||||
val now = System.currentTimeMillis()
|
||||
if (now - lastAlphaEyeParticle < ALPHA_EYE_PARTICLE_COOLDOWN_MS) {
|
||||
return
|
||||
}
|
||||
|
||||
val locatorCandidates = mutableListOf("eye1", "eye2", "eye_left", "eye_right", "eye")
|
||||
locatorCandidates.addAll(getMatchingLocators("eye"))
|
||||
locatorCandidates.addAll(listOf("locator_eye_left", "locator_eye_right"))
|
||||
val locators = locatorCandidates.distinct().filter { locatorStates[it] != null }
|
||||
if (locators.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
locators.forEach { locator ->
|
||||
runtime.resolve("q.particle('cobblemon:alpha_eyes', '$locator')".asExpressionLike())
|
||||
}
|
||||
lastAlphaEyeParticle = now
|
||||
}
|
||||
|
||||
fun cry() {
|
||||
val model = currentModel ?: return
|
||||
if (cryAnimation != null && (cryAnimation in activeAnimations || cryAnimation == primaryAnimation)) {
|
||||
@@ -525,4 +555,4 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
this.getEntity().z + offset.z
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokem
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.PokemonSizeCategory
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.isInventoryKeyPressed
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -602,6 +603,20 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
shadow = true
|
||||
)
|
||||
|
||||
val sizeCategory = selectedPokemon.getSizeCategory()
|
||||
val isAlpha = selectedPokemon.isAlpha
|
||||
|
||||
drawScaledText(
|
||||
x = x + 62,
|
||||
y = y + 32,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
context = context,
|
||||
text = (if (isAlpha) "cobblemon.ui.pokedex.scan.alpha".text() else PokemonSizeCategory.translationKey(sizeCategory).text()).bold(),
|
||||
scale = 1F,
|
||||
shadow = true,
|
||||
centered = true
|
||||
)
|
||||
|
||||
// Shiny Icon
|
||||
if (selectedPokemon.shiny) {
|
||||
blitk(
|
||||
@@ -751,4 +766,4 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
}
|
||||
super.onClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class ParticleStorm(
|
||||
val pokemon = pokeEntity?.pokemon
|
||||
//Use form data if available, species as fall back
|
||||
val baseScale = pokemon?.form?.baseScale ?: pokemon?.species?.baseScale ?: 1.0F
|
||||
val pokemonScale = pokemon?.scaleModifier ?: 1.0F
|
||||
val pokemonScale = pokemon?.effectiveScale ?: 1.0F
|
||||
val entityScale = pokeEntity?.scale ?: 1.0F
|
||||
DoubleValue(baseScale * pokemonScale * entityScale)
|
||||
}
|
||||
|
||||
+26
-2
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.PokemonSizeCategory
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
@@ -86,7 +87,7 @@ class PokedexScannerRenderer {
|
||||
var infoDisplayedCounter = 0
|
||||
usageContext.availableInfoFrames.forEachIndexed {index, isLeftSide ->
|
||||
if (isLeftSide !== null) {
|
||||
if (infoDisplayedCounter > 1 && !usageContext.isPokemonInFocusOwned) return@forEachIndexed
|
||||
if (infoDisplayedCounter > 2 && !usageContext.isPokemonInFocusOwned) return@forEachIndexed
|
||||
infoDisplayedCounter++
|
||||
// Frames
|
||||
val isInnerFrame = index == 1 || index == 2
|
||||
@@ -179,6 +180,29 @@ class PokedexScannerRenderer {
|
||||
}
|
||||
|
||||
if (infoDisplayedCounter == 3) {
|
||||
val pokemon = pokedexEntityData.pokemon
|
||||
val entityAlpha = (usageContext.scannableEntityInFocus?.resolveEntityScan() as? PokemonEntity)
|
||||
?.entityData
|
||||
?.get(PokemonEntity.IS_ALPHA)
|
||||
val isAlpha = entityAlpha ?: pokemon.isAlpha
|
||||
val sizeText = if (isAlpha) {
|
||||
lang("ui.pokedex.scan.alpha").bold()
|
||||
} else {
|
||||
val sizeCategoryText = PokemonSizeCategory.translationKey(pokemon.getSizeCategory()).text()
|
||||
lang("ui.pokedex.scan.size", sizeCategoryText).bold()
|
||||
}
|
||||
drawScaledText(
|
||||
context = graphics,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = sizeText,
|
||||
x = centerX + xOffset + xOffsetText,
|
||||
y = centerY + yOffset + yOffsetText,
|
||||
shadow = true,
|
||||
centered = true
|
||||
)
|
||||
}
|
||||
|
||||
if (infoDisplayedCounter == 4) {
|
||||
val typeText = lang("type.suffix", pokedexEntityData.getApparentForm().types.map { it.displayName.copy() }.reduce { acc, next -> acc.plus("/").plus(next) }).bold()
|
||||
val typeWidth = Minecraft.getInstance().font.width(typeText.font(CobblemonResources.DEFAULT_LARGE))
|
||||
// Split into 2 lines if text width is too long
|
||||
@@ -438,4 +462,4 @@ class PokedexScannerRenderer {
|
||||
renderScanOverlay(graphics, tickDelta)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -117,7 +117,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
model.context = context
|
||||
context.put(RenderContext.SPECIES, shoulderData.species.resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, shoulderData.aspects)
|
||||
val scale = shoulderData.form.baseScale * shoulderData.scaleModifier
|
||||
val scale = shoulderData.form.baseScale
|
||||
val width = shoulderData.form.hitbox.width
|
||||
val heightOffset = -1.5 * scale
|
||||
val widthOffset = width / 2 - 0.7
|
||||
@@ -222,7 +222,7 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
it.species,
|
||||
it.form,
|
||||
it.aspects,
|
||||
it.scaleModifier,
|
||||
it.effectiveScale,
|
||||
it.heldItem
|
||||
)
|
||||
}, { null })
|
||||
@@ -268,4 +268,4 @@ class PokemonOnShoulderRenderer<T : Player>(renderLayerParent: RenderLayerParent
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -33,6 +33,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.SimpleQuirk
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunction
|
||||
import com.cobblemon.mod.common.client.util.exists
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.generic.GenericBedrockEntity
|
||||
@@ -113,7 +114,7 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
open var properties = mutableMapOf<String, String>()
|
||||
|
||||
/*
|
||||
* Hello future Hiro, this is past Hiro. You've gotten forgetful in your old age.
|
||||
* Hello future Hiro, this is past Hiro. You've become forgetful in your old age.
|
||||
*
|
||||
* The profile translation is not actually necessary. The reason why you thought it was necessary
|
||||
* is that there is a 1.5 block offset applied by living-entity-renderer-intended models due to
|
||||
@@ -461,6 +462,7 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
}
|
||||
else {
|
||||
val texture = layer.texture?.invoke(currentState ?: FloatingState()) ?: continue
|
||||
if (!texture.exists()) continue
|
||||
renderLayer = getLayer(texture, layer.emissive, layer.translucent, layer.translucent_cull)
|
||||
}
|
||||
val consumer = provider.getBuffer(renderLayer)
|
||||
@@ -568,9 +570,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
// Is there any reason why we should actually change the pose?
|
||||
if (entity != null && (poseName == null || currentPose == null || !currentPose.isSuitable(state) || entityPoseType !in currentPose.poseTypes)) {
|
||||
val desirablePose = getFirstSuitablePose(state, entityPoseType)
|
||||
if (desirablePose == currentPose) {
|
||||
return currentPose
|
||||
}
|
||||
// If this if succeeds then it just no longer fits this pose
|
||||
if (currentPose != null) {
|
||||
// Don't apply pose correction until the current primary animation is complete.
|
||||
@@ -747,7 +746,7 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
var yRot = 0f
|
||||
// We could improve this to be generalized for other entities. First we'd have to figure out wtf is going on, though.
|
||||
if (entity is PokemonEntity) {
|
||||
scale = entity.pokemon.form.baseScale * entity.pokemon.scaleModifier * (entity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
scale = entity.pokemon.form.baseScale * entity.pokemon.effectiveScale * (entity.delegate as PokemonClientDelegate).activeSendoutScale
|
||||
// If scale is 0 we start getting NaNs
|
||||
scale.coerceAtLeast(0.01f)
|
||||
if (entity.passengers.isNotEmpty() && entity.controllingPassenger is OrientationControllable
|
||||
|
||||
+11
-3
@@ -18,23 +18,25 @@ import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.sound.instances.AlphaCrySoundInstance
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.genericRuntime
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import java.util.SortedMap
|
||||
import java.util.TreeMap
|
||||
import net.minecraft.CrashReport
|
||||
import net.minecraft.ReportedException
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.client.resources.sounds.EntityBoundSoundInstance
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.*
|
||||
|
||||
data class BedrockAnimationGroup(
|
||||
val formatVersion: String,
|
||||
@@ -110,7 +112,13 @@ class BedrockSoundKeyframe(
|
||||
if (soundEvent != null) {
|
||||
if (entity != null) {
|
||||
if (!entity.isSilent) {
|
||||
entity.level().playLocalSound(entity, soundEvent, entity.soundSource, 1F, 1F)
|
||||
// If this entity is an alpha then play their cry as such
|
||||
if (entity is PokemonEntity && entity.pokemon.isAlpha) {
|
||||
Minecraft.getInstance().soundManager.play(
|
||||
AlphaCrySoundInstance(soundEvent, entity.soundSource, 1.5f, 0.7f, entity, entity.level().random.nextLong()))
|
||||
} else {
|
||||
entity.level().playLocalSound(entity, soundEvent, entity.soundSource, 1F, 1F)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(soundEvent, 1F, 1F))
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Vector3f
|
||||
|
||||
/**
|
||||
*
|
||||
* Renders an alpha eye trail based on a list of previous eye locator positions
|
||||
*
|
||||
* @author Jackson
|
||||
* @since March 21st, 2026
|
||||
*/
|
||||
private const val TRAIL_MAX_WIDTH = 0.015f
|
||||
private const val TRAIL_MAX_ALPHA = 0.8f
|
||||
private val TRAIL_COLOR = Vector3f(0.7f, 0.0f, 0.0f)
|
||||
private const val TRAIL_DURATION_MS = 250 // lookback distance in ms for previous eye positions for trail rendering
|
||||
|
||||
private val EYE_LOCATOR_NAMES = setOf(
|
||||
"eye_left", "eye_right", "eye",
|
||||
"locator_eye_left", "locator_eye_right",
|
||||
"eye1", "eye2"
|
||||
)
|
||||
|
||||
/**
|
||||
* Updates the eye trail positions based on the current entity position and locator states
|
||||
*/
|
||||
fun updateEyeTrail(
|
||||
aspects: Set<String>,
|
||||
locatorStates: Map<String, MatrixWrapper>,
|
||||
entityPos: Vec3,
|
||||
trailPositions: MutableMap<String, ArrayDeque<Pair<Vec3, Long>>>
|
||||
) {
|
||||
if ("alpha_eyes" !in aspects) {
|
||||
trailPositions.clear()
|
||||
return
|
||||
}
|
||||
for (locatorName in EYE_LOCATOR_NAMES) {
|
||||
val wrapper = locatorStates[locatorName] ?: continue
|
||||
val pos = wrapper.matrix.getTranslation(Vector3f())
|
||||
val worldPos = Vec3(
|
||||
entityPos.x + pos.x,
|
||||
entityPos.y + pos.y,
|
||||
entityPos.z + pos.z
|
||||
)
|
||||
val now = System.currentTimeMillis()
|
||||
val deque = trailPositions.getOrPut(locatorName) { ArrayDeque() }
|
||||
deque.addLast(worldPos to now)
|
||||
while (deque.isNotEmpty() && now - deque.first().second > TRAIL_DURATION_MS) {
|
||||
deque.removeFirst()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun renderEyeTrail(
|
||||
positions: ArrayDeque<Pair<Vec3, Long>>,
|
||||
entityPos: Vec3,
|
||||
camPos: Vec3,
|
||||
poseStack: PoseStack,
|
||||
bufferSource: MultiBufferSource
|
||||
) {
|
||||
if (positions.size < 2) return
|
||||
|
||||
val consumer = bufferSource.getBuffer(RenderType.lightning())
|
||||
val matrix = poseStack.last().pose()
|
||||
val n = positions.size
|
||||
|
||||
for (i in 0 until n - 1) {
|
||||
val curr = positions[i].first
|
||||
val next = positions[i + 1].first
|
||||
|
||||
val tCurr = i.toFloat() / (n - 1)
|
||||
val tNext = (i + 1).toFloat() / (n - 1)
|
||||
|
||||
val wCurr = TRAIL_MAX_WIDTH * tCurr
|
||||
val wNext = TRAIL_MAX_WIDTH * tNext
|
||||
val aCurr = TRAIL_MAX_ALPHA * tCurr
|
||||
val aNext = TRAIL_MAX_ALPHA * tNext
|
||||
|
||||
val localCurr = curr.subtract(entityPos)
|
||||
val localNext = next.subtract(entityPos)
|
||||
|
||||
val dir = next.subtract(curr).normalize()
|
||||
val toCamera = camPos.subtract(curr).normalize()
|
||||
val perp = dir.cross(toCamera).normalize()
|
||||
|
||||
val px = perp.x.toFloat()
|
||||
val py = perp.y.toFloat()
|
||||
val pz = perp.z.toFloat()
|
||||
|
||||
val r = TRAIL_COLOR.x
|
||||
val g = TRAIL_COLOR.y
|
||||
val b = TRAIL_COLOR.z
|
||||
|
||||
consumer.addVertex(matrix,
|
||||
(localCurr.x - px * wCurr).toFloat(),
|
||||
(localCurr.y - py * wCurr).toFloat(),
|
||||
(localCurr.z - pz * wCurr).toFloat()
|
||||
).setColor(r, g, b, aCurr)
|
||||
|
||||
consumer.addVertex(matrix,
|
||||
(localCurr.x + px * wCurr).toFloat(),
|
||||
(localCurr.y + py * wCurr).toFloat(),
|
||||
(localCurr.z + pz * wCurr).toFloat()
|
||||
).setColor(r, g, b, aCurr)
|
||||
|
||||
consumer.addVertex(matrix,
|
||||
(localNext.x + px * wNext).toFloat(),
|
||||
(localNext.y + py * wNext).toFloat(),
|
||||
(localNext.z + pz * wNext).toFloat()
|
||||
).setColor(r, g, b, aNext)
|
||||
|
||||
consumer.addVertex(matrix,
|
||||
(localNext.x - px * wNext).toFloat(),
|
||||
(localNext.y - py * wNext).toFloat(),
|
||||
(localNext.z - pz * wNext).toFloat()
|
||||
).setColor(r, g, b, aNext)
|
||||
}
|
||||
}
|
||||
+25
-6
@@ -42,7 +42,6 @@ import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.math.DoubleRange
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.math.remap
|
||||
import com.google.common.primitives.Floats
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.ChatFormatting
|
||||
@@ -104,7 +103,7 @@ class PokemonRenderer(
|
||||
packedLight: Int
|
||||
) {
|
||||
val clientDelegate = entity.delegate as PokemonClientDelegate
|
||||
shadowRadius = (min((entity.boundingBox.maxX - entity.boundingBox.minX), (entity.boundingBox.maxZ) - (entity.boundingBox.minZ)).toFloat() / 1.5F * (entity.delegate as PokemonClientDelegate).entityScaleModifier)/entity.scale
|
||||
shadowRadius = (min((entity.boundingBox.maxX - entity.boundingBox.minX), (entity.boundingBox.maxZ) - (entity.boundingBox.minZ)).toFloat() / 1.5F * (entity.delegate as PokemonClientDelegate).activeSendoutScale)/entity.scale
|
||||
model.posableModel = VaryingModelRepository.getPoser(entity.pokemon.species.resourceIdentifier, clientDelegate)
|
||||
model.posableModel.context = model.context
|
||||
model.setupEntityTypeContext(entity)
|
||||
@@ -134,12 +133,12 @@ class PokemonRenderer(
|
||||
drawPlatform(
|
||||
poseMatrix,
|
||||
entity,
|
||||
(entity.delegate as PokemonClientDelegate).entityScaleModifier,
|
||||
(entity.delegate as PokemonClientDelegate).activeSendoutScale,
|
||||
buffer,
|
||||
packedLight,
|
||||
)
|
||||
// keeps the pokemon's root on the raft
|
||||
poseMatrix.translate(0.0, 0.25 * (entity.delegate as PokemonClientDelegate).entityScaleModifier, 0.0)
|
||||
poseMatrix.translate(0.0, 0.25 * (entity.delegate as PokemonClientDelegate).activeSendoutScale, 0.0)
|
||||
}
|
||||
|
||||
modelNow.setLayerContext(buffer, clientDelegate, VaryingModelRepository.getLayers(entity.pokemon.species.resourceIdentifier, clientDelegate))
|
||||
@@ -151,6 +150,26 @@ class PokemonRenderer(
|
||||
super.render(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
|
||||
}
|
||||
|
||||
// Call rendering for alpha eye trail
|
||||
updateEyeTrail(
|
||||
aspects = clientDelegate.currentAspects,
|
||||
locatorStates = clientDelegate.locatorStates,
|
||||
entityPos = entity.getPosition(partialTicks),
|
||||
trailPositions = clientDelegate.eyeTrailPositions
|
||||
)
|
||||
if (clientDelegate.eyeTrailPositions.isNotEmpty()) {
|
||||
val camPos = Minecraft.getInstance().gameRenderer.mainCamera.position
|
||||
for ((_, positions) in clientDelegate.eyeTrailPositions) {
|
||||
renderEyeTrail(
|
||||
positions = positions,
|
||||
entityPos = entity.getPosition(partialTicks),
|
||||
camPos = camPos,
|
||||
poseStack = poseMatrix,
|
||||
bufferSource = buffer
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
modelNow.green = 1F
|
||||
modelNow.blue = 1F
|
||||
modelNow.resetLayerContext()
|
||||
@@ -292,7 +311,7 @@ class PokemonRenderer(
|
||||
}
|
||||
|
||||
override fun scale(pEntity: PokemonEntity, pPoseStack: PoseStack, pPartialTickTime: Float) {
|
||||
val scale = pEntity.pokemon.form.baseScale * pEntity.pokemon.scaleModifier * (pEntity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
val scale = pEntity.pokemon.form.baseScale * pEntity.pokemon.effectiveScale * (pEntity.delegate as PokemonClientDelegate).activeSendoutScale
|
||||
pPoseStack.scale(scale, scale, scale)
|
||||
}
|
||||
|
||||
@@ -308,7 +327,7 @@ class PokemonRenderer(
|
||||
*/
|
||||
fun renderBeam(matrixStack: PoseStack, partialTicks: Float, entity: PokemonEntity, beamTarget: Entity, buffer: MultiBufferSource, offset: Vec3) {
|
||||
val clientDelegate = entity.delegate as PokemonClientDelegate
|
||||
val pokemonPosition = entity.position().add(0.0, entity.bbHeight / 2.0 * clientDelegate.entityScaleModifier.toDouble(), 0.0)
|
||||
val pokemonPosition = entity.position().add(0.0, entity.bbHeight / 2.0 * clientDelegate.activeSendoutScale.toDouble(), 0.0)
|
||||
var beamSourcePosition = if (beamTarget is EmptyPokeBallEntity) {
|
||||
(beamTarget.delegate as PokeBallPosableState).locatorStates["beam"]?.getOrigin() ?: beamTarget.position()
|
||||
} else {
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.sound.instances
|
||||
|
||||
import net.minecraft.client.resources.sounds.EntityBoundSoundInstance
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
/**
|
||||
* A class that acts as a "marker" for alpha cries. This is to avoid having to pass in entity info
|
||||
* to the [NeoforgeSoundEngineMixin] and [FabricSoundEngineMixin]. The play() mixin can just check for it
|
||||
* being an instance of [AlphaCrySoundInstance]
|
||||
*/
|
||||
class AlphaCrySoundInstance(
|
||||
sound: SoundEvent,
|
||||
source: SoundSource,
|
||||
volume: Float,
|
||||
pitch: Float,
|
||||
entity: Entity,
|
||||
seed: Long
|
||||
) : EntityBoundSoundInstance(sound, source, volume, pitch, entity, seed)
|
||||
@@ -20,7 +20,6 @@ import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.MobSpawnType
|
||||
|
||||
object SpawnAllPokemon {
|
||||
|
||||
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.util.alias
|
||||
import com.cobblemon.mod.common.util.commandLang
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.cobblemon.mod.common.util.toBlockPos
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType
|
||||
@@ -76,9 +75,7 @@ object SpawnPokemon {
|
||||
pokemonEntity.moveTo(pos.x, pos.y, pos.z, pokemonEntity.yRot, pokemonEntity.xRot)
|
||||
pokemonEntity.entityData.set(PokemonEntity.SPAWN_DIRECTION, pokemonEntity.random.nextFloat() * 360F)
|
||||
pokemonEntity.finalizeSpawn(world, world.getCurrentDifficultyAt(blockPos), MobSpawnType.COMMAND, null)
|
||||
if (world.addFreshEntity(pokemonEntity)) {
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
world.addFreshEntity(pokemonEntity)
|
||||
throw FAILED_SPAWN_EXCEPTION.create()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
||||
@@ -210,6 +210,18 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Spawning, lang = "shiny_rate", SERVER)
|
||||
var shinyRate = 8192F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "fossil_machine_alpha_chance", SERVER)
|
||||
var fossilMachineAlphaChance = 100
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "fossil_machine_shiny_chance", SERVER)
|
||||
var fossilMachineShinyChance = 500
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "honey_slather_alpha_chance", SERVER)
|
||||
var honeySlatherAlphaChance = 1000
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "honey_slather_shiny_chance", SERVER)
|
||||
var honeySlatherShinyChance = 8192
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "shiny_notice_particles_distance", CLIENT)
|
||||
var shinyNoticeParticlesDistance = 24F
|
||||
|
||||
@@ -219,6 +231,30 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "player_damage_pokemon", SERVER)
|
||||
var playerDamagePokemon = true
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "pokemon_intrinsic_size_min", SERVER)
|
||||
var pokemonIntrinsicSizeMin = 0.95F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "pokemon_intrinsic_size_max", SERVER)
|
||||
var pokemonIntrinsicSizeMax = 1.05F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_small_multiplier", SERVER)
|
||||
var alphaPokemonSizeSmallMultiplier = 1.70F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_medium_multiplier", SERVER)
|
||||
var alphaPokemonSizeMediumMultiplier = 1.55F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_large_multiplier", SERVER)
|
||||
var alphaPokemonSizeLargeMultiplier = 1.40F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_extra_large_multiplier", SERVER)
|
||||
var alphaPokemonSizeExtraLargeMultiplier = 1.25F
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "baby_pokemon_level_duration", SERVER)
|
||||
var babyPokemonLevelDuration = 9
|
||||
|
||||
@CobblemonConfigField(Category.Pokemon, lang = "baby_pokemon_size_multiplier", SERVER)
|
||||
var babyPokemonSizeMultiplier = 0.8F
|
||||
|
||||
@CobblemonConfigField(Category.World, lang = "apple_leftovers_chance", SERVER)
|
||||
var appleLeftoversChance = 0.025
|
||||
|
||||
@@ -360,4 +396,4 @@ class CobblemonConfig {
|
||||
}
|
||||
return newConfig
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(CobblemonMovesetBuilders, reloadable = false)
|
||||
this.register(Abilities, reloadable = false)
|
||||
this.register(CobblemonBehaviours, reloadable = false)
|
||||
this.register(Marks, reloadable = false)
|
||||
this.register(PokemonSpecies, reloadable = false)
|
||||
this.register(SpeciesAdditions, reloadable = false)
|
||||
this.register(PokeBalls, reloadable = false)
|
||||
@@ -107,7 +108,6 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(CobblemonCosmeticItems, reloadable = true)
|
||||
this.register(CobblemonCallbacks, reloadable = true)
|
||||
this.register(CobblemonUnlockableWallpapers, reloadable = true)
|
||||
this.register(Marks, reloadable = false)
|
||||
this.register(StarterDataLoader, reloadable = true)
|
||||
|
||||
CobblemonSpawnPools.load()
|
||||
|
||||
@@ -213,6 +213,7 @@ open class PokemonEntity(
|
||||
@JvmStatic var RIDE_BOOSTS = SynchedEntityData.defineId(PokemonEntity::class.java, RideBoostsDataSerializer)
|
||||
@JvmStatic var RIDE_STAMINA = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.FLOAT)
|
||||
@JvmStatic var SCALE_MODIFIER = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.FLOAT)
|
||||
@JvmStatic var IS_ALPHA = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.BOOLEAN)
|
||||
|
||||
const val BATTLE_LOCK = "battle"
|
||||
const val EVOLUTION_LOCK = "evolving"
|
||||
@@ -460,6 +461,7 @@ open class PokemonEntity(
|
||||
builder.define(RIDE_BOOSTS, emptyMap())
|
||||
builder.define(RIDE_STAMINA, 1F)
|
||||
builder.define(SCALE_MODIFIER, 1F)
|
||||
builder.define(IS_ALPHA, false)
|
||||
}
|
||||
|
||||
override fun onSyncedDataUpdated(data: EntityDataAccessor<*>) {
|
||||
@@ -1095,7 +1097,7 @@ open class PokemonEntity(
|
||||
override fun getBreedOffspring(serverLevel: ServerLevel, ageableMob: AgeableMob) = null
|
||||
|
||||
override fun canSitOnShoulder(): Boolean {
|
||||
return pokemon.form.shoulderMountable
|
||||
return pokemon.form.shoulderMountable && !pokemon.isAlpha
|
||||
}
|
||||
|
||||
override fun wantsToPickUp(stack: ItemStack): Boolean {
|
||||
@@ -1252,7 +1254,7 @@ open class PokemonEntity(
|
||||
}
|
||||
|
||||
override fun getDimensions(pose: Pose): EntityDimensions {
|
||||
val scale = effects.mockEffect?.scale ?: (form.baseScale * pokemon.scaleModifier)
|
||||
val scale = effects.mockEffect?.scale ?: (form.baseScale * pokemon.effectiveScale)
|
||||
var result = this.exposedForm.hitbox.scale(scale)
|
||||
result = result.withEyeHeight(this.exposedForm.eyeHeight(this) * result.height)
|
||||
result = result.scale(this.scale)
|
||||
@@ -1531,7 +1533,7 @@ open class PokemonEntity(
|
||||
}
|
||||
|
||||
fun tryMountingShoulder(player: ServerPlayer): Boolean {
|
||||
if (this.pokemon.belongsTo(player) && this.hasRoomToMount(player)) {
|
||||
if (this.pokemon.belongsTo(player) && this.hasRoomToMount(player) && this.canSitOnShoulder()) {
|
||||
CobblemonEvents.SHOULDER_MOUNT.postThen(
|
||||
ShoulderMountEvent(
|
||||
player,
|
||||
@@ -1589,7 +1591,7 @@ open class PokemonEntity(
|
||||
nbt.putString(DataKeys.SHOULDER_SPECIES, this.pokemon.species.resourceIdentifier.toString())
|
||||
nbt.putString(DataKeys.SHOULDER_FORM, this.pokemon.form.name)
|
||||
nbt.put(DataKeys.SHOULDER_ASPECTS, this.pokemon.aspects.map(StringTag::valueOf).toNbtList())
|
||||
nbt.putFloat(DataKeys.SHOULDER_SCALE_MODIFIER, this.pokemon.scaleModifier)
|
||||
nbt.putFloat(DataKeys.SHOULDER_SCALE_MODIFIER, this.pokemon.effectiveScale)
|
||||
nbt.put(
|
||||
DataKeys.SHOULDER_ITEM,
|
||||
this.level().registryAccess()
|
||||
@@ -2615,11 +2617,15 @@ open class PokemonEntity(
|
||||
* represents a kind of 'responsibility' that the leader feels towards their followers - they believe in this
|
||||
* leader with some amount of fervor, and this gets used to ensure that the leader doesn't choose to follow a
|
||||
* different Pokémon that is of an equal or lower tier than this Pokémon is to its followers.
|
||||
* - Alpha Pokémon automatically have the maximum possible tier.
|
||||
*/
|
||||
fun getHerdTier(): Int {
|
||||
val world = level() as? ServerLevel ?: return 0
|
||||
val herdLeader = this.brain.getMemorySafely(CobblemonMemories.HERD_LEADER).orElse(null)?.let(UUID::fromString)?.let(world::getEntity) as? PokemonEntity
|
||||
return if (herdLeader == null) {
|
||||
if (pokemon.isAlpha) {
|
||||
return Int.MAX_VALUE
|
||||
}
|
||||
if (!brain.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES)) {
|
||||
return 0
|
||||
}
|
||||
@@ -2631,7 +2637,10 @@ open class PokemonEntity(
|
||||
it.behaviour.herd.bestMatchLeader(follower = it, possibleLeader = this)?.tier ?: 0
|
||||
} ?: 0
|
||||
} else {
|
||||
if (herdLeader.pokemon.isAlpha) {
|
||||
return Int.MAX_VALUE
|
||||
}
|
||||
herdLeader.behaviour.herd.bestMatchLeader(follower = this, possibleLeader = herdLeader)?.tier ?: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -230,18 +230,17 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
fun updateTrackedValues() {
|
||||
val trackedSpecies = mock?.species ?: entity.pokemon.species.resourceIdentifier.toString()
|
||||
val trackedNickname = mock?.nickname ?: entity.pokemon.nickname ?: Component.empty()
|
||||
val trackedMark = entity.pokemon.activeMark?.identifier.toString()
|
||||
val trackedAspects = mock?.aspects ?: entity.pokemon.aspects
|
||||
val trackedBall = mock?.pokeball ?: entity.pokemon.caughtBall.name.toString()
|
||||
val trackedScaleModifier = mock?.scaleModifier ?: entity.pokemon.scaleModifier
|
||||
val trackedScaleModifier = mock?.scaleModifier ?: entity.pokemon.effectiveScale
|
||||
|
||||
entity.ownerUUID = entity.pokemon.getOwnerUUID()
|
||||
entity.entityData.set(PokemonEntity.SPECIES, trackedSpecies)
|
||||
if (entity.entityData.get(PokemonEntity.NICKNAME) != trackedNickname) {
|
||||
entity.entityData.set(PokemonEntity.NICKNAME, trackedNickname)
|
||||
}
|
||||
if (entity.entityData.get(PokemonEntity.MARK) !=trackedMark) {
|
||||
entity.entityData.set(PokemonEntity.MARK, trackedMark)
|
||||
if (entity.entityData.get(PokemonEntity.IS_ALPHA) != entity.pokemon.isAlpha) {
|
||||
entity.entityData.set(PokemonEntity.IS_ALPHA, entity.pokemon.isAlpha)
|
||||
}
|
||||
entity.entityData.set(PokemonEntity.ASPECTS, trackedAspects)
|
||||
entity.entityData.set(PokemonEntity.LABEL_LEVEL, entity.pokemon.level)
|
||||
@@ -266,6 +265,11 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
entity.entityData.set(PokemonEntity.RIDE_BOOSTS, newRideBoosts)
|
||||
}
|
||||
|
||||
val trackedMark = entity.pokemon.activeMark?.identifier.toString()
|
||||
if (entity.entityData.get(PokemonEntity.MARK) != trackedMark) {
|
||||
entity.entityData.set(PokemonEntity.MARK, trackedMark)
|
||||
}
|
||||
|
||||
updateShownItem()
|
||||
updatePoseType()
|
||||
}
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.entity.pokemon.ai.sensors
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getMemorySafely
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.sensing.Sensor
|
||||
|
||||
class AlphaLevelMatchingSensor : Sensor<PokemonEntity>(20) {
|
||||
private var lastMatchingPlayerId: UUID? = null
|
||||
|
||||
override fun requires() = setOf(MemoryModuleType.NEAREST_PLAYERS)
|
||||
|
||||
override fun doTick(world: ServerLevel, entity: PokemonEntity) {
|
||||
if (!entity.pokemon.isAlpha || !entity.pokemon.isWild() || entity.isBattling) {
|
||||
lastMatchingPlayerId = null
|
||||
return
|
||||
}
|
||||
|
||||
val nearestPlayer = entity.brain.getMemorySafely(MemoryModuleType.NEAREST_PLAYERS)
|
||||
.orElse(emptyList())
|
||||
.filterIsInstance<ServerPlayer>()
|
||||
.minByOrNull { it.distanceToSqr(entity) }
|
||||
|
||||
if (nearestPlayer == null || nearestPlayer.distanceToSqr(entity) > RADIUS_SQR) {
|
||||
lastMatchingPlayerId = null
|
||||
return
|
||||
}
|
||||
|
||||
if (lastMatchingPlayerId != nearestPlayer.uuid) {
|
||||
lastMatchingPlayerId = nearestPlayer.uuid
|
||||
entity.cry()
|
||||
|
||||
// test particles to make sure the level matching is working
|
||||
SpawnSnowstormEntityParticlePacket(cobblemonResource("shiny_ring"), entity.id, listOf("shiny_particles", "middle"))
|
||||
.sendToPlayersAround(entity.x, entity.y, entity.z, 64.0, world.dimension())
|
||||
}
|
||||
|
||||
val strongestPartyLevel = nearestPlayer.party().maxOfOrNull { it.level } ?: return
|
||||
val targetLevel = when {
|
||||
strongestPartyLevel < 20 -> strongestPartyLevel + 5
|
||||
strongestPartyLevel in 31..40 -> strongestPartyLevel + 10
|
||||
strongestPartyLevel in 51..65 -> strongestPartyLevel + 15
|
||||
strongestPartyLevel >= 66 -> strongestPartyLevel + 20
|
||||
else -> strongestPartyLevel
|
||||
}.coerceAtMost(100)
|
||||
|
||||
if (entity.pokemon.level != targetLevel) {
|
||||
entity.pokemon.level = targetLevel
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val RADIUS_SQR = 32.0 * 32.0
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -39,7 +39,7 @@ class IllusionEffect(
|
||||
|
||||
constructor(disguise: Pokemon) : this(
|
||||
mock = disguise.createPokemonProperties(PokemonPropertyExtractor.ILLUSION),
|
||||
scale = disguise.form.baseScale * disguise.scaleModifier
|
||||
scale = disguise.form.baseScale * disguise.effectiveScale
|
||||
)
|
||||
|
||||
override fun apply(entity: PokemonEntity, future: CompletableFuture<PokemonEntity>) {
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class TransformEffect(
|
||||
|
||||
constructor(mimic: Pokemon, doCry: Boolean = true) : this(
|
||||
mock = mimic.createPokemonProperties(PokemonPropertyExtractor.TRANSFORM),
|
||||
scale = mimic.form.baseScale * mimic.scaleModifier,
|
||||
scale = mimic.form.baseScale * mimic.effectiveScale,
|
||||
doCry = doCry
|
||||
)
|
||||
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.net.messages.client.pokemon.update
|
||||
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
/**
|
||||
* Update packet for the alpha (as in the big scary pack leader) status of a Pokémon.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 1st, 2025
|
||||
*/
|
||||
class AlphaUpdatePacket(pokemon: () -> Pokemon?, value: Boolean): SingleUpdatePacket<Boolean, AlphaUpdatePacket>(pokemon, value) {
|
||||
override val id = ID
|
||||
override fun encodeValue(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeBoolean(this.value)
|
||||
}
|
||||
|
||||
override fun set(pokemon: Pokemon, value: Boolean) {
|
||||
pokemon.isAlpha = value
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("alpha_update")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): CaughtBallUpdatePacket {
|
||||
val pokemon = decodePokemon(buffer)
|
||||
val pokeBall = PokeBalls.getPokeBall(buffer.readIdentifier()) ?: PokeBalls.POKE_BALL
|
||||
return CaughtBallUpdatePacket(pokemon, pokeBall)
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.net.messages.client.pokemon.update
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
/**
|
||||
* Update packet for a Pokémon's scale modifier.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since December 1st, 2025
|
||||
*/
|
||||
class ScaleModifierUpdatePacket(pokemon: () -> Pokemon?, value: Float): SingleUpdatePacket<Float, ScaleModifierUpdatePacket>(pokemon, value) {
|
||||
override val id = ID
|
||||
override fun encodeValue(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeFloat(this.value)
|
||||
}
|
||||
|
||||
override fun set(pokemon: Pokemon, value: Float) {
|
||||
pokemon.scaleModifier = value
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("scale_modifier_update")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): ScaleModifierUpdatePacket {
|
||||
val pokemon = decodePokemon(buffer)
|
||||
val scaleModifier = buffer.readFloat()
|
||||
return ScaleModifierUpdatePacket(pokemon, scaleModifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -62,6 +62,7 @@ class SpawnPokemonPacket(
|
||||
var tickSpawned: Int,
|
||||
var rideBoosts: Map<RidingStat, Float>,
|
||||
var rideStamina: Float,
|
||||
var isAlpha: Boolean,
|
||||
var silent: Boolean,
|
||||
vanillaSpawnPacket: ClientboundAddEntityPacket,
|
||||
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
|
||||
@@ -95,6 +96,7 @@ class SpawnPokemonPacket(
|
||||
entity.tickCount,
|
||||
entity.entityData.get(PokemonEntity.RIDE_BOOSTS),
|
||||
entity.entityData.get(PokemonEntity.RIDE_STAMINA),
|
||||
entity.entityData.get(PokemonEntity.IS_ALPHA),
|
||||
entity.isSilent,
|
||||
vanillaSpawnPacket
|
||||
)
|
||||
@@ -130,6 +132,7 @@ class SpawnPokemonPacket(
|
||||
{ _, value -> buffer.writeFloat(value) }
|
||||
)
|
||||
buffer.writeFloat(rideStamina)
|
||||
buffer.writeBoolean(isAlpha)
|
||||
buffer.writeBoolean(silent)
|
||||
}
|
||||
|
||||
@@ -176,6 +179,7 @@ class SpawnPokemonPacket(
|
||||
entity.entityData.set(PokemonEntity.RIDE_BOOSTS, rideBoosts)
|
||||
entity.entityData.set(PokemonEntity.RIDE_STAMINA, rideStamina)
|
||||
entity.entityData.set(PokemonEntity.SCALE_MODIFIER, scaleModifier)
|
||||
entity.entityData.set(PokemonEntity.IS_ALPHA, isAlpha)
|
||||
entity.isSilent = silent
|
||||
|
||||
entity.tickSpawned = this.tickSpawned
|
||||
@@ -216,6 +220,7 @@ class SpawnPokemonPacket(
|
||||
{ buffer.readFloat() }
|
||||
)
|
||||
val rideStamina = buffer.readFloat()
|
||||
val isAlpha = buffer.readBoolean()
|
||||
val silent = buffer.readBoolean()
|
||||
val vanillaPacket = decodeVanillaPacket(buffer)
|
||||
|
||||
@@ -246,6 +251,7 @@ class SpawnPokemonPacket(
|
||||
tickSpawned,
|
||||
rideBoosts,
|
||||
rideStamina,
|
||||
isAlpha,
|
||||
silent,
|
||||
vanillaPacket
|
||||
)
|
||||
|
||||
+2
-2
@@ -164,7 +164,7 @@ class PokedexUsageContext {
|
||||
// Randomize info frames for render
|
||||
if (focusIntervals == 0F) {
|
||||
availableInfoFrames = mutableListOf(null, null, null, null)
|
||||
for (i in 0..2) {
|
||||
for (i in 0..3) {
|
||||
var randomIndex = Random.nextInt(availableInfoFrames.size)
|
||||
if (availableInfoFrames[randomIndex] !== null) randomIndex = availableInfoFrames.indexOfFirst { it == null }
|
||||
availableInfoFrames.set(randomIndex, Random.nextBoolean())
|
||||
@@ -240,4 +240,4 @@ class PokedexUsageContext {
|
||||
fun playSound(soundEvent: SoundEvent) {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(soundEvent, 1.0F))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ import com.cobblemon.mod.common.util.codec.internal.ClientPokemonP3
|
||||
import com.cobblemon.mod.common.util.codec.internal.PokemonP1
|
||||
import com.cobblemon.mod.common.util.codec.internal.PokemonP2
|
||||
import com.cobblemon.mod.common.util.codec.internal.PokemonP3
|
||||
import com.cobblemon.mod.common.util.nextBetween
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.util.setPositionSafely
|
||||
@@ -243,6 +244,21 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
var characteristic: Characteristic = Characteristic.calculate(ivs, uuid)
|
||||
private set
|
||||
|
||||
var isAlpha: Boolean = false
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
field = value
|
||||
val alphaMark = Marks.getByIdentifier(cobblemonResource("mark_alpha"))!!
|
||||
|
||||
if (value) { activeMark = alphaMark }
|
||||
else { scaleModifier = 1F }
|
||||
|
||||
exchangeMark(alphaMark, value)
|
||||
updateAspects()
|
||||
onChange(AlphaUpdatePacket({ this }, value))
|
||||
}
|
||||
}
|
||||
|
||||
fun setIV(stat : Stat, value : Int) {
|
||||
val quotient = clamp(currentHealth / maxHealth.toFloat(), 0F, 1F)
|
||||
ivs[stat] = value
|
||||
@@ -251,6 +267,31 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
}
|
||||
}
|
||||
|
||||
fun initializeScale() {
|
||||
if (isAlpha) {
|
||||
scaleModifier = 1F
|
||||
return
|
||||
}
|
||||
val config = Cobblemon.config
|
||||
setIntrinsicScale(Random.nextBetween(config.pokemonIntrinsicSizeMin, config.pokemonIntrinsicSizeMax))
|
||||
}
|
||||
|
||||
fun assignSizeMarks() {
|
||||
// this is where we should assign a mark based on min or max intrinsic scale
|
||||
val miniMark = Marks.getByIdentifier(cobblemonResource("mark_mini"))!!
|
||||
val jumboMark = Marks.getByIdentifier(cobblemonResource("mark_jumbo"))!!
|
||||
val config = Cobblemon.config
|
||||
|
||||
if (scaleModifier == config.pokemonIntrinsicSizeMin) { // minimum size
|
||||
exchangeMark(miniMark, true)
|
||||
activeMark = miniMark
|
||||
}
|
||||
if (scaleModifier == config.pokemonIntrinsicSizeMax) { // maximum size
|
||||
exchangeMark(jumboMark, true)
|
||||
activeMark = jumboMark
|
||||
}
|
||||
}
|
||||
|
||||
fun hyperTrainIV(stat: Stat, value: Int) {
|
||||
val quotient = clamp(currentHealth / maxHealth.toFloat(), 0F, 1F)
|
||||
CobblemonEvents.HYPER_TRAINED_IV_PRE.postThen(
|
||||
@@ -555,7 +596,46 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
val speed: Int
|
||||
get() = getStat(Stats.SPEED)
|
||||
|
||||
var scaleModifier = 1F
|
||||
var scaleModifier: Float = 1F
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
field = value
|
||||
onChange(ScaleModifierUpdatePacket({ this }, value))
|
||||
}
|
||||
}
|
||||
|
||||
val effectiveScale: Float
|
||||
get() {
|
||||
val babyPokemonMultiplier = if (level <= 1) {
|
||||
Cobblemon.config.babyPokemonSizeMultiplier
|
||||
} else if (Cobblemon.config.babyPokemonLevelDuration <= 1 || level >= Cobblemon.config.babyPokemonLevelDuration) {
|
||||
1F
|
||||
} else {
|
||||
val minMultiplier = Cobblemon.config.babyPokemonSizeMultiplier
|
||||
val maxLevel = Cobblemon.config.babyPokemonLevelDuration
|
||||
val t = (level - 1).toFloat() / (maxLevel - 1).toFloat()
|
||||
minMultiplier + (1F - minMultiplier) * t
|
||||
}
|
||||
return babyPokemonMultiplier * if (this.isAlpha) getAlphaScaleMultiplier() else scaleModifier
|
||||
}
|
||||
|
||||
private fun getAlphaScaleMultiplier(): Float {
|
||||
val config = Cobblemon.config
|
||||
val hitbox = form.hitbox
|
||||
val baseHitboxSize = max(hitbox.width, hitbox.height) * form.baseScale
|
||||
return when {
|
||||
baseHitboxSize < 0.5F -> config.alphaPokemonSizeSmallMultiplier
|
||||
baseHitboxSize < 1.5F -> config.alphaPokemonSizeMediumMultiplier
|
||||
baseHitboxSize < 10F -> config.alphaPokemonSizeLargeMultiplier
|
||||
else -> config.alphaPokemonSizeExtraLargeMultiplier
|
||||
}
|
||||
}
|
||||
|
||||
private fun setIntrinsicScale(value: Float) {
|
||||
val deltaPercent = (value - 1F) * 100F
|
||||
val roundedPercent = (deltaPercent * 10F).roundToInt() / 10F
|
||||
scaleModifier = 1F + (roundedPercent / 100F)
|
||||
}
|
||||
|
||||
var caughtBall: PokeBall = PokeBalls.POKE_BALL
|
||||
set(value) {
|
||||
@@ -575,6 +655,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
var activeMark: Mark? = null
|
||||
set(value) {
|
||||
field = value
|
||||
updateAspects()
|
||||
onChange(ActiveMarkUpdatePacket({ this }, value))
|
||||
}
|
||||
|
||||
@@ -2022,6 +2103,10 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
return createPokemonProperties(*extractors.toTypedArray())
|
||||
}
|
||||
|
||||
fun getSizeCategory(): PokemonSizeCategory {
|
||||
return PokemonSizeCategory.fromScale(scaleModifier)
|
||||
}
|
||||
|
||||
fun addExperience(source: ExperienceSource, xp: Int): AddExperienceResult {
|
||||
if (xp < 0 || !this.canLevelUpFurther()) {
|
||||
return AddExperienceResult(level, level, emptySet(), 0) // no negatives!
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
|
||||
enum class PokemonSizeCategory {
|
||||
XS,
|
||||
S,
|
||||
M,
|
||||
L,
|
||||
XL;
|
||||
|
||||
companion object {
|
||||
// Find which size category corresponds to the given scale modifier.
|
||||
// The scale modifier should be between the intrinsic min and max size.
|
||||
fun fromScale(scaleModifier: Float): PokemonSizeCategory {
|
||||
val config = Cobblemon.config
|
||||
val minScale = config.pokemonIntrinsicSizeMin
|
||||
val maxScale = config.pokemonIntrinsicSizeMax
|
||||
val range = (maxScale - minScale).coerceAtLeast(0.0001F)
|
||||
val segmentSize = range / PokemonSizeCategory.entries.size
|
||||
val adjustedScale = (scaleModifier - minScale).coerceIn(0F, range)
|
||||
val index = (adjustedScale / segmentSize).toInt().coerceIn(0, PokemonSizeCategory.entries.size - 1)
|
||||
return PokemonSizeCategory.entries[index]
|
||||
}
|
||||
|
||||
fun translationKey(category: PokemonSizeCategory) = "cobblemon.ui.size_category.${category.name.lowercase()}"
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.pokemon.ai
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
class HerdBehaviour {
|
||||
@@ -39,6 +40,9 @@ class HerdBehaviour {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestLeader != null && possibleLeader.pokemon.isAlpha) {
|
||||
return ToleratedHerdLeader(PokemonProperties(), 9001, ignoresLevel = true) // WHAT?? OVER 9000???
|
||||
}
|
||||
return bestLeader
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ object PokemonBrain {
|
||||
SensorType.NEAREST_LIVING_ENTITIES,
|
||||
SensorType.HURT_BY,
|
||||
SensorType.NEAREST_PLAYERS,
|
||||
CobblemonSensors.ALPHA_LEVEL_MATCHING,
|
||||
CobblemonSensors.POKEMON_DISTURBANCE,
|
||||
CobblemonSensors.POKEMON_DEFEND_OWNER,
|
||||
CobblemonSensors.POKEMON_DROWSY,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.aspects
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonCosmeticItems
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
@@ -53,6 +54,37 @@ val COSMETIC_SLOT_ASPECT = object : AspectProvider {
|
||||
override fun provide(properties: PokemonProperties) = emptySet<String>()
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the aspect(s) of the active mark, if any.
|
||||
*/
|
||||
val MARK_ASPECT = object : AspectProvider {
|
||||
override fun provide(pokemon: Pokemon): Set<String> {
|
||||
return pokemon.activeMark?.aspects?.toSet() ?: emptySet()
|
||||
}
|
||||
|
||||
override fun provide(properties: PokemonProperties): Set<String> = emptySet()
|
||||
}
|
||||
|
||||
val ALPHA_ASPECT = object : AspectProvider {
|
||||
val ASPECT = "alpha"
|
||||
|
||||
override fun provide(pokemon: Pokemon): Set<String> {
|
||||
return if (pokemon.isAlpha) {
|
||||
setOf(ASPECT)
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
override fun provide(properties: PokemonProperties): Set<String> {
|
||||
return if (properties.isAlpha == true) {
|
||||
setOf(ASPECT)
|
||||
} else {
|
||||
emptySet()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val CHARACTERISTIC_RAINBOW_ASPECT = object : AspectProvider {
|
||||
fun calculateColourAspect(nature: Nature, characteristic: Characteristic): String? {
|
||||
return when (nature.increasedStat to characteristic.relevantStat) {
|
||||
|
||||
@@ -20,6 +20,7 @@ object DataKeys {
|
||||
const val POKEMON_FRIENDSHIP = "Friendship"
|
||||
const val POKEMON_FULLNESS = "Fullness"
|
||||
const val POKEMON_INTERACTION_COOLDOWN = "InteractionCooldown"
|
||||
const val POKEMON_ALPHA = "Alpha"
|
||||
|
||||
const val POKEMON_IVS = "IVs"
|
||||
const val POKEMON_IVS_BASE = "Base"
|
||||
|
||||
@@ -488,6 +488,6 @@ fun ServerPlayer.updateShoulderNbt(pokemon: Pokemon) {
|
||||
nbt.putString(DataKeys.SHOULDER_SPECIES, pokemon.species.resourceIdentifier.toString())
|
||||
nbt.putString(DataKeys.SHOULDER_FORM, pokemon.form.name)
|
||||
nbt.put(DataKeys.SHOULDER_ASPECTS, pokemon.aspects.map(StringTag::valueOf).toNbtList())
|
||||
nbt.putFloat(DataKeys.SHOULDER_SCALE_MODIFIER, pokemon.scaleModifier)
|
||||
nbt.putFloat(DataKeys.SHOULDER_SCALE_MODIFIER, pokemon.effectiveScale)
|
||||
if ((pokemon.state as ShoulderedState).isLeftShoulder) shoulderEntityLeft = nbt else shoulderEntityRight = nbt
|
||||
}
|
||||
@@ -35,6 +35,7 @@ internal data class ClientPokemonP3(
|
||||
val rideBoosts: Map<String, Float>,
|
||||
val currentFullness: Int,
|
||||
val interactionCooldowns: Map<ResourceLocation, Int>,
|
||||
val isAlpha: Boolean,
|
||||
) : Partial<Pokemon> {
|
||||
|
||||
override fun into(other: Pokemon): Pokemon {
|
||||
@@ -53,6 +54,7 @@ internal data class ClientPokemonP3(
|
||||
this.rideBoosts.let { other.setRideBoosts(it.mapKeys { RidingStat.valueOf(it.key) }) }
|
||||
other.currentFullness = this.currentFullness
|
||||
other.interactionCooldowns = this.interactionCooldowns.toMutableMap()
|
||||
other.isAlpha = isAlpha
|
||||
return other
|
||||
}
|
||||
|
||||
@@ -75,6 +77,7 @@ internal data class ClientPokemonP3(
|
||||
Codec.unboundedMap(Codec.STRING, Codec.FLOAT).fieldOf(DataKeys.POKEMON_RIDE_BOOSTS).forGetter(ClientPokemonP3::rideBoosts),
|
||||
Codec.intRange(0, 100).fieldOf(DataKeys.POKEMON_FULLNESS).forGetter(ClientPokemonP3::currentFullness),
|
||||
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT).fieldOf(DataKeys.POKEMON_INTERACTION_COOLDOWN).forGetter(ClientPokemonP3::interactionCooldowns),
|
||||
Codec.BOOL.optionalFieldOf(DataKeys.POKEMON_ALPHA, false).forGetter(ClientPokemonP3::isAlpha)
|
||||
).apply(instance, ::ClientPokemonP3)
|
||||
}
|
||||
|
||||
@@ -92,6 +95,7 @@ internal data class ClientPokemonP3(
|
||||
pokemon.getRideBoosts().mapKeys { it.key.name },
|
||||
pokemon.currentFullness,
|
||||
pokemon.interactionCooldowns,
|
||||
pokemon.isAlpha,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ internal data class PokemonP3(
|
||||
val rideStamina: Float,
|
||||
val currentFullness: Int,
|
||||
val interactionCooldowns: Map<ResourceLocation, Int>,
|
||||
val isAlpha: Boolean
|
||||
) : Partial<Pokemon> {
|
||||
|
||||
override fun into(other: Pokemon): Pokemon {
|
||||
@@ -79,6 +80,7 @@ internal data class PokemonP3(
|
||||
other.rideStamina = this.rideStamina
|
||||
other.currentFullness = this.currentFullness
|
||||
other.interactionCooldowns = this.interactionCooldowns.toMutableMap()
|
||||
other.isAlpha = isAlpha
|
||||
other.recalculateCharacteristic()
|
||||
other.updateAspects()
|
||||
return other
|
||||
@@ -102,6 +104,7 @@ internal data class PokemonP3(
|
||||
Codec.FLOAT.optionalFieldOf(DataKeys.POKEMON_RIDE_STAMINA, 1F).forGetter(PokemonP3::rideStamina),
|
||||
Codec.intRange(0, 100).optionalFieldOf(DataKeys.POKEMON_FULLNESS, 0).forGetter(PokemonP3::currentFullness),
|
||||
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT).optionalFieldOf(DataKeys.POKEMON_INTERACTION_COOLDOWN, emptyMap<ResourceLocation, Int>()).forGetter(PokemonP3::interactionCooldowns),
|
||||
Codec.BOOL.optionalFieldOf(DataKeys.POKEMON_ALPHA, false).forGetter(PokemonP3::isAlpha)
|
||||
).apply(instance) {
|
||||
originalTrainerType,
|
||||
originalTrainer,
|
||||
@@ -117,7 +120,8 @@ internal data class PokemonP3(
|
||||
rideBoosts,
|
||||
rideStamina,
|
||||
currentFullness,
|
||||
interactionCooldown -> PokemonP3(
|
||||
interactionCooldown,
|
||||
isAlpha -> PokemonP3(
|
||||
originalTrainerType,
|
||||
originalTrainer,
|
||||
forcedAspects.toSet(),
|
||||
@@ -133,6 +137,7 @@ internal data class PokemonP3(
|
||||
rideStamina,
|
||||
currentFullness,
|
||||
interactionCooldown,
|
||||
isAlpha
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -157,6 +162,7 @@ internal data class PokemonP3(
|
||||
pokemon.rideStamina,
|
||||
pokemon.currentFullness,
|
||||
pokemon.interactionCooldowns,
|
||||
pokemon.isAlpha
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:alpha_eyes",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_blend",
|
||||
"texture": "textures/particles/vanilla/generic"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.size": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [1, 0.5]
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"event_outer": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:alpha_eyes_outer",
|
||||
"type": "emitter_bound"
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_local_space": {
|
||||
"position": true,
|
||||
"rotation": false
|
||||
},
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 64,
|
||||
"max_particles": 200
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_events": {
|
||||
"creation_event": "event_outer"
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"radius": "0.04 * math.clamp(q.entity_size, 0.5,1.2)",
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.1
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(1,4) * 90"
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": -3.5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.1, 0.1],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 64,
|
||||
"texture_height": 8,
|
||||
"uv": [40, 0],
|
||||
"uv_size": [8, 8]
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": [1, 0, 0, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:alpha_eyes_outer",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_blend",
|
||||
"texture": "textures/particles/vanilla/generic"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.size": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [1, 0]
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 24,
|
||||
"max_particles": 200
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_sphere": {
|
||||
"radius": 0.04,
|
||||
"direction": [0, 1, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.7
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(1,4) * 90"
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 4, 0],
|
||||
"linear_drag_coefficient": 6
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": [0.06, 0.06],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 64,
|
||||
"texture_height": 8,
|
||||
"flipbook": {
|
||||
"base_UV": [56, 0],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [-8, 0],
|
||||
"frames_per_second": 12,
|
||||
"max_frame": 8
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FFFF0000",
|
||||
"0.22": "#FFFF0000",
|
||||
"1.0": "#00FF0000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -295,7 +295,7 @@
|
||||
"rotation": [-7.5, 0, 0],
|
||||
"cubes": [
|
||||
{"origin": [-2, 48.49, -4], "size": [4, 4, 2], "uv": [0, 51]},
|
||||
{"origin": [-1.5, 48.5, -1.995], "size": [3, 4, 0], "uv": [90, 0]},
|
||||
{"origin": [-1.5, 48.5, -2], "size": [3, 4, 0], "uv": [90, 0]},
|
||||
{"origin": [1.5, 51.49749, -3.03033], "size": [0, 1, 1], "pivot": [1.5, 52.52782, -2], "rotation": [45, 0, -7.5], "uv": [37, 39]},
|
||||
{"origin": [-1.5, 51.49749, -3.03033], "size": [0, 1, 1], "pivot": [-1.5, 52.52782, -2], "rotation": [45, 0, 7.5], "uv": [37, 38]}
|
||||
]
|
||||
|
||||
+16
-26
@@ -29,8 +29,7 @@
|
||||
"poseTypes": ["PORTRAIT", "PROFILE"],
|
||||
"isBattle": false,
|
||||
"isTouchingWater": false,
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -47,8 +46,7 @@
|
||||
"poseTypes": ["STAND"],
|
||||
"isBattle": true,
|
||||
"isTouchingWater": false,
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -70,8 +68,7 @@
|
||||
"battle-flying": {
|
||||
"poseTypes": ["HOVER"],
|
||||
"isBattle": true,
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -96,8 +93,7 @@
|
||||
"jump": {
|
||||
"poseTypes": ["STAND", "WALK"],
|
||||
"condition": "q.in_air",
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -119,8 +115,7 @@
|
||||
"isBattle": false,
|
||||
"isTouchingWater": false,
|
||||
"condition": "!q.in_air && q.is_sprinting",
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -144,8 +139,7 @@
|
||||
"isBattle": false,
|
||||
"isTouchingWater": false,
|
||||
"condition": "!q.in_air",
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -167,8 +161,7 @@
|
||||
"isBattle": false,
|
||||
"isTouchingWater": false,
|
||||
"condition": "!q.in_air && !q.is_sprinting",
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -190,8 +183,7 @@
|
||||
"hover": {
|
||||
"poseTypes": ["HOVER"],
|
||||
"isBattle": false,
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -210,8 +202,7 @@
|
||||
"poseTypes": ["FLY"],
|
||||
"isBattle": false,
|
||||
"condition": "!q.is_gliding",
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -235,8 +226,7 @@
|
||||
"poseTypes": ["FLY"],
|
||||
"isBattle": false,
|
||||
"condition": "q.is_gliding",
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -260,8 +250,7 @@
|
||||
"poseTypes": ["STAND", "FLOAT"],
|
||||
"isTouchingWater": true,
|
||||
"isUnderWater": false,
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -286,8 +275,7 @@
|
||||
"poseTypes": ["WALK", "SWIM"],
|
||||
"isTouchingWater": true,
|
||||
"isUnderWater": false,
|
||||
"animations": [
|
||||
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"animations": ["q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
|
||||
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
|
||||
"q.look('neck3', 0.45, 0.45, 10, -10, 20, -20)",
|
||||
"q.look('neck4', 0.35, 0.35, 5, -5, 15, -15)",
|
||||
@@ -313,8 +301,7 @@
|
||||
"namedAnimations": {
|
||||
"cry": "q.bedrock_stateful('dummy', 'cry')"
|
||||
},
|
||||
"animations": [
|
||||
"q.bedrock('charizard', 'sleep')",
|
||||
"animations": ["q.bedrock('charizard', 'sleep')",
|
||||
{
|
||||
"condition": "q.is_holding_item",
|
||||
"animation": "q.bedrock('charizard', 'hold_item')"
|
||||
@@ -326,3 +313,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0001_bulbasaur/bulbasaur_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0001_bulbasaur/bulbasaur_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0002_ivysaur/ivysaur_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0002_ivysaur/ivysaur_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0003_venusaur/venusaur_male_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0003_venusaur/venusaur_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -26,7 +26,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0004_charmander/charmander_shiny.png",
|
||||
"layers": [
|
||||
{
|
||||
@@ -45,6 +47,18 @@
|
||||
"translucent": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0004_charmander/charmander_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -26,7 +26,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0005_charmeleon/charmeleon_shiny.png",
|
||||
"layers": [
|
||||
{
|
||||
@@ -45,6 +47,18 @@
|
||||
"translucent": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0005_charmeleon/charmeleon_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+10
@@ -45,6 +45,16 @@
|
||||
"translucent": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["alpha_eyes"],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0006_charizard/charizard_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+21
-3
@@ -10,11 +10,15 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0007_squirtle/squirtle_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-black_glasses"],
|
||||
"aspects": [
|
||||
"cosmetic_item-black_glasses"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"texture": "cobblemon:textures/pokemon/0007_squirtle/squirtle_triangleglasses.png"
|
||||
@@ -22,12 +26,26 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-wise_glasses"],
|
||||
"aspects": [
|
||||
"cosmetic_item-wise_glasses"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"texture": "cobblemon:textures/pokemon/0007_squirtle/squirtle_circleglasses.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0007_squirtle/squirtle_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+21
-3
@@ -10,11 +10,15 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0008_wartortle/wartortle_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-black_glasses"],
|
||||
"aspects": [
|
||||
"cosmetic_item-black_glasses"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"texture": "cobblemon:textures/pokemon/0008_wartortle/wartortle_triangleglasses.png"
|
||||
@@ -22,12 +26,26 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-wise_glasses"],
|
||||
"aspects": [
|
||||
"cosmetic_item-wise_glasses"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"texture": "cobblemon:textures/pokemon/0008_wartortle/wartortle_circleglasses.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0008_wartortle/wartortle_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+21
-3
@@ -10,11 +10,15 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0009_blastoise/blastoise_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-black_glasses"],
|
||||
"aspects": [
|
||||
"cosmetic_item-black_glasses"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"texture": "cobblemon:textures/pokemon/0009_blastoise/blastoise_triangleglasses.png"
|
||||
@@ -22,12 +26,26 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-wise_glasses"],
|
||||
"aspects": [
|
||||
"cosmetic_item-wise_glasses"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"texture": "cobblemon:textures/pokemon/0009_blastoise/blastoise_circleglasses.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0009_blastoise/blastoise_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0010_caterpie/caterpie_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0010_caterpie/caterpie_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0011_metapod/metapod_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0011_metapod/metapod_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0012_butterfree/butterfree_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0012_butterfree/butterfree_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0013_weedle/weedle_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0013_weedle/weedle_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0014_kakuna/kakuna_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0014_kakuna/kakuna_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -9,8 +9,22 @@
|
||||
"texture": "cobblemon:textures/pokemon/0015_beedrill/beedrill.png"
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0015_beedrill/beedrill_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0015_beedrill/beedrill_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0016_pidgey/pidgey_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0016_pidgey/pidgey_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0017_pidgeotto/pidgeotto_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0017_pidgeotto/pidgeotto_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0018_pidgeot/pidgeot_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0018_pidgeot/pidgeot_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0019_rattata/rattata_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0019_rattata/rattata_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0020_raticate/raticate_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0020_raticate/raticate_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0021_spearow/spearow_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0021_spearow/spearow_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0022_fearow/fearow_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0022_fearow/fearow_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0023_ekans/ekans_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0023_ekans/ekans_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+68
-16
@@ -16,7 +16,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0024_arbok/arbok_shiny.png",
|
||||
"layers": [
|
||||
{
|
||||
@@ -27,7 +29,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["snake-pattern-attack"],
|
||||
"aspects": [
|
||||
"snake-pattern-attack"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -37,7 +41,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["snake-pattern-dark"],
|
||||
"aspects": [
|
||||
"snake-pattern-dark"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -47,7 +53,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["snake-pattern-elusive"],
|
||||
"aspects": [
|
||||
"snake-pattern-elusive"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -57,7 +65,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["snake-pattern-heart"],
|
||||
"aspects": [
|
||||
"snake-pattern-heart"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -67,7 +77,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["snake-pattern-legacy"],
|
||||
"aspects": [
|
||||
"snake-pattern-legacy"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -77,7 +89,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["snake-pattern-sound"],
|
||||
"aspects": [
|
||||
"snake-pattern-sound"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -87,7 +101,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["snake-pattern-speed"],
|
||||
"aspects": [
|
||||
"snake-pattern-speed"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -97,7 +113,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-attack"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-attack"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -107,7 +126,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-dark"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-dark"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -117,7 +139,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-elusive"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-elusive"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -127,7 +152,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-heart"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-heart"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -137,7 +165,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-legacy"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-legacy"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -147,7 +178,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-sound"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-sound"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -157,7 +191,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-speed"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-speed"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -167,7 +204,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "snake-pattern-classic"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"snake-pattern-classic"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pattern",
|
||||
@@ -175,6 +215,18 @@
|
||||
"emissive": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0024_arbok/arbok_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+113
-29
@@ -17,7 +17,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0025_pikachu/pikachu_shiny.png",
|
||||
"layers": [
|
||||
{
|
||||
@@ -29,7 +31,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["female"],
|
||||
"aspects": [
|
||||
"female"
|
||||
],
|
||||
"poser": "cobblemon:pikachu",
|
||||
"model": "cobblemon:pikachu_female.geo",
|
||||
"texture": "cobblemon:textures/pokemon/0025_pikachu/pikachu.png",
|
||||
@@ -43,7 +47,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny", "female"],
|
||||
"aspects": [
|
||||
"shiny",
|
||||
"female"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0025_pikachu/pikachu_shiny.png",
|
||||
"layers": [
|
||||
{
|
||||
@@ -55,7 +62,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-rage_candy_bar"],
|
||||
"aspects": [
|
||||
"cosmetic_item-rage_candy_bar"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -65,7 +74,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-pewter_crunchies"],
|
||||
"aspects": [
|
||||
"cosmetic_item-pewter_crunchies"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -75,7 +86,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lava_cookie"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lava_cookie"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -85,7 +98,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-old_gateau"],
|
||||
"aspects": [
|
||||
"cosmetic_item-old_gateau"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -95,7 +110,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-casteliacone"],
|
||||
"aspects": [
|
||||
"cosmetic_item-casteliacone"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -105,7 +122,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lumiose_galette"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lumiose_galette"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -115,7 +134,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-big_malasada"],
|
||||
"aspects": [
|
||||
"cosmetic_item-big_malasada"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -125,7 +146,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-smoked_tail_curry"],
|
||||
"aspects": [
|
||||
"cosmetic_item-smoked_tail_curry"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -135,7 +158,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-compass"],
|
||||
"aspects": [
|
||||
"cosmetic_item-compass"
|
||||
],
|
||||
"model": "cobblemon:pikachu_captain_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -145,11 +170,15 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-shears"],
|
||||
"aspects": [
|
||||
"cosmetic_item-shears"
|
||||
],
|
||||
"model": "cobblemon:pikachu_fluff_male.geo"
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-leather_helmet"],
|
||||
"aspects": [
|
||||
"cosmetic_item-leather_helmet"
|
||||
],
|
||||
"model": "cobblemon:pikachu_detective_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -159,7 +188,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-sinister_tea"],
|
||||
"aspects": [
|
||||
"cosmetic_item-sinister_tea"
|
||||
],
|
||||
"model": "cobblemon:pikachu_detective_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -169,7 +200,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-cocoa_beans"],
|
||||
"aspects": [
|
||||
"cosmetic_item-cocoa_beans"
|
||||
],
|
||||
"model": "cobblemon:pikachu_detective_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -179,7 +212,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-rage_candy_bar", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-rage_candy_bar",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -189,7 +225,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-pewter_crunchies", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-pewter_crunchies",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -199,7 +238,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lava_cookie", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lava_cookie",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -209,7 +251,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-old_gateau", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-old_gateau",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -219,7 +264,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-casteliacone", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-casteliacone",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -229,7 +277,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lumiose_galette", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lumiose_galette",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -239,7 +290,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-big_malasada", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-big_malasada",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -249,7 +303,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-smoked_tail_curry", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-smoked_tail_curry",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -259,7 +316,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-compass", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-compass",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_captain_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -269,11 +329,17 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-shears", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-shears",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_fluff_female.geo"
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-leather_helmet", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-leather_helmet",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_detective_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -283,7 +349,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-sinister_tea", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-sinister_tea",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_detective_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -293,7 +362,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-cocoa_beans", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-cocoa_beans",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:pikachu_detective_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -301,6 +373,18 @@
|
||||
"texture": "cobblemon:textures/pokemon/0025_pikachu/pikachu_detective.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0025_pikachu/pikachu_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+113
-29
@@ -17,7 +17,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0026_raichu/raichu_shiny.png",
|
||||
"layers": [
|
||||
{
|
||||
@@ -29,7 +31,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["female"],
|
||||
"aspects": [
|
||||
"female"
|
||||
],
|
||||
"poser": "cobblemon:raichu",
|
||||
"model": "cobblemon:raichu_female.geo",
|
||||
"texture": "cobblemon:textures/pokemon/0026_raichu/raichu.png",
|
||||
@@ -43,7 +47,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["female","shiny"],
|
||||
"aspects": [
|
||||
"female",
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0026_raichu/raichu_shiny.png",
|
||||
"layers": [
|
||||
{
|
||||
@@ -55,7 +62,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-rage_candy_bar"],
|
||||
"aspects": [
|
||||
"cosmetic_item-rage_candy_bar"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -65,7 +74,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-pewter_crunchies"],
|
||||
"aspects": [
|
||||
"cosmetic_item-pewter_crunchies"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -75,7 +86,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lava_cookie"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lava_cookie"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -85,7 +98,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-old_gateau"],
|
||||
"aspects": [
|
||||
"cosmetic_item-old_gateau"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -95,7 +110,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-casteliacone"],
|
||||
"aspects": [
|
||||
"cosmetic_item-casteliacone"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -105,7 +122,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lumiose_galette"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lumiose_galette"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -115,7 +134,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-big_malasada"],
|
||||
"aspects": [
|
||||
"cosmetic_item-big_malasada"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -125,7 +146,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-smoked_tail_curry"],
|
||||
"aspects": [
|
||||
"cosmetic_item-smoked_tail_curry"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -135,7 +158,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-compass"],
|
||||
"aspects": [
|
||||
"cosmetic_item-compass"
|
||||
],
|
||||
"model": "cobblemon:raichu_captain_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -145,11 +170,15 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-shears"],
|
||||
"aspects": [
|
||||
"cosmetic_item-shears"
|
||||
],
|
||||
"model": "cobblemon:raichu_fluff_male.geo"
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-leather_helmet"],
|
||||
"aspects": [
|
||||
"cosmetic_item-leather_helmet"
|
||||
],
|
||||
"model": "cobblemon:raichu_detective_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -159,7 +188,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-sinister_tea"],
|
||||
"aspects": [
|
||||
"cosmetic_item-sinister_tea"
|
||||
],
|
||||
"model": "cobblemon:raichu_detective_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -169,7 +200,9 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-cocoa_beans"],
|
||||
"aspects": [
|
||||
"cosmetic_item-cocoa_beans"
|
||||
],
|
||||
"model": "cobblemon:raichu_detective_male.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -179,7 +212,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-rage_candy_bar", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-rage_candy_bar",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -189,7 +225,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-pewter_crunchies", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-pewter_crunchies",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -199,7 +238,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lava_cookie", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lava_cookie",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -209,7 +251,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-old_gateau", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-old_gateau",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -219,7 +264,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-casteliacone", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-casteliacone",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -229,7 +277,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-lumiose_galette", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-lumiose_galette",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -239,7 +290,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-big_malasada", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-big_malasada",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -249,7 +303,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-smoked_tail_curry", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-smoked_tail_curry",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_cap_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -259,7 +316,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-compass", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-compass",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_captain_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -269,11 +329,17 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-shears", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-shears",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_fluff_female.geo"
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-leather_helmet", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-leather_helmet",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_detective_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -283,7 +349,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-sinister_tea", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-sinister_tea",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_detective_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -293,7 +362,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": ["cosmetic_item-cocoa_beans", "female"],
|
||||
"aspects": [
|
||||
"cosmetic_item-cocoa_beans",
|
||||
"female"
|
||||
],
|
||||
"model": "cobblemon:raichu_detective_female.geo",
|
||||
"layers": [
|
||||
{
|
||||
@@ -301,6 +373,18 @@
|
||||
"texture": "cobblemon:textures/pokemon/0026_raichu/raichu_detective.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0026_raichu/raichu_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0027_sandshrew/sandshrew_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0027_sandshrew/sandshrew_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0028_sandslash/sandslash_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0028_sandslash/sandslash_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0029_nidoranf/nidoranf_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0029_nidoranf/nidoranf_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0030_nidorina/nidorina_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0030_nidorina/nidorina_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0031_nidoqueen/nidoqueen_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0031_nidoqueen/nidoqueen_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0032_nidoranm/nidoranm_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0032_nidoranm/nidoranm_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0033_nidorino/nidorino_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0033_nidorino/nidorino_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0034_nidoking/nidoking_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0034_nidoking/nidoking_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0035_clefairy/clefairy_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0035_clefairy/clefairy_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0036_clefable/clefable_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0036_clefable/clefable_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0037_vulpix/vulpix_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0037_vulpix/vulpix_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0038_ninetales/ninetales_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0038_ninetales/ninetales_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+18
-2
@@ -10,17 +10,33 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0039_jigglypuff/jigglypuff_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": ["color-black"],
|
||||
"aspects": [
|
||||
"color-black"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "pokemopolis",
|
||||
"texture": "cobblemon:textures/pokemon/0039_jigglypuff/jigglypuff_pokemopolis.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0039_jigglypuff/jigglypuff_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0040_wigglytuff/wigglytuff_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0040_wigglytuff/wigglytuff_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0041_zubat/zubat_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0041_zubat/zubat_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+15
-1
@@ -10,8 +10,22 @@
|
||||
"layers": []
|
||||
},
|
||||
{
|
||||
"aspects": ["shiny"],
|
||||
"aspects": [
|
||||
"shiny"
|
||||
],
|
||||
"texture": "cobblemon:textures/pokemon/0042_golbat/golbat_shiny.png"
|
||||
},
|
||||
{
|
||||
"aspects": [
|
||||
"alpha_eyes"
|
||||
],
|
||||
"layers": [
|
||||
{
|
||||
"name": "alpha_eyes",
|
||||
"texture": "cobblemon:textures/pokemon/0042_golbat/golbat_alpha.png",
|
||||
"emissive": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user