mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-30 22:08:59 -04:00
Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4590d95711 | ||
|
|
af969d7f85 | ||
|
|
c325dfd724 | ||
|
|
0996a20ebf | ||
|
|
bc58f8ea59 | ||
|
|
dc9d285e45 | ||
|
|
2cf879a769 | ||
|
|
9051a45add | ||
|
|
0ca248a599 | ||
|
|
3d527d2def | ||
|
|
ee90e82cc1 | ||
|
|
6c1bf7381b | ||
|
|
b20dc93fdf | ||
|
|
ee03c477cc | ||
|
|
f296d1f945 | ||
|
|
64a930aadb | ||
|
|
5c6d0bc372 |
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-3
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-2
@@ -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.
Binary file not shown.
|
After Width: | Height: | Size: 470 B |
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"#cobblemon:berries",
|
||||
"cobblemon:berry_juice"
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user