mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-28 04:56:26 -04:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4c4dadee1 | ||
|
|
990cb1886e | ||
|
|
15ae1100ac |
+1
-267
@@ -2,273 +2,7 @@
|
||||
## [1.8.x (MONTH xth, 2026)](#1-8-x)
|
||||
|
||||
### Additions
|
||||
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
|
||||
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
|
||||
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
|
||||
- Added brewing recipe for Throat Spray.
|
||||
- Added mood particles! Pokémon now visually react to certain actions:
|
||||
- Angry particles when attacking a mob.
|
||||
- Annoyed particles when a player tries to feed them while they’re already full.
|
||||
- Sweat droplets when they run out of stamina while being ridden.
|
||||
- Added config options to award experience to fainted Pokémon for opponents they helped defeat (`awardExperienceToFaintedPokemon`) and to still award experience for defeated enemies even after battle loss/forfeit (`awardExperienceOnBattleLoss`)
|
||||
- Party Overlay Exp Gained Animation will now display the amount of EXP the Pokémon gained
|
||||
- Added a toast to notify players of how they can scroll through their party. Did you know you can hold R and scroll instead of using arrow keys??!
|
||||
- Added a new layer property that makes a layer scroll in a direction. "scrolling": {"speedU": 0.1, "speedV": 0.1}
|
||||
- Added missing crops to Botany Pots integration
|
||||
- Added a way to obtain Porygon by inserting the Upgrade or Dubious Disc into a data monitor
|
||||
- Added a new `cobblemon:structure`, which is a feature without any restrictions allowing the Builders to place certain structures in much more specific manner.
|
||||
- Added Configs for Infinite Use TMs and Unlocking all TMs
|
||||
- Added Type Gem blocks
|
||||
- Added Type Gem Clusters
|
||||
- Added TMs
|
||||
- Added TM Machine
|
||||
- Added Deepslate Core Block
|
||||
- Added /givetm Command
|
||||
- Added advancement triggers for learning TMs: `cobblemon:has_learn_specific_tm` (per-TM), `cobblemon:has_learn_all_tm` (all TMs learned), and `cobblemon:tms_learned` (count-based), backed by a new `totalTMLearnedCount` on player advancement data.
|
||||
- Added `cobblemon:catch_alpha_pokemon` advancement trigger and `totalAlphaCaptureCount` tracking for capturing Alpha Pokémon.
|
||||
- Added Move Dex to Pokédex
|
||||
- Added the Habitat Block, a spawner block for servers and adventure maps that controls spawning in an area.
|
||||
- Added Disk Rack for storing disks and being an audio sequencer for Noteblocks
|
||||
- Added intrinsic scaling to all Pokémon (+-5%). Some rendering cases, such as shoulder mounting, revert to 1.0 scaling to preserve animation accuracy.
|
||||
- Added scaling to "baby" Pokémon (smaller (-20%) at level 1 → normally sized at level 10)
|
||||
- Added conditional seats for riding. Seats can be gated by molang such as "is_alpha".
|
||||
- Added Alpha Pokémon
|
||||
- Added alpha scaling (alphas are larger than their normal counterparts)
|
||||
- Alphas will always lead herds and will spawn in herds
|
||||
- Alphas spawn with two random TM moves from their learnset
|
||||
- Alpha Pokémon will always defend themselves from players that attack them
|
||||
- Added alpha level matching and stat boost (based on level)
|
||||
- Added pitch-down and reverb to alpha cries
|
||||
- Added alpha Pokémon bait effect
|
||||
- Added alpha eye rendering including eye overlay, bloom, eye trail, and particles.
|
||||
- Added cobweb block slowness immunity for spider Pokémon
|
||||
- Added 49 new habitat structures. 34 as typical Minecraft structures and 15 as structures that get placed as biome features to allow for more natural placement in generation. Structures placed as biome features will not be able to be located with the `/locate structure` command.
|
||||
- Vanilla village house template pools have been adjusted to account for the new abandoned village structure habitat. Weights have changed within the JSON file for every piece to ensure too many habitats don't generate in a single village.
|
||||
- Added 10 new ruin structures.
|
||||
- rooted_arch_ruins & crumbling_arch_ruins have been transferred over to biome features, allowing for better placement in generation.
|
||||
- All ruin structures that did not generate with a gimmighoul/gilded chest before will now generate with one.
|
||||
- All ruin structures gilded chest loot tables have been updated to include a guaranteed TM not learned naturally by any Pokémon through their level-up moveset. Each ruin gets its own specific TM, so you can now go hunting ruins to complete your move dex!
|
||||
- All fossil structures have been transferred over to biome features, allowing for better placement in generation.
|
||||
- The prehistoric_underwater_fissure & prehistoric_submerged_impact fossil structures now use the biome tag `#cobblemon:is_temperate_ocean`.
|
||||
- Gimmighoul towers now generate at ground level rather than sinking one block into the ground.
|
||||
- A new shipwreck cove structure called the "magma_shipwreck_cove" has been added.
|
||||
- Shipwreck coves now generate slightly more frequently.
|
||||
- Added equipment loot tables for shipwreck cove enemies.
|
||||
- Maps from abandoned fishing boats leading to shipwreck coves now will skip explored chunks, allowing the player to find more shipwreck coves easier.
|
||||
- The lush shipwreck cove's phantom mob spawner has been replaced with breezes.
|
||||
- The lush shipwreck cove structure itself has been slightly cleaned up to be less noisy with the blocks it is built out of.
|
||||
- All shipwreck coves' spawners have been adjusted to give compatible mobs enchanted iron or diamond armour and weapons while in its ominous state. The armour given to the mobs will also use the automaton trim. We upped the difficulty because it was too easy now that your Pokémon can fight for you.
|
||||
- One TM of the elemental hyper beams has been added as guaranteed loot to the main treasure chest in every shipwreck cove. (Magma cove gets blast burn, lush cove gets frenzy plant, and submerged cove gets hydro cannon)
|
||||
- Added 7 new advancements
|
||||
- Pressing the inventory key now closes the Pokémon interact wheel GUI
|
||||
- Pokémon cries now play when clicking Pokémon in the summary screen.
|
||||
- Pressing the Summary key while either the starter selection or summary screen are open now closes those screens
|
||||
- Ice type Pokémon are now immune to Packed Snow
|
||||
- Held item visibility can now be controlled by the held_item_visible command argument.
|
||||
|
||||
### New rideable Pokémon
|
||||
- Crobat
|
||||
- Skarmory
|
||||
- Milotic
|
||||
- Archeops
|
||||
- Goodra
|
||||
- Goodra (Hisuian Form)
|
||||
- Drampa
|
||||
- Duraludon
|
||||
- Archaludon
|
||||
|
||||
### Pokémon Added
|
||||
#### Generation 3
|
||||
- Wurmple
|
||||
- Silcoon
|
||||
- Beautifly
|
||||
- Cascoon
|
||||
- Dustox
|
||||
- Skitty
|
||||
- Delcatty
|
||||
- Seviper
|
||||
- Zangoose
|
||||
|
||||
#### Generation 4
|
||||
- Cherubi
|
||||
- Cherrim
|
||||
- Stunky
|
||||
- Skuntank
|
||||
|
||||
#### Generation 5
|
||||
- Audino
|
||||
- Pawniard
|
||||
- Bisharp
|
||||
|
||||
#### Generation 6
|
||||
- Pancham (+ Cosmetic with Black Glasses)
|
||||
- Pangoro (+ Cosmetic with Black Glasses)
|
||||
|
||||
#### Generation 7
|
||||
- Rockruff
|
||||
- Lycanroc
|
||||
|
||||
#### Generation 8
|
||||
- Rolycoly
|
||||
- Carkol
|
||||
- Coalossal
|
||||
- Runerigus
|
||||
- Snom
|
||||
- Frosmoth
|
||||
- Indeedee
|
||||
- Duraludon
|
||||
- Applin
|
||||
- Flapple
|
||||
- Appletun
|
||||
|
||||
#### Generation 9
|
||||
|
||||
- Nymble
|
||||
- Lokix
|
||||
- Kingambit
|
||||
- Dipplin
|
||||
- Archaludon
|
||||
- Hydrapple
|
||||
|
||||
#### Regional Forms
|
||||
- Sandshrew (Alolan Form)
|
||||
- Sandslash (Alolan Form)
|
||||
- Yamask (Galarian Form)
|
||||
- Avalugg (Hisuian Form)
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
|
||||
- Sandshrew
|
||||
- Sandslash
|
||||
- Nidoking
|
||||
- Zubat
|
||||
- Golbat
|
||||
- Crobat
|
||||
- Ditto
|
||||
- Porygon
|
||||
- Porygon2
|
||||
- Porygon-Z
|
||||
- Skarmory
|
||||
- Smoochum
|
||||
- Jynx
|
||||
- Popplio
|
||||
- Brionne
|
||||
- Primarina
|
||||
- Fletchling
|
||||
- Fletchinder
|
||||
- Talonflame
|
||||
- Sableye
|
||||
- Mawile
|
||||
- Goomy
|
||||
- Sliggoo
|
||||
- Goodra
|
||||
- Nacli
|
||||
- Naclstack
|
||||
- Garganacl
|
||||
- Bidoof
|
||||
- Cranidos
|
||||
- Chatot
|
||||
- Yamask
|
||||
- Cofagrigus
|
||||
- Tyranitar
|
||||
- Turtonator
|
||||
- Golett
|
||||
- Corsola
|
||||
- Arbok (New Patterns: Angry, Cartoon, Clown, Comedic, Crow, Grin, Ink, Modern, Rain, Scribble, Silence, Sloth, Suspicious, Will)
|
||||
- ... and Substitute
|
||||
|
||||
#### Model changes to the regional bias resource pack:
|
||||
|
||||
- Added Mime Jr. (Galar Bias)
|
||||
- Added Bergmite (Hisui Bias)
|
||||
- Changed models for every existing regional bias
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
|
||||
- Kakuna
|
||||
- Grimer
|
||||
- Nidoran♀ (+ New shoulder mount)
|
||||
- Nidorina
|
||||
- Nidoran♂ (+ New shoulder mount)
|
||||
- Sandshrew
|
||||
- Diglett
|
||||
- Dugtrio
|
||||
- Graveler
|
||||
- Happiny
|
||||
- Chansey
|
||||
- Blissey
|
||||
- Poliwhirl
|
||||
- Poliwrath
|
||||
- Zubat
|
||||
- Vulpix
|
||||
- Drowzee
|
||||
- Hypno
|
||||
- Noctowl
|
||||
- Skarmory
|
||||
- Skitty
|
||||
- Flygon
|
||||
- Shellos
|
||||
- Riolu
|
||||
- Lucario
|
||||
- Purrloin
|
||||
- Liepard
|
||||
- Joltik
|
||||
- Galvantula
|
||||
- Nidoking
|
||||
- Fletchling
|
||||
- Fletchinder
|
||||
- Talonflame
|
||||
- Archeops
|
||||
- Drampa
|
||||
- Sewaddle
|
||||
- Swadloon
|
||||
- Leavanny
|
||||
- Goomy
|
||||
- Sliggoo
|
||||
- Goodra
|
||||
- Shedinja
|
||||
- Skwovet
|
||||
- Greedent
|
||||
- Bidoof
|
||||
- Cranidos
|
||||
- Chatot
|
||||
- Yamask
|
||||
- Cofagrigus
|
||||
- Luvdisc
|
||||
- Staryu
|
||||
- Starmie
|
||||
- Togetic
|
||||
- Rellor
|
||||
- Rabsca
|
||||
- Yungoos
|
||||
- Gumshoos
|
||||
- Cottonee
|
||||
- Whimsicott
|
||||
- Corsola
|
||||
|
||||
#### Added sounds to the following moves
|
||||
|
||||
- Absorb
|
||||
- Aurora Beam
|
||||
- Double Team
|
||||
- Draco Meteor
|
||||
- Fire Punch
|
||||
- Fire Spin
|
||||
- Flame Charge
|
||||
- Flame Wheel
|
||||
- Giga Drain
|
||||
- Ice Punch
|
||||
- Leech Life
|
||||
- Magical Leaf
|
||||
- Mega Drain
|
||||
- Minimize
|
||||
- Poison Gas
|
||||
- Rock Throw
|
||||
- Scary Face
|
||||
- Seed bomb
|
||||
- Smokescreen
|
||||
- String Shot
|
||||
- Tail Whip
|
||||
- You can now view the biome, level, and date you caught a Pokémon.
|
||||
|
||||
### Changes
|
||||
|
||||
|
||||
@@ -344,6 +344,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(RideStaminaUpdatePacket.ID, RideStaminaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(AlphaUpdatePacket.ID, AlphaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(ScaleModifierUpdatePacket.ID, ScaleModifierUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(MetDataUpdatePacket.ID, MetDataUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Evolution start
|
||||
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
+3
-7
@@ -92,17 +92,13 @@ interface PokemonAndMoveSelectingItem {
|
||||
}
|
||||
|
||||
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
if (pokemon.entity == null && stack.`is`(CobblemonItemTags.POKE_FOOD) && pokemon.isFull()) {
|
||||
return false
|
||||
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
|
||||
return !pokemon.isFull()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean {
|
||||
return bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
|
||||
}
|
||||
|
||||
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
|
||||
fun canUseOnMove(stack: ItemStack, pokemon: Pokemon, move: Move): Boolean = canUseOnMove(stack, move)
|
||||
fun canUseOnMove(stack: ItemStack, move: Move): Boolean
|
||||
|
||||
|
||||
@@ -107,16 +107,13 @@ interface PokemonSelectingItem {
|
||||
}
|
||||
|
||||
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
if (pokemon.entity == null && stack.`is`(CobblemonItemTags.POKE_FOOD) && pokemon.isFull()) {
|
||||
return false
|
||||
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
|
||||
return !pokemon.isFull()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean {
|
||||
return bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
|
||||
}
|
||||
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
|
||||
|
||||
fun interactWithSpecificBattle(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon): InteractionResultHolder<ItemStack> {
|
||||
return if (canUseOnBattlePokemon(stack, battlePokemon)) {
|
||||
|
||||
+2
-3
@@ -55,9 +55,8 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
|
||||
}
|
||||
functions["feed_pokemon"] = { params ->
|
||||
val amount = params.getDouble(0)
|
||||
val playSound = params.getBooleanOrNull(1) != false
|
||||
val playMoodParticles = params.getBooleanOrNull(2) != false
|
||||
DoubleValue(pokemon.feedPokemon(amount.toInt(), playSound, playMoodParticles))
|
||||
val playSound = params.getBooleanOrNull(1) ?: true
|
||||
pokemon.feedPokemon(amount.toInt(), playSound)
|
||||
}
|
||||
functions["behaviour"] = { pokemon.form.behaviour.struct }
|
||||
functions["behavior"] = { pokemon.form.behaviour.struct } // Inferior
|
||||
|
||||
@@ -44,7 +44,6 @@ object ActionEffects : JsonDataRegistry<ActionEffectTimeline> {
|
||||
ActionEffectKeyframe.register<EntityMoLangActionEffectKeyframe>("entity_molang")
|
||||
ActionEffectKeyframe.register<MoLangActionEffectKeyframe>("molang")
|
||||
ActionEffectKeyframe.register<ParallelActionEffectKeyframe>("parallel")
|
||||
ActionEffectKeyframe.register<LoopActionEffectKeyframe>("loop")
|
||||
ActionEffectKeyframe.register<CanInterruptActionEffectKeyframe>("can_interrupt")
|
||||
ActionEffectKeyframe.register<CannotInterruptActionEffectKeyframe>("cannot_interrupt")
|
||||
ActionEffectKeyframe.register<RemoveHoldsActionEffectKeyframe>("remove_holds")
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class LoopActionEffectKeyframe(
|
||||
val keyframe: ActionEffectKeyframe = PauseActionEffectKeyframe()
|
||||
) : ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
val future = CompletableFuture<Unit>()
|
||||
runIteration(context, future)
|
||||
return future
|
||||
}
|
||||
|
||||
private fun runIteration(context: ActionEffectContext, future: CompletableFuture<Unit>) {
|
||||
context.currentKeyframes.add(keyframe)
|
||||
keyframe.play(context)
|
||||
.thenRun { context.currentKeyframes.remove(keyframe) }
|
||||
.thenAccept {
|
||||
if (condition.resolveBoolean(context.runtime)) {
|
||||
runIteration(context, future)
|
||||
} else {
|
||||
future.complete(Unit)
|
||||
}
|
||||
}
|
||||
.exceptionally {
|
||||
future.completeExceptionally(it)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
-7
@@ -6,23 +6,59 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves
|
||||
package com.cobblemon.mod.common.client.gui.summary
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.ObjectSelectionList
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.util.Mth
|
||||
|
||||
class MoveDescriptionScrollList(
|
||||
class ScrollableTextBoxEntry(
|
||||
var line : MutableComponent
|
||||
) :
|
||||
ObjectSelectionList.Entry<ScrollableTextBoxEntry>() {
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
rowTop: Int,
|
||||
rowLeft: Int,
|
||||
rowWidth: Int,
|
||||
rowHeight: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
isHovered: Boolean,
|
||||
partialTicks: Float
|
||||
) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = line,
|
||||
x = rowLeft + 82,
|
||||
y = rowTop,
|
||||
scale = 0.5F,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
override fun getNarration(): Component {
|
||||
return line
|
||||
}
|
||||
}
|
||||
|
||||
class ScrollableTextBox(
|
||||
private val listX: Int,
|
||||
private val listY: Int,
|
||||
height: Int,
|
||||
width: Int,
|
||||
slotHeight: Int
|
||||
) : ObjectSelectionList<MoveDescriptionEntry>(
|
||||
) : ObjectSelectionList<ScrollableTextBoxEntry>(
|
||||
Minecraft.getInstance(),
|
||||
60, // width
|
||||
30, // height
|
||||
width, // width
|
||||
height, // height
|
||||
0, // top
|
||||
slotHeight
|
||||
), CobblemonRenderable {
|
||||
@@ -38,8 +74,31 @@ class MoveDescriptionScrollList(
|
||||
return x + width - 3
|
||||
}
|
||||
|
||||
override fun getMaxPosition(): Int {
|
||||
return super.getMaxPosition() + 3 // add bottom padding
|
||||
}
|
||||
|
||||
// we do our own scrollbar rendering, and this being true renders the vanilla one
|
||||
override fun scrollbarVisible() = false
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, f: Float) {
|
||||
isHovered = pMouseX >= x && pMouseY >= y && pMouseX < x + width && pMouseY < y + height
|
||||
|
||||
if (maxScroll > 0) {
|
||||
val right = x + width
|
||||
val bottom = y + height
|
||||
val darkGray = 0xFF5B595B.toInt()
|
||||
val lightGray = 0xFF8C8C8C.toInt()
|
||||
context.fill(right - 2, y + 2, right - 4, bottom - 2, darkGray)
|
||||
// vanilla scrollbar mumbo jumbo
|
||||
var scrollHeight = ((height * height).toFloat() / maxPosition.toFloat()).toInt()
|
||||
scrollHeight = Mth.clamp(scrollHeight, 32, height - 8)
|
||||
var scrollY = scrollAmount.toInt() * (height - scrollHeight + 2) / maxScroll + y - 1
|
||||
if (scrollY < y) { scrollY = y }
|
||||
|
||||
context.fill(right - 2, scrollY + 2, right - 4, scrollY + scrollHeight - 3, lightGray)
|
||||
}
|
||||
|
||||
context.enableScissor(
|
||||
x,
|
||||
y,
|
||||
@@ -79,7 +138,7 @@ class MoveDescriptionScrollList(
|
||||
&& mouseY < bottom
|
||||
}
|
||||
|
||||
fun setMoveDescription(moveDescription: MutableComponent) {
|
||||
fun setText(moveDescription: MutableComponent) {
|
||||
clearEntries()
|
||||
val splitWidth = 100
|
||||
val text = moveDescription.string
|
||||
@@ -103,7 +162,8 @@ class MoveDescriptionScrollList(
|
||||
}
|
||||
|
||||
for (part in splitText) {
|
||||
addEntry(MoveDescriptionEntry(Component.literal(part)))
|
||||
addEntry(ScrollableTextBoxEntry(Component.literal(part)))
|
||||
}
|
||||
scrollAmount = 0.0
|
||||
}
|
||||
}
|
||||
+32
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.gui.MultiLineLabelK
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.*
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.summary.ScrollableTextBox
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNatureTextIfMinted
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.StatWidget.Companion.SCALE
|
||||
@@ -27,6 +28,7 @@ import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class InfoWidget(
|
||||
pX: Int,
|
||||
@@ -45,6 +47,25 @@ class InfoWidget(
|
||||
private val infoBaseResource = cobblemonResource("textures/gui/summary/summary_info_base.png")
|
||||
}
|
||||
|
||||
private var metDataWidget: ScrollableTextBox = ScrollableTextBox(x + 5, y + 123, 20, 61, 5)
|
||||
|
||||
init {
|
||||
pokemon.metData?.let { metData ->
|
||||
val biome = ResourceLocation.parse(metData.biome.registeredName)
|
||||
val biomeName = Component.translatable("biome.${biome.namespace}.${biome.path}")
|
||||
metDataWidget.setText(lang("ui.info.met_data",
|
||||
biomeName,
|
||||
metData.date.monthValue,
|
||||
metData.date.dayOfMonth,
|
||||
metData.date.year,
|
||||
metData.level
|
||||
))
|
||||
} ?: run {
|
||||
metDataWidget.setText(lang("ui.info.met_data_unavailable"))
|
||||
}
|
||||
addWidget(metDataWidget)
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
val matrices = context.pose()
|
||||
// Base texture
|
||||
@@ -163,6 +184,17 @@ class InfoWidget(
|
||||
)
|
||||
matrices.popPose()
|
||||
|
||||
metDataWidget.render(context, pMouseX, pMouseY, pPartialTicks)
|
||||
|
||||
|
||||
// val textLines = mutableListOf<MutableComponent>()
|
||||
// pokemon.metData?.let { metData ->
|
||||
|
||||
// }
|
||||
//
|
||||
// metDataWidget.textLines = textLines
|
||||
// metDataWidget.render(context, pMouseX, pMouseY, pPartialTicks)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.info.experience_points"),
|
||||
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves
|
||||
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.ObjectSelectionList
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
class MoveDescriptionEntry(
|
||||
var line : MutableComponent
|
||||
) :
|
||||
ObjectSelectionList.Entry<MoveDescriptionEntry>() {
|
||||
|
||||
override fun render(
|
||||
context: GuiGraphics,
|
||||
index: Int,
|
||||
rowTop: Int,
|
||||
rowLeft: Int,
|
||||
rowWidth: Int,
|
||||
rowHeight: Int,
|
||||
mouseX: Int,
|
||||
mouseY: Int,
|
||||
isHovered: Boolean,
|
||||
partialTicks: Float
|
||||
) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = line,
|
||||
x = rowLeft + 82,
|
||||
y = rowTop,
|
||||
scale = 0.5F,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
override fun getNarration(): Component {
|
||||
return line
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.Move
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.summary.ScrollableTextBox
|
||||
import com.cobblemon.mod.common.client.gui.summary.Summary
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
@@ -70,9 +71,11 @@ class MovesWidget(
|
||||
addWidget(it)
|
||||
}
|
||||
|
||||
private var descriptionScrollList = MoveDescriptionScrollList(
|
||||
x + 69,
|
||||
private var descriptionScrollList = ScrollableTextBox(
|
||||
x + 68,
|
||||
y + 113,
|
||||
30,
|
||||
61,
|
||||
5
|
||||
)
|
||||
|
||||
@@ -215,7 +218,7 @@ class MovesWidget(
|
||||
|
||||
fun selectMove(move: Move?) {
|
||||
selectedMove = if (selectedMove == move || move == null) null else move
|
||||
descriptionScrollList.setMoveDescription(selectedMove?.description ?: "".text())
|
||||
descriptionScrollList.setText(selectedMove?.description ?: "".text())
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.getMemorySafely
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
@@ -32,23 +29,12 @@ object FleeFromAttackerTask {
|
||||
Trigger { _, entity, _ ->
|
||||
val hurtByEntity = it.get(hurtByEntity)
|
||||
val avoidTarget = it.tryGet(avoidTarget).orElse(null)
|
||||
|
||||
if (avoidTarget != null && avoidTarget == hurtByEntity) {
|
||||
if (avoidTarget != null && avoidTarget == hurtByEntity.uuid) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val avoidDurationTicks = mainThreadRuntime.resolveInt(avoidDurationTicks)
|
||||
|
||||
val pokemonEntity = entity as? PokemonEntity
|
||||
pokemonEntity?.let {
|
||||
it.after(1.0f) {
|
||||
it.playMoodParticle("mood_stress")
|
||||
}
|
||||
}
|
||||
|
||||
entity.brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, hurtByEntity, avoidDurationTicks.toLong())
|
||||
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.entity.ai
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.behavior.OneShot
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
@@ -25,16 +24,10 @@ object GetAngryAtAttackerTask {
|
||||
Trigger { _, entity, _ ->
|
||||
val hurtByEntity = it.get(hurtByEntity)
|
||||
val angryAt = it.tryGet(angryAt).orElse(null)
|
||||
|
||||
if (angryAt != null && angryAt == hurtByEntity.uuid) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
val becomingAngry = angryAt == null
|
||||
entity.brain.setMemory(MemoryModuleType.ANGRY_AT, hurtByEntity.uuid)
|
||||
if (becomingAngry) {
|
||||
(entity as PokemonEntity?)?.playMoodParticle("mood_anger_steam")
|
||||
}
|
||||
return@Trigger true
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -47,6 +47,7 @@ import com.cobblemon.mod.common.net.messages.client.battle.BattleCaptureStartPac
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.PokemonMetData
|
||||
import com.cobblemon.mod.common.pokemon.ai.PokemonBrain
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.util.*
|
||||
@@ -74,6 +75,9 @@ import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.EntityHitResult
|
||||
import net.minecraft.world.phys.HitResult
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
import java.util.Date
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragModifier, Schedulable {
|
||||
@@ -360,6 +364,12 @@ class EmptyPokeBallEntity : ThrowableItemProjectile, PosableEntity, WaterDragMod
|
||||
party.add(pokemon.pokemon)
|
||||
val leashHolder = pokemon.leashHolder
|
||||
|
||||
pokemon.pokemon.metData = PokemonMetData(
|
||||
this.level().getBiome(this.blockPosition()),
|
||||
LocalDate.now(ZoneId.systemDefault()),
|
||||
pokemon.pokemon.level
|
||||
)
|
||||
|
||||
if (leashHolder != null) {
|
||||
val blockPos = leashHolder.blockPosition()
|
||||
val blockState = level().getBlockState(blockPos)
|
||||
|
||||
@@ -34,9 +34,6 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addPokemonFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
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.net.serializers.PlatformTypeDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.RideBoostsDataSerializer
|
||||
@@ -428,9 +425,6 @@ open class PokemonEntity(
|
||||
|
||||
var occupiedSeats = mutableMapOf<Seat, Entity>()
|
||||
|
||||
var moodParticleLock = false
|
||||
var playedZeroStaminaParticle = false
|
||||
|
||||
init {
|
||||
delegate.initialize(this)
|
||||
delegate.changePokemon(pokemon)
|
||||
@@ -910,27 +904,6 @@ open class PokemonEntity(
|
||||
return future
|
||||
}
|
||||
|
||||
fun playMoodParticle(particleName: String) {
|
||||
if (moodParticleLock) return
|
||||
|
||||
val actionEffect = ActionEffects.actionEffects[cobblemonResource(particleName)] ?: return
|
||||
|
||||
cry()
|
||||
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
providers = mutableListOf(UsersProvider(this)),
|
||||
runtime = runtime,
|
||||
level = level()
|
||||
)
|
||||
actionEffect.run(context)
|
||||
|
||||
moodParticleLock = true
|
||||
after(5.0f) {
|
||||
moodParticleLock = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveWithoutId(nbt: CompoundTag): CompoundTag {
|
||||
val tethering = this.tethering
|
||||
if (tethering != null) {
|
||||
@@ -2342,8 +2315,6 @@ open class PokemonEntity(
|
||||
ifRidingAvailable { _, _, state ->
|
||||
state.stamina.set(entityData.get(RIDE_STAMINA))
|
||||
}
|
||||
|
||||
playedZeroStaminaParticle = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2372,26 +2343,12 @@ open class PokemonEntity(
|
||||
|
||||
override fun tickRidden(driver: Player, movementInput: Vec3) {
|
||||
super.tickRidden(driver, movementInput)
|
||||
|
||||
ifRidingAvailable { behaviour, settings, state ->
|
||||
behaviour.tick(settings, state, this, driver, movementInput)
|
||||
if (entityData.get(RIDE_STAMINA) == -1F) {
|
||||
state.stamina.set(1F, forced = true)
|
||||
}
|
||||
|
||||
if (!level().isClientSide) {
|
||||
val stamina = state.stamina.get()
|
||||
|
||||
if (stamina <= 0f) {
|
||||
if (!playedZeroStaminaParticle) {
|
||||
playMoodParticle("mood_stress")
|
||||
playedZeroStaminaParticle = true
|
||||
}
|
||||
} else {
|
||||
playedZeroStaminaParticle = false
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.level().isClientSide) {
|
||||
val pose = behaviour.pose(settings, state, this)
|
||||
if (pose != this.entityData.get(POSE_TYPE)) {
|
||||
|
||||
-5
@@ -44,11 +44,6 @@ class DefendOwnerSensor : Sensor<PokemonEntity>(10) {
|
||||
return@findClosest false
|
||||
}.map { mob -> mob as LivingEntity }
|
||||
|
||||
val previousAttacker = entity.brain.getMemorySafely(CobblemonMemories.NEAREST_VISIBLE_ATTACKER)
|
||||
val isNewAttacker = nearestAttacker.isPresent && previousAttacker.isEmpty
|
||||
entity.brain.setMemory(CobblemonMemories.NEAREST_VISIBLE_ATTACKER, nearestAttacker)
|
||||
if (isNewAttacker) {
|
||||
entity.playMoodParticle("mood_anger_steam")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-6
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.entity.pokemon.ai.tasks
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.getMemorySafely
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.ai.behavior.OneShot
|
||||
@@ -61,12 +60,7 @@ object AttackHostileMobsTask {
|
||||
}
|
||||
|
||||
if (hostile != null) {
|
||||
val isNewTarget = currentTarget == null
|
||||
entity.brain.setMemory(MemoryModuleType.ATTACK_TARGET, hostile)
|
||||
if (isNewTarget) {
|
||||
(entity as? PokemonEntity)?.playMoodParticle("mood_anger_steam")
|
||||
}
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ class EatHeldItemTask(entity: PokemonEntity) : Behavior<PokemonEntity>(
|
||||
}
|
||||
this.timelastEaten = time
|
||||
if (itemConfig != null && itemConfig.fullnessValue > 0) {
|
||||
entity.pokemon.feedPokemon(itemConfig.fullnessValue, false, false)
|
||||
entity.pokemon.feedPokemon(itemConfig.fullnessValue, false)
|
||||
}
|
||||
// Check if the result item is something that should be dropped
|
||||
resultItemStack = entity.pokemon.heldItem()
|
||||
|
||||
@@ -13,9 +13,7 @@ import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.client.pot.CookingQuality
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@@ -94,9 +92,7 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
val boosts = getBoosts(stack)
|
||||
pokemon.addRideBoosts(boosts.mapValues { it.value.toFloat() })
|
||||
|
||||
@@ -96,9 +96,8 @@ class PokePuffItem : Item(Properties().stacksTo(64)), PokemonSelectingItem {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
if (!pokemon.feedPokemon(4)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
// Feed the Pokémon 4 fullness points
|
||||
pokemon.feedPokemon(4)
|
||||
|
||||
val friendshipChange = PokePuffUtils.calculateFriendshipChange(stack, pokemon.nature)
|
||||
|
||||
|
||||
+6
-8
@@ -54,16 +54,14 @@ class FriendshipRaisingBerryItem(block: BerryBlock, val stat: Stat) : BerryItem(
|
||||
val evLowerAmount = max(genericRuntime.resolveInt(CobblemonMechanics.berries.evLowerAmount), 0)
|
||||
val decreasedEVs = pokemon.evs.add(stat, -evLowerAmount, ItemEvSource(player, stack, pokemon)) != 0
|
||||
|
||||
if (!increasedFriendship && !decreasedEVs) {
|
||||
return InteractionResultHolder.pass(stack)
|
||||
}
|
||||
return if (increasedFriendship || decreasedEVs) {
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
stack.consume(1, player)
|
||||
InteractionResultHolder.success(stack)
|
||||
} else {
|
||||
InteractionResultHolder.pass(stack)
|
||||
}
|
||||
|
||||
stack.consume(1, player)
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
@@ -54,10 +54,7 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> ExpressionLike): Ber
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
pokemon.feedPokemon(1)
|
||||
pokemon.currentHealth = Integer.min(pokemon.currentHealth + genericRuntime.resolveInt(amount(), pokemon), pokemon.maxHealth)
|
||||
stack.consume(1, player)
|
||||
return InteractionResultHolder.success(stack)
|
||||
@@ -65,7 +62,7 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> ExpressionLike): Ber
|
||||
|
||||
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
|
||||
super.applyToBattlePokemon(player, stack, battlePokemon)
|
||||
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
|
||||
battlePokemon.originalPokemon.feedPokemon(1)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
@@ -48,26 +48,21 @@ class PPRestoringBerryItem(block: BerryBlock, val amount: () -> ExpressionLike):
|
||||
&& super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon, move: Move) {
|
||||
if (!canUseOnPokemon(stack, pokemon) && canUseOnMove(stack, move)) {
|
||||
return
|
||||
}
|
||||
if (canUseOnPokemon(stack, pokemon) && canUseOnMove(stack, move)) {
|
||||
pokemon.feedPokemon(1)
|
||||
val moveToRecover = pokemon.moveSet.find { it.template == move.template }
|
||||
if (moveToRecover != null && moveToRecover.currentPp < moveToRecover.maxPp) {
|
||||
moveToRecover.currentPp =
|
||||
min(moveToRecover.maxPp, moveToRecover.currentPp + genericRuntime.resolveInt(amount(), pokemon))
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return
|
||||
}
|
||||
|
||||
val moveToRecover = pokemon.moveSet.find { it.template == move.template }
|
||||
if (moveToRecover != null && moveToRecover.currentPp < moveToRecover.maxPp) {
|
||||
moveToRecover.currentPp =
|
||||
min(moveToRecover.maxPp, moveToRecover.currentPp + genericRuntime.resolveInt(amount(), pokemon))
|
||||
|
||||
stack.consume(1, player)
|
||||
stack.consume(1, player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon, move: Move) {
|
||||
super.applyToBattlePokemon(player, stack, battlePokemon, move)
|
||||
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
|
||||
battlePokemon.originalPokemon.feedPokemon(1)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
+2
-4
@@ -59,9 +59,7 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
|
||||
}
|
||||
|
||||
// count these berries as multiple feedings due to the amount they heal
|
||||
if (!pokemon.feedPokemon(5)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
pokemon.feedPokemon(5)
|
||||
|
||||
var amount = Integer.min(pokemon.currentHealth + (genericRuntime.resolveFloat(portion(), pokemon) * pokemon.maxHealth).toInt(), pokemon.maxHealth)
|
||||
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(pokemon, amount, this), { cancelledEvent -> return InteractionResultHolder.fail(stack)}) { event ->
|
||||
@@ -75,7 +73,7 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
|
||||
|
||||
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
|
||||
super.applyToBattlePokemon(player, stack, battlePokemon)
|
||||
battlePokemon.originalPokemon.feedPokemon(5, playMoodParticle = false)
|
||||
battlePokemon.originalPokemon.feedPokemon(5)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
+8
-12
@@ -58,23 +58,19 @@ class StatusCuringBerryItem(block: BerryBlock, vararg val status: Status): Berry
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
return if (canUseOnPokemon(stack, pokemon)) {
|
||||
pokemon.feedPokemon(1)
|
||||
pokemon.status = null
|
||||
stack.consume(1, player)
|
||||
InteractionResultHolder.success(stack)
|
||||
} else {
|
||||
InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
pokemon.status = null
|
||||
stack.consume(1, player)
|
||||
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
|
||||
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
|
||||
super.applyToBattlePokemon(player, stack, battlePokemon)
|
||||
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
|
||||
battlePokemon.originalPokemon.feedPokemon(1)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
@@ -53,10 +53,7 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
var amount = Integer.min(pokemon.currentHealth + 20, pokemon.maxHealth)
|
||||
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(pokemon, amount, this), { cancelledEvent -> return InteractionResultHolder.fail(stack)}) { event ->
|
||||
@@ -77,9 +74,7 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
|
||||
|
||||
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
|
||||
super.applyToBattlePokemon(player, stack, battlePokemon)
|
||||
|
||||
battlePokemon.originalPokemon.feedPokemon(1, playMoodParticle = false)
|
||||
|
||||
battlePokemon.originalPokemon.feedPokemon(1)
|
||||
if (!player.hasInfiniteMaterials()) {
|
||||
val woodenBowlItemStack = ItemStack(Items.BOWL)
|
||||
if (!player.inventory.add(woodenBowlItemStack)) {
|
||||
|
||||
+1
-3
@@ -33,9 +33,7 @@ class FreshStartMochiItem : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
pokemon.evs.forEach {
|
||||
pokemon.setEV(it.key, 0)
|
||||
|
||||
@@ -27,9 +27,7 @@ class MochiItem(override val stat: Stat): CobblemonItem(Properties()), EVIncreas
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
if (!pokemon.feedPokemon(1)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
return super.applyToPokemon(player, stack, pokemon)
|
||||
}
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.cobblemon.mod.common.net.messages.client.pokemon.update
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.PokemonMetData
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
class MetDataUpdatePacket(pokemon: () -> Pokemon?, value: PokemonMetData): SingleUpdatePacket<PokemonMetData, MetDataUpdatePacket>(pokemon, value) {
|
||||
override val id = ID
|
||||
|
||||
override fun encodeValue(buffer: RegistryFriendlyByteBuf) {
|
||||
val biome = value.biome.unwrapKey().getOrNull()
|
||||
?: ResourceKey.create(Registries.BIOME, ResourceLocation.parse("minecraft:plains"))
|
||||
buffer.writeResourceKey(biome)
|
||||
buffer.writeLong(value.date.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli())
|
||||
buffer.writeInt(value.level)
|
||||
}
|
||||
|
||||
override fun set(
|
||||
pokemon: Pokemon,
|
||||
value: PokemonMetData
|
||||
) {
|
||||
pokemon.metData = value
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("met_data_update")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): MetDataUpdatePacket {
|
||||
val pokemon = decodePokemon(buffer)
|
||||
val biomeKey = buffer.readResourceKey(Registries.BIOME)
|
||||
val dateTime = buffer.readLong()
|
||||
val date = Instant.ofEpochMilli(dateTime).atZone(ZoneId.systemDefault()).toLocalDate()
|
||||
val level = buffer.readInt()
|
||||
val biome = buffer.registryAccess().lookupOrThrow(Registries.BIOME).getOrThrow(biomeKey)
|
||||
return MetDataUpdatePacket(pokemon, PokemonMetData(biome, date, level))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -550,6 +550,12 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
onChange(OriginalTrainerUpdatePacket({ this }, value))
|
||||
}
|
||||
|
||||
var metData: PokemonMetData? = null
|
||||
set(value) {
|
||||
field = value
|
||||
value?.let { onChange(MetDataUpdatePacket({ this }, it)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache friendship on trade for OT
|
||||
*/
|
||||
@@ -991,10 +997,6 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
this.recall()
|
||||
}
|
||||
|
||||
fun playMoodParticle(particleName: String) {
|
||||
entity?.playMoodParticle(particleName)
|
||||
}
|
||||
|
||||
fun heal() {
|
||||
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(this)) { event ->
|
||||
this.currentHealth = maxHealth
|
||||
@@ -1066,13 +1068,23 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
else -> 0 // For weights less than 0.1
|
||||
}
|
||||
|
||||
fun feedPokemon(feedCount: Int, playSound: Boolean = true, playMoodParticle: Boolean = true): Boolean {
|
||||
playFullnessEffects(playSound, playMoodParticle)
|
||||
fun feedPokemon(feedCount: Int, playSound: Boolean = true) {
|
||||
// play sounds from the entity first (itemstack is consumed outside of this function)
|
||||
if (this.entity != null && playSound) {
|
||||
val fullnessPercent = ((this.currentFullness).toFloat() / (this.getMaxFullness()).toFloat()) * (.5f)
|
||||
|
||||
if (this.currentFullness >= this.getMaxFullness()) {
|
||||
this.entity?.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
this.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
}
|
||||
|
||||
// if it is already full we don't need to do anything
|
||||
// TODO this can happen when feeding in battle since we are temporarily ignoring fullness checks for pp/hp/status berries
|
||||
if (isFull()) {
|
||||
return false
|
||||
return
|
||||
}
|
||||
|
||||
this.currentFullness = (this.currentFullness + feedCount).coerceIn(0, this.getMaxFullness())
|
||||
@@ -1081,31 +1093,6 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
if (this.currentFullness == 1) {
|
||||
this.resetMetabolismCycle()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun playFullnessEffects(playSound: Boolean = true, playMoodParticle: Boolean = true) {
|
||||
if (!playSound && !playMoodParticle) return
|
||||
|
||||
val pokemonEntity = entity ?: return
|
||||
val fullnessPercent = ((this.currentFullness).toFloat() / (this.getMaxFullness()).toFloat()) * (.5f)
|
||||
|
||||
if (!isFull()) {
|
||||
if (playSound) {
|
||||
pokemonEntity.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (playSound) {
|
||||
pokemonEntity.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
|
||||
if (playMoodParticle) {
|
||||
pokemonEntity.playMoodParticle("mood_annoyed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// decrease a pokemon's Fullness value by a certain amount
|
||||
@@ -1546,6 +1533,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
this.potentialMarks.clear()
|
||||
this.potentialMarks += other.marks
|
||||
this.markings = other.markings
|
||||
this.metData = other.metData
|
||||
this.recalculateCharacteristic()
|
||||
this.updateAspects()
|
||||
this.refreshOriginalTrainer()
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.cobblemon.mod.common.pokemon
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import java.time.LocalDate
|
||||
|
||||
/**
|
||||
* Stores information about the circumstances of a player's meeting with a [Pokemon]
|
||||
*
|
||||
* @param biome A [Holder] for the [Biome] the [Pokemon] was caught in
|
||||
* @param date A [LocalDate] of the real life date the [Pokemon] was caught
|
||||
* @param level The level the [Pokemon] was when caught
|
||||
*/
|
||||
data class PokemonMetData(
|
||||
val biome: Holder<Biome>,
|
||||
val date: LocalDate,
|
||||
val level: Int
|
||||
) {
|
||||
companion object {
|
||||
private val LOCAL_DATE_CODEC: Codec<LocalDate> = Codec.STRING.xmap(
|
||||
LocalDate::parse,
|
||||
LocalDate::toString
|
||||
)
|
||||
|
||||
val CODEC: Codec<PokemonMetData> = RecordCodecBuilder.create { instance ->
|
||||
instance.group(
|
||||
Biome.CODEC
|
||||
.fieldOf("biome")
|
||||
.forGetter { it.biome },
|
||||
LOCAL_DATE_CODEC
|
||||
.fieldOf("date")
|
||||
.forGetter { it.date },
|
||||
Codec.INT
|
||||
.fieldOf("level")
|
||||
.forGetter { it.level }
|
||||
).apply(instance) { biome, date, level ->
|
||||
PokemonMetData(
|
||||
biome = biome,
|
||||
date = date,
|
||||
level = level
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,7 @@ object DataKeys {
|
||||
const val POKEMON_ORIGINAL_TRAINER_NAME = "PokemonOriginalTrainerName"
|
||||
const val POKEMON_ORIGINAL_TRAINER_TYPE = "PokemonOriginalTrainerType"
|
||||
const val POKEMON_ORIGINAL_TRAINER_FRIENDSHIP = "PokemonOriginalTrainerFriendship"
|
||||
const val POKEMON_MET_DATA = "PokemonMetData"
|
||||
|
||||
const val POKEMON_PROPERTIES_MOVES = "Moves"
|
||||
const val POKEMON_PROPERTIES_HELDITEM = "HeldItem"
|
||||
|
||||
+13
-9
@@ -8,25 +8,23 @@
|
||||
|
||||
package com.cobblemon.mod.common.util.codec.internal
|
||||
|
||||
import com.cobblemon.mod.common.api.mark.Marks
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.client.settings.ServerSettings
|
||||
import com.cobblemon.mod.common.pokemon.OriginalTrainerType
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.PokemonMetData
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import java.util.*
|
||||
|
||||
internal data class ClientPokemonP4(
|
||||
val originalTrainerFriendship: Optional<Int>
|
||||
val originalTrainerFriendship: Optional<Int>,
|
||||
val pokemonMetData: Optional<PokemonMetData>
|
||||
) : Partial<Pokemon> {
|
||||
|
||||
override fun into(other: Pokemon): Pokemon {
|
||||
this.originalTrainerFriendship.ifPresent { other.originalTrainerFriendship = it }
|
||||
other.metData = this.pokemonMetData.orElse(null)
|
||||
return other
|
||||
}
|
||||
|
||||
@@ -36,12 +34,18 @@ internal data class ClientPokemonP4(
|
||||
*/
|
||||
internal val CODEC: MapCodec<ClientPokemonP4> = RecordCodecBuilder.mapCodec { instance ->
|
||||
instance.group(
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(ClientPokemonP4::originalTrainerFriendship)
|
||||
).apply(instance, ::ClientPokemonP4)
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(ClientPokemonP4::originalTrainerFriendship),
|
||||
PokemonMetData.CODEC.optionalFieldOf(DataKeys.POKEMON_MET_DATA).forGetter(ClientPokemonP4::pokemonMetData)
|
||||
).apply(instance) {
|
||||
originalTrainerFriendship, pokemonMetData -> ClientPokemonP4(
|
||||
originalTrainerFriendship, pokemonMetData
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun from(pokemon: Pokemon): ClientPokemonP4 = ClientPokemonP4(
|
||||
Optional.ofNullable(pokemon.originalTrainerFriendship)
|
||||
Optional.ofNullable(pokemon.originalTrainerFriendship),
|
||||
Optional.ofNullable(pokemon.metData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.util.codec.internal
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.PokemonMetData
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
@@ -16,28 +17,32 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.*
|
||||
|
||||
internal data class PokemonP4(
|
||||
val originalTrainerFriendship: Optional<Int>
|
||||
val originalTrainerFriendship: Optional<Int>,
|
||||
val pokemonMetData: Optional<PokemonMetData>
|
||||
) : Partial<Pokemon> {
|
||||
|
||||
override fun into(other: Pokemon): Pokemon {
|
||||
this.originalTrainerFriendship.ifPresent { other.originalTrainerFriendship = it }
|
||||
other.refreshOriginalTrainer()
|
||||
other.metData = this.pokemonMetData.orElse(null)
|
||||
return other
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal val CODEC: MapCodec<PokemonP4> = RecordCodecBuilder.mapCodec { instance ->
|
||||
instance.group(
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(PokemonP4::originalTrainerFriendship)
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(PokemonP4::originalTrainerFriendship),
|
||||
PokemonMetData.CODEC.optionalFieldOf(DataKeys.POKEMON_MET_DATA).forGetter(PokemonP4::pokemonMetData)
|
||||
).apply(instance) {
|
||||
originalTrainerFriendship -> PokemonP4(
|
||||
originalTrainerFriendship
|
||||
originalTrainerFriendship, pokemonMetData -> PokemonP4(
|
||||
originalTrainerFriendship, pokemonMetData
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun from(pokemon: Pokemon): PokemonP4 = PokemonP4(
|
||||
Optional.ofNullable(pokemon.originalTrainerFriendship)
|
||||
Optional.ofNullable(pokemon.originalTrainerFriendship),
|
||||
Optional.ofNullable(pokemon.metData)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:mood_anger_steam",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/mood/steam_center_double"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, "math.clamp((v.entity_radius*1.2),0.48,0.96)*0.75", 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["math.clamp((v.entity_radius*1.5),0.9,2.4)", "math.clamp((v.entity_radius*0.5),0.3,0.8)"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 48,
|
||||
"texture_height": 176,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [48, 16],
|
||||
"step_UV": [0, 16],
|
||||
"max_frame": 11,
|
||||
"stretch_to_lifetime": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:mood_anger_veins",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/mood/vein_red"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_initialization": {
|
||||
"creation_expression": "v.particle_size = math.clamp((v.entity_radius*0.75),0.15,0.4);"
|
||||
},
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"direction": ["math.random(-1,1)", 1.5, "math.random(-1,1)"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1.25
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(-1,2)*90"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "v.particle_size*13",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, 0.75, 0],
|
||||
"linear_drag_coefficient": "v.particle_size*15"
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["math.clamp((v.entity_radius*0.75),0.15,0.3)", "math.clamp((v.entity_radius*0.75),0.15,0.3)"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 22,
|
||||
"texture_height": 11,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [11, 11],
|
||||
"step_UV": [11, 0],
|
||||
"frames_per_second": 6,
|
||||
"max_frame": 2,
|
||||
"loop": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_motion_collision": {},
|
||||
"minecraft:particle_appearance_lighting": {},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age/v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.86": "#ffffffff",
|
||||
"1.0": "#FF000000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:mood_annoyed",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/mood/scribble_purple"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_initialization": {
|
||||
"creation_expression": "v.particle_size = math.clamp((v.entity_radius*0.75),0.2,0.5);"
|
||||
},
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 2
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"direction": [0, 1, 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 1
|
||||
},
|
||||
"minecraft:particle_initial_speed": "v.particle_size*10",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 3
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["math.clamp((v.entity_radius*0.75),0.2,0.5)", "math.clamp((v.entity_radius*0.75),0.2,0.5)"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 168,
|
||||
"texture_height": 14,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [14, 14],
|
||||
"step_UV": [14, 0],
|
||||
"frames_per_second": 10,
|
||||
"max_frame": 12
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_lighting": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:mood_stress",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/mood/sweat_blue"
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_initialization": {
|
||||
"creation_expression": "v.particle_height = math.clamp((v.entity_radius*1.2),0.48,0.96);"
|
||||
},
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_looping": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, "math.clamp((v.entity_radius*1.2),0.48,0.96)*0.75", 0]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.45
|
||||
},
|
||||
"minecraft:particle_initial_speed": 0,
|
||||
"minecraft:particle_motion_dynamic": {},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["math.clamp((v.entity_radius*1.2),0.48,0.96)", "math.clamp((v.entity_radius*0.65),0.26,0.52)"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 216,
|
||||
"texture_height": 13,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [24, 13],
|
||||
"step_UV": [24, 0],
|
||||
"max_frame": 9,
|
||||
"stretch_to_lifetime": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_lighting": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1267,6 +1267,8 @@
|
||||
"cobblemon.ui.info.ability": "Ability",
|
||||
"cobblemon.ui.info.experience_points": "Exp. Points",
|
||||
"cobblemon.ui.info.to_next_level": "To Next Lv.",
|
||||
"cobblemon.ui.info.met_data": "Met in %1$s on %2$s/%3$s/%4$s at Lv.%5$s",
|
||||
"cobblemon.ui.info.met_data_unavailable": "Met a long time ago",
|
||||
"cobblemon.ui.trade": "Trade",
|
||||
"cobblemon.trade.expired.sender": "Your request to trade with %1$s has timed out!",
|
||||
"cobblemon.trade.expired.receiver": "The trade request from %1$s has timed out!",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 979 B |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 744 B |
Binary file not shown.
|
Before Width: | Height: | Size: 589 B |
Binary file not shown.
|
Before Width: | Height: | Size: 290 B |
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"timeline": [
|
||||
{
|
||||
"type": "entity_particles",
|
||||
"effect": "cobblemon:mood_anger_steam",
|
||||
"locators": ["head", "top"]
|
||||
},
|
||||
{
|
||||
"type": "loop",
|
||||
"condition": "q.entity.has_memory_value('minecraft:angry_at') || q.entity.has_memory_value('minecraft:attack_target') || q.entity.has_memory_value('cobblemon:nearest_visible_attacker')",
|
||||
"keyframe": {
|
||||
"type": "sequence",
|
||||
"keyframes": [
|
||||
{
|
||||
"type": "entity_particles",
|
||||
"effect": "cobblemon:mood_anger_veins",
|
||||
"locators": ["head", "top"]
|
||||
},
|
||||
{
|
||||
"type": "pause",
|
||||
"pause": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"timeline": [
|
||||
{
|
||||
"type": "entity_particles",
|
||||
"effect": "cobblemon:mood_annoyed",
|
||||
"locators": ["head", "top"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"timeline": [
|
||||
{
|
||||
"type": "entity_particles",
|
||||
"effect": "cobblemon:mood_stress",
|
||||
"locators": ["head", "top"]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user