Compare commits

...
Author SHA1 Message Date
jeffw773 4590d95711 - Magikarp now gains tiny "Jump Power" when fed (does not cap how high it can be) 2023-11-21 13:42:56 -08:00
jeffw773 af969d7f85 - Camerupt -> Lava Bucket (1 in-game days)
- Vespiqueen -> Honey Bottle (1 in-game day)
- Miltank -> MooMoo Milk (1 in-game day)
2023-11-21 13:22:46 -08:00
jeffw773 c325dfd724 - Miltank gives MooMoo Milks when player has glass bottle (every 15mins)
- Shuckle Berry Juice Meter working
2023-11-21 10:47:43 -08:00
jeffw773 0996a20ebf Merge remote-tracking branch 'origin/pokemon_with_full_bellies' into pokemon_with_full_bellies 2023-11-21 10:20:47 -08:00
jeffw773 bc58f8ea59 - Added special Berry Juice meter for Shuckle 2023-11-21 10:20:30 -08:00
Lily dc9d285e45 add moomoo milk 2023-11-21 18:02:50 +00:00
jeffw773 2cf879a769 - Added special Berry Juice meter for Shuckle 2023-11-20 22:54:44 -08:00
jeffw773 9051a45add - Added some new ways to "milk" pokemon
- Camerupt -> Lava Bucket
- Combee / Vespiqueen -> Honey Bottle
- Female Gogoat / Female Bouffalant -> Milk Bucket
2023-11-20 20:53:35 -08:00
jeffw773 0ca248a599 - Fixed Metabolism rate math 2023-11-20 12:24:49 -08:00
jeffw773 3d527d2def - Default minimum metabolism cycle is 1 minute 2023-11-20 08:52:59 -08:00
jeffw773 ee90e82cc1 - Shuckle creates Berry Juice held item after it loses 1 fullness and has no held item slot anymore
- Pokemon lose 2 fullness after sleeping
- Pokemon lose 1 fullness after battle end
- Pokemon fullness and metabolism changed to new formulas
- added fix to Battle UI to be on par with main branch (for better testing)
2023-11-20 08:49:22 -08:00
jeffw773 6c1bf7381b - Pokemon lose 75% fullness when player sleeps 2023-11-15 17:07:47 -08:00
MoeBoy76 b20dc93fdf decrease fullness for all remaining active Pokémon after a Pokémon faints 2023-11-15 16:24:09 +11:00
jeffw773 ee03c477cc - Metabolism tweaked so slowest pokemon takes 8 mins to lose 1 fullness 2023-11-14 19:58:53 -08:00
jeffw773 f296d1f945 - Metabolism is working now (Faster mons lose fullness faster than slower mons)
- Pitch of the berry eating sound increases slightly as the pokemon gets more Full
- Extra sound added that plays when a Pokemon is full or overfed
2023-11-14 15:41:51 -08:00
jeffw773 64a930aadb - Changed all berries and Berry Juice to count as food that give certain levels of fullness to Pokemon.
- All Pokemon have a unique MaxFullness value that is scaled off their base HP stat
2023-11-14 00:10:48 -08:00
jeffw773 5c6d0bc372 Added a Fullness aspect to Pokemon for adding a limit to how much food they can be given in a specified amount of time 2023-11-12 20:40:14 -08:00
23 changed files with 510 additions and 29 deletions

No files matched your search

