mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 06:36:25 -04:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c74f01bd6d | ||
|
|
199a8ba675 | ||
|
|
556f92e4b0 | ||
|
|
4f395ca47f |
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.block.MintBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfirePotColor
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
@@ -42,6 +43,7 @@ import com.cobblemon.mod.common.item.interactive.ability.AbilityChangeItem
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.pokeball.PokeBall
|
||||
import com.cobblemon.mod.common.pokemon.IVs
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.Registry
|
||||
@@ -50,6 +52,7 @@ import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.effect.MobEffects
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -66,6 +69,7 @@ import net.minecraft.world.item.SignItem
|
||||
import net.minecraft.world.item.SmithingTemplateItem
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import kotlin.math.ceil
|
||||
|
||||
@Suppress("unused", "SameParameterValue")
|
||||
object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<Item>>, Item>() {
|
||||
@@ -614,7 +618,11 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
// Medicine
|
||||
@JvmField
|
||||
val RARE_CANDY = candyItem("rare_candy", Rarity.RARE) { _, pokemon -> pokemon.getExperienceToNextLevel() }
|
||||
val RARE_CANDY = candyItem("rare_candy", Rarity.RARE) { player, pokemon ->
|
||||
if (pokemon != null) return@candyItem pokemon.getExperienceToNextLevel()
|
||||
return@candyItem -1
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val EXPERIENCE_CANDY_XS = candyItem("exp_candy_xs") { _, _ -> CandyItem.DEFAULT_XS_CANDY_YIELD }
|
||||
@JvmField
|
||||
@@ -1476,7 +1484,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return item
|
||||
}
|
||||
|
||||
private fun candyItem(name: String, rarity: Rarity = Rarity.COMMON, calculator: CandyItem.Calculator): CandyItem = this.create(name, CandyItem(rarity, calculator))
|
||||
private fun candyItem(name: String, rarity: Rarity = Rarity.COMMON, calculator: (ServerPlayer, Pokemon?) -> Int): CandyItem = this.create(name, CandyItem(rarity, calculator))
|
||||
|
||||
private fun pokerodItem(pokeRodId: ResourceLocation, rarity: Rarity = Rarity.COMMON): PokerodItem {
|
||||
val settings = Item.Properties().stacksTo(1).durability(256).rarity(rarity)
|
||||
|
||||
+6
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
@@ -25,8 +26,13 @@ interface ExperienceSource {
|
||||
fun isInteraction() = this is CandyExperienceSource
|
||||
fun isCommand() = this is CommandExperienceSource
|
||||
fun isSidemod() = this is SidemodExperienceSource
|
||||
fun isMob() = this is MobExperienceSource
|
||||
}
|
||||
|
||||
open class MobExperienceSource(
|
||||
mob: LivingEntity,
|
||||
) : ExperienceSource
|
||||
|
||||
open class SidemodExperienceSource(
|
||||
val sidemodId: String
|
||||
) : ExperienceSource
|
||||
|
||||
@@ -344,6 +344,9 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Spawning, lang = "despawner_max_age_ticks", SERVER)
|
||||
var despawnerMaxAgeTicks = 3600
|
||||
|
||||
@CobblemonConfigField(Category.World, lang = "mob_experience_conversion_rate", SERVER)
|
||||
var mobExperienceConversionRate = 50.0
|
||||
|
||||
fun clone(): CobblemonConfig {
|
||||
val newConfig = CobblemonConfig()
|
||||
CobblemonConfig::class.memberProperties.forEach { property ->
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.cobblemon.mod.common.api.net.serializers.PoseTypeDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.RideBoostsDataSerializer
|
||||
import com.cobblemon.mod.common.api.net.serializers.StringSetDataSerializer
|
||||
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.MobExperienceSource
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.ChoiceSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.FlagSpeciesFeature
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
@@ -1259,7 +1260,18 @@ open class PokemonEntity(
|
||||
|
||||
override fun doHurtTarget(target: Entity): Boolean {
|
||||
if (beamMode != 0) return false
|
||||
return super.doHurtTarget(target)
|
||||
val result = super.doHurtTarget(target)
|
||||
if (result && !target.isAlive && target is LivingEntity && !level().isClientSide) {
|
||||
val experience = target.getExperienceReward(level() as ServerLevel, this)
|
||||
val source = MobExperienceSource(mob = target)
|
||||
if (this.owner is ServerPlayer) {
|
||||
pokemon.addExperienceWithPlayer(this.owner as ServerPlayer, source, (experience * Cobblemon.config.mobExperienceConversionRate).toInt())
|
||||
}
|
||||
else {
|
||||
pokemon.addExperience(source, (experience * Cobblemon.config.mobExperienceConversionRate).toInt())
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun hurt(source: DamageSource, amount: Float): Boolean {
|
||||
|
||||
@@ -8,17 +8,24 @@
|
||||
|
||||
package com.cobblemon.mod.common.item.interactive
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.ExperienceCandyUseEvent
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.CandyExperienceSource
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.entity.ExperienceOrb
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.food.FoodProperties
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Rarity
|
||||
import net.minecraft.world.level.Level
|
||||
@@ -34,22 +41,59 @@ import net.minecraft.world.level.Level
|
||||
*/
|
||||
class CandyItem(
|
||||
val item_rarity: Rarity,
|
||||
val calculator: Calculator
|
||||
val expYield: (ServerPlayer, Pokemon?) -> Int
|
||||
) : CobblemonItem(Properties().apply {
|
||||
rarity(item_rarity)
|
||||
}), PokemonSelectingItem {
|
||||
food(FoodProperties.Builder()
|
||||
.alwaysEdible()
|
||||
.nutrition(0)
|
||||
.saturationModifier(0.0f)
|
||||
.build())
|
||||
}) {
|
||||
|
||||
override val bagItem = null
|
||||
override fun finishUsingItem(stack: ItemStack, level: Level, livingEntity: LivingEntity): ItemStack? {
|
||||
if (livingEntity !is Player) return super.finishUsingItem(stack, level, livingEntity)
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
if (user is ServerPlayer) {
|
||||
return use(user, user.getItemInHand(hand))
|
||||
/* Didn't find a good way to determine the XP needed until the beginning of the next level.
|
||||
* This works but is a little jank. Feel free to investigate a better solution.
|
||||
*/
|
||||
if (level.isClientSide && this == CobblemonItems.RARE_CANDY) {
|
||||
val volume = if (livingEntity.experienceLevel > 30) 1.0f else livingEntity.experienceLevel.toFloat() / 30.0f
|
||||
livingEntity.playSound(SoundEvents.PLAYER_LEVELUP, volume * 0.75f, 1.0f)
|
||||
}
|
||||
return InteractionResultHolder.success(user.getItemInHand(hand))
|
||||
|
||||
if (livingEntity !is ServerPlayer) return super.finishUsingItem(stack, level, livingEntity)
|
||||
if (this == CobblemonItems.RARE_CANDY) {
|
||||
livingEntity.setExperienceLevels(livingEntity.experienceLevel + 1)
|
||||
livingEntity.setExperiencePoints(0)
|
||||
}
|
||||
else {
|
||||
val expYield = expYield(livingEntity, null)
|
||||
val playerExperience = (expYield / Cobblemon.config.mobExperienceConversionRate).toInt().coerceAtLeast(1)
|
||||
ExperienceOrb.award(livingEntity.serverLevel(), livingEntity.position(), playerExperience)
|
||||
}
|
||||
return super.finishUsingItem(stack, level, livingEntity)
|
||||
}
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack>? {
|
||||
val experience = this.calculator.calculate(player, pokemon)
|
||||
override fun interactLivingEntity(
|
||||
stack: ItemStack,
|
||||
player: Player,
|
||||
interactionTarget: LivingEntity,
|
||||
usedHand: InteractionHand
|
||||
): InteractionResult {
|
||||
if (player.level().isClientSide) return InteractionResult.FAIL
|
||||
if (player.isCrouching) return InteractionResult.FAIL
|
||||
if (interactionTarget !is PokemonEntity) return InteractionResult.PASS
|
||||
if (interactionTarget.pokemon.getOwnerPlayer() != player) return InteractionResult.PASS
|
||||
return applyToPokemon(player as ServerPlayer, stack, interactionTarget.pokemon)?.result ?: InteractionResult.FAIL
|
||||
}
|
||||
|
||||
fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack>? {
|
||||
if (!pokemon.canLevelUpFurther()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
val experience = expYield(player, pokemon)
|
||||
CobblemonEvents.EXPERIENCE_CANDY_USE_PRE.postThen(
|
||||
event = ExperienceCandyUseEvent.Pre(player, pokemon, this, experience, experience),
|
||||
ifSucceeded = { preEvent ->
|
||||
@@ -74,29 +118,6 @@ class CandyItem(
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
return pokemon.isPlayerOwned()
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional interface responsible for resolving the experience a candy will yield.
|
||||
*
|
||||
* @author Licious
|
||||
* @since March 5th, 2022
|
||||
*/
|
||||
fun interface Calculator {
|
||||
|
||||
/**
|
||||
* Resolves the experience the [CandyItem] will give.
|
||||
*
|
||||
* @param player The [ServerPlayer] using the candy.
|
||||
* @param pokemon The [Pokemon] receiving experience.
|
||||
* @return The experience that will be received
|
||||
*/
|
||||
fun calculate(player: ServerPlayer, pokemon: Pokemon): Int
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_XS_CANDY_YIELD = 100
|
||||
const val DEFAULT_S_CANDY_YIELD = 800
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToPlayers
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
@@ -148,6 +149,7 @@ import net.minecraft.util.Mth.ceil
|
||||
import net.minecraft.util.Mth.clamp
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.ExperienceOrb
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.MobSpawnType
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -2016,6 +2018,12 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
}
|
||||
)
|
||||
|
||||
val player = getOwnerPlayer()
|
||||
if (player != null && player.inventory.getArmor(3).item == CobblemonItems.EXP_SHARE) {
|
||||
val playerExperience = (appliedXP / Cobblemon.config.mobExperienceConversionRate * Cobblemon.config.experienceShareMultiplier).toInt().coerceAtLeast(1)
|
||||
ExperienceOrb.award(player.serverLevel(), player.position(), playerExperience)
|
||||
}
|
||||
|
||||
experience += appliedXP
|
||||
// Bound is needed here as we can still be allowed to level up but go over the current cap
|
||||
var newLevel = experienceGroup.getLevel(experience).coerceAtMost(Cobblemon.config.maxPokemonLevel)
|
||||
|
||||
@@ -2621,6 +2621,8 @@
|
||||
"cobblemon.config.ui.infinite_ride_stamina.tooltip": "Whether rideable Pokémon have infinite stamina.",
|
||||
"cobblemon.config.ui.remember_riding_camera": "Remember Riding Camera",
|
||||
"cobblemon.config.ui.remember_riding_camera.tooltip": "Whether the camera mode will automatically switch to the last used camera mode when mounting a rideable Pokémon.",
|
||||
"cobblemon.config.ui.mob_experience_conversion_rate": "Mob Experience Conversion Rate",
|
||||
"cobblemon.config.ui.mob_experience_conversion_rate.tooltip": "The conversion rate for mob experience to pokemon experience when a Pokemon kills a mob.",
|
||||
|
||||
"cobblemon.config.ui.allow_starter_on_join": "Allow Starter on Join",
|
||||
"cobblemon.config.ui.prompt_starter_once_only": "Prompt Starter Once Only",
|
||||
|
||||
Reference in New Issue
Block a user