@@ -16,11 +16,13 @@ import com.cobblemon.mod.common.api.data.DataProvider
import com.cobblemon.mod.common.api.drop.CommandDropEntry
import com.cobblemon.mod.common.api.drop.DropEntry
import com.cobblemon.mod.common.api.drop.ItemDropEntry
import com.cobblemon.mod.common.api.events.CobblemonEvents.BATTLE_FAINTED
import com.cobblemon.mod.common.api.events.CobblemonEvents.BATTLE_VICTORY
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
import com.cobblemon.mod.common.api.events.CobblemonEvents.EVOLUTION_COMPLETE
import com.cobblemon.mod.common.api.events.CobblemonEvents.LEVEL_UP_EVENT
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_CAPTURED
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_FAINTED
import com.cobblemon.mod.common.api.events.CobblemonEvents.TRADE_COMPLETED
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
@@ -79,6 +81,7 @@ import com.cobblemon.mod.common.config.constraint.IntConstraint
import com.cobblemon.mod.common.config.starter.StarterConfig
import com.cobblemon.mod.common.data.CobblemonDataProvider
import com.cobblemon.mod.common.events.AdvancementHandler
import com.cobblemon.mod.common.events.BellyHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.item.PokeBallItem
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
@@ -366,6 +369,9 @@ object Cobblemon {
LEVEL_UP_EVENT.subscribe { AdvancementHandler.onLevelUp(it) }
TRADE_COMPLETED.subscribe { AdvancementHandler.onTradeCompleted(it) }
//BATTLE_FAINTED.subscribe { BellyHandler.onFaint(it) }
BATTLE_VICTORY.subscribe { BellyHandler.onVictory(it) }
BagItems.observable.subscribe {
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
battleRegistry.startBattle(
@@ -368,6 +368,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val SUPERB_REMEDY = create("superb_remedy", RemedyItem(RemedyItem.SUPERB))
@JvmField
val MOOMOO_MILK = create("moomoo_milk", Item(Item.Settings()))
@JvmField
val POTION = create("potion", PotionItem(PotionType.POTION))
@JvmField
@@ -692,6 +695,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
return item
}
private fun candyItem(name: String, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(calculator))
private fun heldItem(name: String, remappedName: String? = null): CobblemonItem = create(
@@ -82,6 +82,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, RegistryKey<Regi
val BERRY_HARVEST = this.create("berry.harvest")
@JvmField
val BERRY_EAT = this.create("berry.eat")
@JvmField
val BERRY_EAT_FULL = this.create("berry.eat.full")
@JvmField
val MULCH_PLACE = this.create("mulch.place")
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.advancement.CobblemonCriteria
import com.cobblemon.mod.common.advancement.criterion.PokemonInteractContext
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.callback.PartySelectCallbacks
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.battles.BagItemActionResponse
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
@@ -131,8 +132,19 @@ interface PokemonSelectingItem {
canSelect = ::canUseOnPokemon,
handler = { pk ->
if (stack.isHeld(player)) {
applyToPokemon(player, stack, pk)
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, Registries.ITEM.getId(stack.item)))
if (stack.isIn(CobblemonItemTags.POKE_FOOD)) {
if (!pk.isFull()) {
//pk.feedPokemon()
applyToPokemon(player, stack, pk)
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, Registries.ITEM.getId(stack.item)))
}
// If the pokemon is full then it will not hit the above if statement and it will skip over the else statement below
}
else {
applyToPokemon(player, stack, pk)
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, Registries.ITEM.getId(stack.item)))
}
}
}
)
@@ -96,6 +96,8 @@ object CobblemonItemTags {
val CONSUMED_IN_PVP_BATTLE = create("held/consumed_in_pvp_battle")
@JvmField
val CONSUMED_IN_WILD_BATTLE = create("held/consumed_in_wild_battle")
@JvmField
val POKE_FOOD = create("poke_food")
private fun create(path: String) = TagKey.of(RegistryKeys.ITEM, cobblemonResource(path))
@@ -1485,9 +1485,7 @@ object ShowdownInterpreter {
GO
}
}
privateMessage.pnxAndUuid(0)?.let { (pnx, _) -> {
battle.sendSidedUpdate(actor, BattleHealthChangePacket(pnx, remainingHealth.toFloat()), BattleHealthChangePacket(pnx, newHealthRatio))
}}
privateMessage.pnxAndUuid(0)?.let { (pnx, _) -> battle.sendSidedUpdate(actor, BattleHealthChangePacket(pnx, remainingHealth.toFloat()), BattleHealthChangePacket(pnx, newHealthRatio)) }
battle.minorBattleActions[battlePokemon.uuid] = privateMessage
WaitDispatch(1F)
@@ -8,11 +8,8 @@
package com.cobblemon.mod.common.entity.pokemon
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonEntities
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.*
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.drop.DropTable
import com.cobblemon.mod.common.api.entity.Despawner
import com.cobblemon.mod.common.api.events.CobblemonEvents
@@ -24,6 +21,7 @@ import com.cobblemon.mod.common.api.interaction.PokemonEntityInteraction
import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeature
import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.pokemon.status.Statuses
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
import com.cobblemon.mod.common.api.reactive.SimpleObservable
@@ -130,6 +128,9 @@ class PokemonEntity(
this.updateEyeHeight()
}
var despawner: Despawner<PokemonEntity> = Cobblemon.bestSpawner.defaultPokemonDespawner
/** The player that caused this Pokémon to faint. */
@@ -534,6 +535,9 @@ class PokemonEntity(
return property
}
override fun createChild(level: ServerWorld, partner: PassiveEntity) = null
override fun isReadyToSitOnPlayer(): Boolean {
@@ -556,6 +560,28 @@ class PokemonEntity(
player.setStackInHand(hand, milkBucket)
return ActionResult.success(world.isClient)
}
//Camerupt gives Lava Bucket if player uses Bucket on it
else if (pokemon.species.name == "Camerupt" && pokemon.lastMilked >= 900) {
player.playSound(SoundEvents.ENTITY_GOAT_MILK, 1.0f, 1.0f)
val lavaBucket = ItemUsage.exchangeStack(itemStack, player, Items.LAVA_BUCKET.defaultStack)
player.setStackInHand(hand, lavaBucket)
pokemon.milk()
return ActionResult.success(world.isClient)
}
//Gogoat gives Milk Bucket if player uses Bucket on it
else if (pokemon.species.name == "Gogoat" && pokemon.gender.name == "Female") {
player.playSound(SoundEvents.ENTITY_GOAT_MILK, 1.0f, 1.0f)
val milkBucket = ItemUsage.exchangeStack(itemStack, player, Items.MILK_BUCKET.defaultStack)
player.setStackInHand(hand, milkBucket)
return ActionResult.success(world.isClient)
}
//Bouffalant gives Milk Bucket if player uses Bucket on it
else if (pokemon.species.name == "Bouffalant" && pokemon.gender.name == "Female") {
player.playSound(SoundEvents.ENTITY_GOAT_MILK, 1.0f, 1.0f)
val milkBucket = ItemUsage.exchangeStack(itemStack, player, Items.MILK_BUCKET.defaultStack)
player.setStackInHand(hand, milkBucket)
return ActionResult.success(world.isClient)
}
} else if (itemStack.isOf(Items.BOWL)) {
if (pokemon.getFeature<FlagSpeciesFeature>(DataKeys.IS_MOOSHTANK) != null) {
player.playSound(SoundEvents.ENTITY_MOOSHROOM_MILK, 1.0f, 1.0f)
@@ -563,6 +589,30 @@ class PokemonEntity(
player.setStackInHand(hand, mushroomStew)
return ActionResult.success(world.isClient)
}
//Shuckle uses its Berry Juice meter to dispense Berry Juice if a player uses Wooden Bowl on it
else if (pokemon.species.name == "Shuckle" && pokemon.berryJuiceMeter > 0) {
player.playSound(SoundEvents.ENTITY_MOOSHROOM_MILK, 1.0f, 1.0f)
val berryJuice = ItemUsage.exchangeStack(itemStack, player, CobblemonItems.BERRY_JUICE.defaultStack)
player.setStackInHand(hand, berryJuice)
pokemon.getBerryJuice()
return ActionResult.success(world.isClient)
}
} else if (itemStack.isOf(Items.GLASS_BOTTLE)) {
if ((pokemon.species.name == "Vespiqueen") && pokemon.lastMilked >= 900) {
player.playSound(SoundEvents.ENTITY_GOAT_MILK, 1.0f, 1.0f)
val honeyBottle = ItemUsage.exchangeStack(itemStack, player, Items.HONEY_BOTTLE.defaultStack)
player.setStackInHand(hand, honeyBottle)
pokemon.milk()
return ActionResult.success(world.isClient)
}
//Miltank gives MooMoo Milk if player uses Glass Bottle on it
else if (pokemon.species.name == "Miltank" && pokemon.lastMilked >= 900) {
player.playSound(SoundEvents.ENTITY_MOOSHROOM_MILK, 1.0f, 1.0f)
val moomooMilk = ItemUsage.exchangeStack(itemStack, player, CobblemonItems.MOOMOO_MILK.defaultStack)
player.setStackInHand(hand, moomooMilk)
pokemon.milk()
return ActionResult.success(world.isClient)
}
}
if (hand == Hand.MAIN_HAND && player is ServerPlayerEntity && pokemon.getOwnerPlayer() == player) {
@@ -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.events
import com.cobblemon.mod.common.api.events.battles.BattleFaintedEvent
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
import com.cobblemon.mod.common.util.party
object BellyHandler {
fun onFaint(event : BattleFaintedEvent) {
event.battle.activePokemon.forEach() {
if(it.battlePokemon != event.killed) {
it.battlePokemon?.entity?.pokemon?.loseFullness(1)
}
}
}
fun onVictory(event : BattleVictoryEvent) {
event.battle.players.forEach() {
it.party().forEach() {
it.loseFullness(1)
}
}
// Redacted code which only made last 2 active pokemon lose fullness
/*event.battle.activePokemon.forEach() {
// every pokemon that took part in the battle loses 1 fullness
it.battlePokemon?.entity?.pokemon?.loseFullness(1)
}*/
}
}
@@ -28,6 +28,12 @@ object ServerTickHandler {
// Party tick
for (player in server.playerManager.playerList) {
player.party().onSecondPassed(player)
for (pokemon in player.party()) {
// only run on pokemon who have a fullness value above 0 to save on resources for the server
if (pokemon.currentFullness > 0 || pokemon.isMilkable(pokemon)) {
pokemon.onSecondPassed(player, pokemon)
}
}
}
}
}
@@ -48,11 +48,23 @@ class FriendshipRaisingBerryItem(block: BerryBlock, val stat: Stat) : BerryItem(
val currentStat = pokemon.evs.getOrDefault(stat)
val newEV = max(currentStat - genericRuntime.resolveInt(CobblemonMechanics.berries.evLowerAmount), 0)
pokemon.setEV(stat, newEV)
if (!pokemon.isFull()) {
pokemon.setEV(stat, newEV)
}
val decreasedEVs = currentStat != pokemon.evs.getOrDefault(stat)
return if (increasedFriendship || decreasedEVs) {
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
return if ((increasedFriendship || decreasedEVs) && !pokemon.isFull()) {
pokemon.feedPokemon(1)
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
player.playSound(CobblemonSounds.BERRY_EAT_FULL, SoundCategory.PLAYERS, 1F, 1F)
}
else {
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F + fullnessPercent)
}
if (!player.isCreative) {
stack.decrement(1)
}
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.item.BerryItem
@@ -25,6 +26,7 @@ import net.minecraft.item.ItemStack
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.server.world.ServerWorld
import net.minecraft.sound.SoundCategory
import net.minecraft.text.Text
import net.minecraft.util.Hand
import net.minecraft.util.TypedActionResult
import net.minecraft.world.World
@@ -48,12 +50,35 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> Expression): BerryIt
stack: ItemStack,
pokemon: Pokemon
): TypedActionResult<ItemStack>? {
if (pokemon.isFullHealth() || pokemon.isFainted()) {
if (pokemon.isFullHealth() || pokemon.isFainted() || pokemon.isFull()) {
if (pokemon.isFull()) {
val message = "${pokemon.species.name} has eaten ${pokemon.currentFullness}/${pokemon.getMaxFullness()} times. It is too full!"
player.sendMessage(Text.of(message))
}
else if (pokemon.isFullHealth()) {
val message = "${pokemon.species.name} is at Max HP already!"
player.sendMessage(Text.of(message))
}
return TypedActionResult.fail(stack)
}
pokemon.feedPokemon(1)
//var message = "Fullness for ${pokemon.species.name} is ${pokemon.currentFullness}. It can eat ${(pokemon.getMaxFullness() - pokemon.currentFullness)} more poke_food"
//player.sendMessage(Text.of(message))
pokemon.currentHealth = Integer.min(pokemon.currentHealth + genericRuntime.resolveInt(amount(), pokemon), pokemon.hp)
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
//message = "Pitch for Berry Food is at ${(fullnessPercent) + 1F}"
//player.sendMessage(Text.of(message))
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
player.playSound(CobblemonSounds.BERRY_EAT_FULL, SoundCategory.PLAYERS, 1F, 1F)
}
else {
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F + fullnessPercent)
}
if (!player.isCreative) {
stack.decrement(1)
}
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.item.PokemonAndMoveSelectingItem
import com.cobblemon.mod.common.api.moves.Move
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.item.BerryItem
@@ -47,12 +48,24 @@ class PPRestoringBerryItem(block: BerryBlock, val amount: () -> Expression): Ber
override fun canUseOnMove(move: Move) = move.currentPp < move.maxPp
override fun canUseOnPokemon(pokemon: Pokemon) = pokemon.moveSet.any(::canUseOnMove)
override fun applyToPokemon(player: ServerPlayerEntity, stack: ItemStack, pokemon: Pokemon, move: Move) {
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))
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
if (!player.isCreative) {
stack.decrement(1)
if (!pokemon.isFull()) {
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))
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
player.playSound(CobblemonSounds.BERRY_EAT_FULL, SoundCategory.PLAYERS, 1F, 1F)
}
else {
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F + fullnessPercent)
}
if (!player.isCreative) {
stack.decrement(1)
}
}
}
}
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.battles.model.PokemonBattle
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.block.BerryBlock
import com.cobblemon.mod.common.item.BerryItem
import com.cobblemon.mod.common.item.battle.BagItem
@@ -24,10 +25,12 @@ import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.sound.SoundCategory
import net.minecraft.text.Text
import net.minecraft.util.Hand
import net.minecraft.util.TypedActionResult
import net.minecraft.world.World
/**
* A berry that heals the Pokémon by some portion of their max HP.
*
@@ -50,12 +53,33 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
stack: ItemStack,
pokemon: Pokemon
): TypedActionResult<ItemStack>? {
if (pokemon.isFullHealth() || pokemon.isFainted()) {
if (pokemon.isFullHealth() || pokemon.isFainted() || pokemon.isFull()) {
if (pokemon.isFull()) {
val message = "${pokemon.species.name} has eaten ${pokemon.currentFullness}/${pokemon.getMaxFullness()} times. It is too full!"
player.sendMessage(Text.of(message))
}
else if (pokemon.isFullHealth()) {
val message = "${pokemon.species.name} is at Max HP already!"
player.sendMessage(Text.of(message))
}
return TypedActionResult.fail(stack)
}
// count these berries as multiple feedings due to the amount they heal
pokemon.feedPokemon(5)
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
pokemon.currentHealth = Integer.min(pokemon.currentHealth + (genericRuntime.resolveFloat(portion(), pokemon) * pokemon.hp).toInt(), pokemon.hp)
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
player.playSound(CobblemonSounds.BERRY_EAT_FULL, SoundCategory.PLAYERS, 1F, 1F)
}
else {
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F + fullnessPercent)
}
if (!player.isCreative) {
stack.decrement(1)
}
@@ -46,7 +46,8 @@ class StatusCuringBerryItem(block: BerryBlock, vararg val status: Status): Berry
pokemon: Pokemon
): TypedActionResult<ItemStack>? {
val currentStatus = pokemon.status?.status
return if (currentStatus != null && (status.isEmpty() || currentStatus in status)) {
return if (currentStatus != null && (status.isEmpty() || currentStatus in status) && !pokemon.isFull()) {
pokemon.feedPokemon(1)
pokemon.status = null
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
if (!player.isCreative) {
@@ -250,6 +250,8 @@ object CobblemonItemGroups {
entries.add(CobblemonItems.JOLLY_MINT)
entries.add(CobblemonItems.NAIVE_MINT)
entries.add(CobblemonItems.SERIOUS_MINT)
entries.add(CobblemonItems.MOOMOO_MILK)
}
private fun evolutionItemEntries(displayContext: DisplayContext, entries: Entries) {
@@ -45,11 +45,23 @@ class BerryJuiceItem : CobblemonItem(Settings()), PokemonSelectingItem {
stack: ItemStack,
pokemon: Pokemon
): TypedActionResult<ItemStack>? {
if (pokemon.isFullHealth()) {
if (pokemon.isFullHealth() || !pokemon.isFull()) {
return TypedActionResult.fail(stack)
}
pokemon.feedPokemon(1)
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
pokemon.currentHealth = Integer.min(pokemon.currentHealth + 20, pokemon.hp)
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F)
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
player.playSound(CobblemonSounds.BERRY_EAT_FULL, SoundCategory.PLAYERS, 1F, 1F)
}
else {
player.playSound(CobblemonSounds.BERRY_EAT, SoundCategory.PLAYERS, 1F, 1F + fullnessPercent)
}
if (!player.isCreative) {
stack.decrement(1)
val woodenBowlItemStack = ItemStack(Items.BOWL)
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.pokemon
import com.bedrockk.molang.runtime.struct.VariableStruct
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToPlayers
import com.cobblemon.mod.common.CobblemonSounds
import com.cobblemon.mod.common.api.abilities.Abilities
@@ -48,6 +49,7 @@ import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
import com.cobblemon.mod.common.api.storage.pc.PCStore
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.BattleRegistry
import com.cobblemon.mod.common.config.CobblemonConfig
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.PokemonUpdatePacket
@@ -88,10 +90,7 @@ import net.minecraft.util.math.MathHelper.clamp
import net.minecraft.util.math.Vec3d
import java.util.*
import java.util.concurrent.CompletableFuture
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
import kotlin.math.*
import kotlin.random.Random
open class Pokemon : ShowdownIdentifiable {
@@ -551,6 +550,11 @@ open class Pokemon : ShowdownIdentifiable {
val entity = entity
entity?.heal(entity.maxHealth - entity.health)
this.moveSet.partialHeal()
if (this.currentFullness > 0) {
// reduce current fullness of the pokemon by 2
this.loseFullness(2)
}
}
/**
@@ -574,6 +578,257 @@ open class Pokemon : ShowdownIdentifiable {
}
}
// code for Shuckle Berry Juice farming
var berryJuiceMeter = 0
fun getBerryJuice() {
if (this.berryJuiceMeter != 0) {
this.berryJuiceMeter -= 1
}
}
//last time this pokemon was milked (this will increase overtime)
var lastMilked = 0
// reset the lastMilked timer whenever this pokemon is milked
fun milk() {
lastMilked = 0
}
// Silly Magikarp Jump mechanics
var jumpPower = 0.0
// reset Magikarp Jump Power
fun resetJumpPower() {
this.jumpPower = 0.0
}
// function to add incremental jump power to Magikarp
fun addJumpPower(value: Double) {
this.jumpPower = value / 100
}
// returns true depending on the type of pokemon
fun isMilkable(pokemon: Pokemon): Boolean {
if (
pokemon.species.name == "Miltank" ||
pokemon.species.name == "Camerupt" ||
pokemon.species.name == "Vespiqueen" ||
pokemon.species.name == "Combee" ||
(pokemon.species.name == "Gogoat" && pokemon.gender.name == "Female") ||
(pokemon.species.name == "Bouffalant" && pokemon.gender.name == "Female")
) {
return true
}
else {
return false
}
}
// Value of current Fullness level
var currentFullness = 0
// DEPRECATED
//base Hunger value for all pokemon
var baseFullness = 5
// function to return the max hunger for the pokemon
fun getMaxFullness(): Int {
// get base HP stat of the referenced Pokemon
//var baseHP = this.species.baseStats.getOrDefault(Stats.HP,0)
// get weight of the pokemon
var weight = this.species.weight.toDouble()
//return (baseFullness + scaleFullnessRates(baseHP))
return ((getGrassKnotPower(weight) / 10 / 2) + 1)
}
// function to get grassKnot power based on weight (in Lbs)
fun getGrassKnotPower(weight: Double): Int {
return when {
weight in 0.1..21.8 -> 20
weight in 21.9..54.9 -> 40
weight in 55.0..110.1 -> 60
weight in 110.2..220.3 -> 80
weight in 220.4..440.8 -> 100
weight >= 440.9 -> 120
else -> 0 // For weights less than 0.1
}
}
// Method to add a new feeding time
fun feedPokemon(feedCount: Int) {
// get the fullness set to 0 in case something weird happens
if (this.currentFullness < 0) {
this.currentFullness = 0
}
// if pokemon is not full then feed
if (this.isFull() == false) {
this.currentFullness += feedCount
}
// pokemon was fed the first berry so we should reset their metabolism cycle so there is no inconsistencies
if (this.currentFullness == 1) {
this.resetMetabolismCycle()
}
// Every time Magikarp gets fed his JumpPower increases
if (this.species.name == "Magikarp") {
this.addJumpPower(feedCount.toDouble())
}
}
// decrease a pokemon's Fullness value by a certain amount
fun loseFullness(value: Int) {
this.currentFullness -= value
// handle possible case of fullness being less than 0
if (this.currentFullness < 0) {
this.currentFullness = 0
}
// if that pokemon is Shuckle and the berry juice meter if not full then increase the berry juice meter
if (this.species.name == "Shuckle" && this.berryJuiceMeter < 12){
this.berryJuiceMeter += 1
}
}
// DEPRECATED FOR NOW
// function to scale Hunger based off of the base HP stat of a Pokemon
fun scaleFullnessRates(stat: Int): Int {
// lowest base HP stat of a pokemon before adding more hunger
var lowerThreshold = 25
// highest base HP stat of a pokemon to be at max extra hunger
var upperThreshold = 150
// Value of the highest additional hunger allowed to be given
var maxAdditionalHunger = 15
// To adjust the curvature of the hunger scale increase as base HP gets larger
var hungerScaleExponent = 2.0
return when {
stat <= lowerThreshold -> 0
stat > upperThreshold -> maxAdditionalHunger
else -> {
// Scale the thresholds for hunger to be 0-1
val scaledStat = (stat - lowerThreshold) / (upperThreshold - lowerThreshold).toDouble()
// Apply exponential function for non-linear growth of the hunger increase
val result = maxAdditionalHunger * Math.pow(scaledStat, hungerScaleExponent)
// Ensure the result is within the bounds of the min and max thresholds
result.toInt().coerceIn(0, maxAdditionalHunger)
}
}
}
// Amount of seconds that need to pass for the pokemon to lose 1 fullness value
fun getMetabolismRate(): Int {
val hp = this.species.baseStats.getOrDefault(Stats.HP,0)
val atk = this.species.baseStats.getOrDefault(Stats.ATTACK,0)
val spatk = this.species.baseStats.getOrDefault(Stats.SPECIAL_ATTACK,0)
val def = this.species.baseStats.getOrDefault(Stats.DEFENCE,0)
val spdef = this.species.baseStats.getOrDefault(Stats.SPECIAL_DEFENCE,0)
val speed = this.species.baseStats.getOrDefault(Stats.SPEED,0)
// Base Stat Total for the pokemon
val BST = hp + atk + spatk + def + spdef + speed
// multiplying scaling value
val multiplier = 4
//base berry count
val baseBerryCount = 20
//rate of metabolism in seconds
var metabolismRate = ((baseBerryCount.toDouble() - ((speed.toDouble() / BST.toDouble()) * baseBerryCount.toDouble()) * multiplier.toDouble()) * 60.0).toInt()
// returns value in seconds for the onSecondPassed function
// check for below 0 value and set to minimum to 1 minute
if (metabolismRate <= 0) {
return 1 * 60
}
else {
return metabolismRate
}
/*var baseSpeed = this.species.baseStats.getOrDefault(Stats.SPEED, 0)
// maximum time it can take for a pokemon to lose 1 fullness
val maxRate = 480
// minimum time it can take for a pokemon to lose 1 fullness
val minRate = 120
// inflection point of the graph
val metabolismInflection = 80
// steepness of the curve near the inflection point
val steepness = 0.1
val metabolismRate = (maxRate - minRate) / (1 + Math.exp(steepness * (baseSpeed - metabolismInflection))) + minRate
// Ensure the metabolism rate is within a reasonable range
return metabolismRate.toInt().coerceIn(minRate.toInt(), maxRate.toInt())*/
}
// Boolean function that checks if a Pokemon can eat food based on fedTimes
fun isFull(): Boolean {
// Check if the pokemon is at max fullness
if (currentFullness >= this.getMaxFullness()) {
return true
}
return false
}
// The value that will increase per second until it hits a Pokemon's metabolism Factor then be set back to zero
var metabolismCycle = 0
// for setting the metabolism cycle of a pokemon back to 0 in certain cases
fun resetMetabolismCycle() {
this.metabolismCycle = 0
}
/**
* Called every second on the Pokémon for their fullness
*/
open fun onSecondPassed(player: ServerPlayerEntity, pokemon: Pokemon) {
// have metabolism cycle increase each second
metabolismCycle += 1
// set cap for lastMilked to save on resources potentially [CURRENTLY SET TO 3 HOURS]
if (pokemon.lastMilked != 10800) {
pokemon.lastMilked += 1
}
// if the metabolismCycle value equals the Pokemon's metabolism rate then decrease Fullness by 1
if (metabolismCycle >= pokemon.getMetabolismRate()) {
// as a baseline we will decrement the Fullness by 1 for each metabolism cycle
val message = "${pokemon.species.name}'s Fullness went down by 1"
if (pokemon.currentFullness > 0) {
player.sendMessage(Text.of(message))
pokemon.loseFullness(1)
}
//reset the metabolic cycle back to zero
metabolismCycle = 0
}
}
/**
* A utility method that checks if this Pokémon species or form data contains the [CobblemonPokemonLabels.LEGENDARY] label.
* This is used in Pokémon officially considered legendary.
@@ -267,6 +267,7 @@
"item.cobblemon.x_special_attack": "X Special Attack",
"item.cobblemon.dire_hit": "Dire Hit",
"item.cobblemon.guard_spec": "Guard Spec",
"item.cobblemon.moomoo_milk": "Moomoo Milk",
"item.cobblemon.full_heal": "Full Heal",
"item.cobblemon.antidote": "Antidote",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/moomoo_milk"
}
}
@@ -87,6 +87,9 @@
"berry.eat": {
"sounds": [ "cobblemon:berry_eat" ]
},
"berry.eat.full": {
"sounds": [ "cobblemon:berry_eat_full" ]
},
"pokemon.bulbasaur.ambient": {
"sounds": [ "cobblemon:pokemon/bulbasaur/bulbasaur_ambient" ]
},
Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

@@ -0,0 +1,7 @@
{
"replace": false,
"values": [
"#cobblemon:berries",
"cobblemon:berry_juice"
]
}