mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-11-03 23:08:53 -05:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
488bb72918 |
No files matched your search
@@ -7,7 +7,6 @@
|
||||
- Added `/changewallpaper <player> <boxNumber> <wallpaper>` command to change a box wallpaper through commands.
|
||||
- Added `/renamebox <player> <boxNumber> <name>` command to rename a PC box through commands.
|
||||
- Added IVs and EVs stat displays in PC.
|
||||
- improved filter by Name, now is available search by exact names or partial matches, for example "cha" will show Charmander, Charmeleon and Charizard among others that match.
|
||||
|
||||
### Developer
|
||||
- Added `RenamePCBoxEvent.Pre` and `RenamePCBoxEvent.Post` events to prevent players from renaming a box or changing their input.
|
||||
|
||||
+3
-28
@@ -21,15 +21,8 @@
|
||||
- Fixed Moon Ball moon phase logic to actually work correctly
|
||||
- Added `translucent_cull` boolean option into resolver's layer to allow for translucent textures with culling
|
||||
- Added [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) support for items held by Pokémon.
|
||||
- Added the Clear Amulet, Grip Claw, Lagging Tail, Luminous Moss, Metal Alloy, Scroll of Darkness, Scroll of Waters
|
||||
- Added Recipes for Masterpiece Cup, Eject Pack
|
||||
- Added modification to Minecraft Creative Inventory search to account for item names that contain `poké` when input contains `poke`.
|
||||
- Added Campfire Pot as well as loads of new food items (Poke Puffs, Ponigiri, Sinister Tea, etc)
|
||||
- Added Hearty Grains, a new crop used in the new cooking mechanic
|
||||
- Added Tatami blocks and Tatami Mat blocks, made from Hearty Grain, for decorating builds
|
||||
- Added `/pcsearch <player> <pokemonProperties>` command that searches for a specific Pokémon within a player's PC.
|
||||
- Added `/pctake <player> <box> <slot>` command that takes a specific Pokémon from a player's PC. Removes the pokemon if target is self or ran from the server.
|
||||
- Added Hyper Training items (IV Modification) as well as some additional candy items to do so (Health Candy, Sickly Candy)
|
||||
|
||||
### Pokémon Added
|
||||
|
||||
@@ -123,13 +116,12 @@
|
||||
- Made Blocks of Gold count as Big Nuggets when held by a Pokémon (for Fling functionality)
|
||||
- Players can now eat Sweet and Tart Apples, Whipped Dreams, and the Alcremie Sweets.
|
||||
- Updated Sweet and Tart Apple sprites
|
||||
- Updated the following recipes: Air Balloon, Assault Vest, Binding Band, Black Belt, Blunder Policy, Choice Band, Choice Scarf, Cleanse Tag, Covert Cloak, Destiny Knot, Eject Button, Expert Belt, Focus Band, Focus Sash, Magnet, Metronome, Muscle Band, Power Anklet, Power Band, Power Belt, Power Bracer, Power Lens, Power Weight, Protective Pads, Protein, Punching Glove, Reaper Cloth, Rocky Helmet, Room Service, Sachet, Safety Goggles, Silk Scarf, Spell Tag, Utility Umbrella, Weakness Policy, Zinc, Chipped Pot, Cracked Pot, Unremarkable Cup, Loaded Dice, Charcoal Stick, Dragon Fang, Miracle Seed, Mystic Water, Never Melt Ice, Twisted Spoon, Black Glasses, Fairy Feather, Hard Stone, Silver Powder, Soft Sand
|
||||
- Added alternate ingredient options to the following recipes: Cell Battery, Damp Rock, Heat Rock, Icy Rock, Smooth Rock
|
||||
- Updated the following recipes: Air Balloon, Assault Vest, Binding Band, Black Belt, Blunder Policy, Choice Band, Choice Scarf, Cleanse Tag, Covert Cloak, Destiny Knot, Eject Button, Expert Belt, Focus Band, Focus Sash, Magnet, Metronome, Muscle Band, Power Anklet, Power Band, Power Belt, Power Bracer, Power Lens, Power Weight, Protective Pads, Protein, Punching Glove, Reaper Cloth, Rocky Helmet, Room Service, Sachet, Safety Goggles, Silk Scarf, Spell Tag, Utility Umbrella, Weakness Policy, Zinc
|
||||
- Added alternate ingredient options to the following recipes: Cell Battery, Charcoal Stick, Dragon Fang, Miracle Seed, Mystic Water, Never Melt Ice, Twisted Spoon, Damp Rock, Heat Rock, Icy Rock, Smooth Rock
|
||||
- Grouped together some recipes within the Recipe Book. Groups include: the seven basic Poké Balls, the seven basic Ancient Poké Balls, Gilded Chests, Pokedexes, and the Weather Rocks.
|
||||
- Updated some item tags to better integrate behaviours between Cobblemon, Vanilla Minecraft, and other mods
|
||||
- Removed Cooked Meat, Raw Meat, Protein Ingredients, and Zinc Ingredients, the first two are now using `c` namespace tags, the latter have better integrated use of tags within their recipes which removes need for custom tags.
|
||||
- Added our seeds tag into `#c:seeds`, which is now made use of for the Miracle Seed recipe.
|
||||
- Added herbs and snowballs to the consumable in PvE and Wild battle tags
|
||||
- Added our seeds tag into `#c:seeds`, which is now made use of for the Miracle Seed recipe.
|
||||
- Tweaked the Natural Materials Vanilla file to fit with the changes to tags
|
||||
- Substantially optimised spawning checks mainly by front-loading biome filtering.
|
||||
- When using the `cobblemon` or `generation_9` capture calculators a critical capture with a single shake will always play for successful captures when you've already registered the Pokémon as caught in your Pokédex.
|
||||
@@ -144,15 +136,10 @@
|
||||
- Improved parity with vanilla mobs' drop behavior; loot and XP drop on death instead of after the entire death sequence finishes.
|
||||
- Quirk animations no longer play in the battle GUI since they were pretty distracting.
|
||||
- A number of Pokemon that float above the ground visually (Gastly, Klingklang, etc.) are no longer considered to be touching the ground
|
||||
- Changed the recipes for Level, Lure, and Moon Balls to be cleaner
|
||||
- Renamed `pokemonId` and `type` to `species` in relevant Advancement triggers for conformity, this is a breaking change.
|
||||
- Added a separate `species` argument to the `pick_starter`, `pasture_use` and `resurrect_pokemon` Advancement triggers.
|
||||
- Made `CobblemonAgingDespawner` thresholds configurable via the config file.
|
||||
- Tweaked Berry flavor data to balance cooking pot mechanics
|
||||
- Made Red, Yellow, Green, Blue, Pink, Black, and White Apricorn Sprout and Saccharine Sapling able to be placed into flower pots.
|
||||
- Added all Potted Apricorn Sprouts, Potted Saccharine Saplings, and Potted Pep-Up Flowers to the `#minecraft:flower_pots` block tag
|
||||
- Corrected the healing values of the remedies and energy root, and reintroduced the friendship lowering mechanics for them, revivl herb, and heal powder
|
||||
- Updated battle language keys for side effects to use position-specific formats, improving grammatical consistency
|
||||
|
||||
### Fixes
|
||||
- Fixed Particles sometimes facing the wrong direction (looking at you, Swords Dance)
|
||||
@@ -193,10 +180,6 @@
|
||||
- Fixed the `dimensions` spawning condition using the incorrect ResourceLocation, causing it to not function properly.
|
||||
- Fix issue where locator X axis was not aligned with blockbench.
|
||||
- Fix issue where particle effects that play on frame 1 on sendout would never play (Gastly)
|
||||
- Fixed the block texture name for the Pep-Up Flower being inaccurate
|
||||
- Fixed issue where the restoration tank would not accept valid items from a hopper.
|
||||
- Fixed energy root not being shearable
|
||||
- Fixed energy root always spreading into more energy roots instead of by chance (same as big root)
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -223,8 +206,6 @@
|
||||
}
|
||||
}
|
||||
`
|
||||
- The IVs class has now been extended to include Hyper Trained values.
|
||||
- Added `Pokemon#hyperTrainIV()` and `IVs#setHyperTrainedIV(Stat, Int)`
|
||||
|
||||
### MoLang & Datapacks
|
||||
- The following usages for item predicates can now use item conditions like advancements do, you can learn about them in the [Minecraft wiki](https://minecraft.wiki/w/Advancement_definition#minecraft:filled_bucket)
|
||||
@@ -244,14 +225,8 @@
|
||||
- Fixed `heldItem` property inside spawn files not working and causing crashes
|
||||
- Fixed `spawn_bedrock_particles` MoLang causing crashes when used in a server environment
|
||||
- The Pokédex form lang key definition now follows `cobblemon.ui.pokedex.info.form.{species}-{formname}` instead of `cobblemon.ui.pokedex.info.form.{formname}`.
|
||||
- Added `play_sound_on_server` as an available Molang function for the `worldHolder` & `player` functions.
|
||||
- Added `run_molang_after` as an available Molang function for the `entity` functions when schedulable.
|
||||
- Added an optional parameter for `run_molang` to schedule the function.
|
||||
- Added `labels` & `has_label` as available Molang functions for the `speciesFunctions`
|
||||
- Added datapack-defined starter categories via `data/<namespace>/starters/*.json`, with built-in fallback and `useConfigStarters` merge option.
|
||||
- The format of the `remedies.json` file has changed to allow for individual friendshipDrop amounts per remedy
|
||||
- Fixed `entity.find_nearby_block` causing crashes when attempting to use a block tag
|
||||
- Spawn Filters can now access `v.spawn.class` to get the identifier of an NPC class for when trying to influence NPC spawns
|
||||
|
||||
## [1.6.1 (January 26th, 2025)](#1-6-1)
|
||||
|
||||
|
||||
@@ -1,67 +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.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.world.CobblemonStructureIDs;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.structure.Structure;
|
||||
import net.minecraft.world.level.levelgen.structure.StructurePiece;
|
||||
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Mixin(Structure.class)
|
||||
public abstract class StructureMixin {
|
||||
// Define a set of structures that should not spawn below Sea Level
|
||||
@Unique
|
||||
private static final Set<ResourceLocation> RESTRICTED_STRUCTURES = new HashSet<>(Arrays.asList(
|
||||
CobblemonStructureIDs.STONJOURNER_HENGE,
|
||||
CobblemonStructureIDs.LUNA_HENGE,
|
||||
CobblemonStructureIDs.SOL_HENGE
|
||||
));
|
||||
|
||||
@Inject(method = "generate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/StructureStart;isValid()Z"),
|
||||
cancellable = true)
|
||||
public void cobblemon$isValid(RegistryAccess registryAccess, ChunkGenerator chunkGenerator, BiomeSource biomeSource,
|
||||
RandomState randomState, StructureTemplateManager structureTemplateManager, long seed,
|
||||
ChunkPos chunkPos, int references, LevelHeightAccessor heightAccessor,
|
||||
Predicate<Holder<Biome>> validBiome,
|
||||
CallbackInfoReturnable<StructureStart> cir,
|
||||
@Local StructureStart structureStart) {
|
||||
ResourceLocation structureKey = registryAccess.registryOrThrow(Registries.STRUCTURE).getKey((Structure) (Object) this);
|
||||
if(!RESTRICTED_STRUCTURES.contains(structureKey)) {
|
||||
return;
|
||||
}
|
||||
for (StructurePiece piece : structureStart.getPieces()) {
|
||||
if (piece.getBoundingBox().minY() < chunkGenerator.getSeaLevel()) {
|
||||
cir.setReturnValue(StructureStart.INVALID_START);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -56,7 +56,7 @@ public abstract class ClientRecipeBookMixin {
|
||||
case MISC -> var7 = CobblemonRecipeCategories.COOKING_POT_MISC.toVanillaCategory();
|
||||
case FOODS -> var7 = CobblemonRecipeCategories.COOKING_POT_FOODS.toVanillaCategory();
|
||||
case MEDICINES -> var7 = CobblemonRecipeCategories.COOKING_POT_MEDICINES.toVanillaCategory();
|
||||
case COMPLEX_DISHES -> var7 = CobblemonRecipeCategories.COOKING_POT_COMPLEX_DISHES.toVanillaCategory();
|
||||
case BAITS -> var7 = CobblemonRecipeCategories.COOKING_POT_BAITS.toVanillaCategory();
|
||||
default -> throw new MatchException(null, null);
|
||||
}
|
||||
cir.setReturnValue(var7);
|
||||
|
||||
+5
-5
@@ -50,10 +50,10 @@ public class RecipeBookCategoriesMixin {
|
||||
private static void cobblemon$addRecipeBookType(CallbackInfo ci) {
|
||||
ArrayList<RecipeBookCategories> types = new ArrayList<>(List.of($VALUES));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_SEARCH", $VALUES.length, new ItemStack(Items.COMPASS)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.LEEK_AND_POTATO_STEW)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.POTION)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_COMPLEX_DISHES", $VALUES.length + 3, new ItemStack(CobblemonItems.POKE_PUFF)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.PROTEIN)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_FOODS", $VALUES.length + 1, new ItemStack(CobblemonItems.ROASTED_LEEK)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MEDICINES", $VALUES.length + 2, new ItemStack(CobblemonItems.HP_UP)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_BAITS", $VALUES.length + 3, new ItemStack(CobblemonItems.PERSIM_BERRY)));
|
||||
types.add(cobblemon$createCategory("COOKING_POT_MISC", $VALUES.length + 4, new ItemStack(CobblemonItems.MIRROR_HERB)));
|
||||
$VALUES = types.toArray(RecipeBookCategories[]::new);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class RecipeBookCategoriesMixin {
|
||||
CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_FOODS.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_MEDICINES.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_COMPLEX_DISHES.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_BAITS.toVanillaCategory(),
|
||||
CobblemonRecipeCategories.COOKING_POT_MISC.toVanillaCategory());
|
||||
cir.setReturnValue(var10000);
|
||||
return;
|
||||
|
||||
@@ -78,6 +78,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.FlowHandler
|
||||
import com.cobblemon.mod.common.events.PokedexHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
@@ -284,6 +285,11 @@ object Cobblemon {
|
||||
event.newFriendship = event.pokemon.friendship + increment.roundToInt()
|
||||
}
|
||||
|
||||
CobblemonEvents.FULLNESS_UPDATED.subscribe(Priority.LOWEST) { event ->
|
||||
event.newFullness = event.newFullness.coerceAtMost(100)
|
||||
}
|
||||
|
||||
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
}
|
||||
|
||||
|
||||
@@ -515,30 +515,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val HEARTY_GRAINS = this.create("hearty_grains", HeartyGrainsBlock(BlockBehaviour.Properties.of().pushReaction(PushReaction.DESTROY).ignitedByLava().mapColor(MapColor.PLANT).noCollission().randomTicks().instabreak().sound(CobblemonSounds.VIVICHOKE_SOUNDS)))
|
||||
|
||||
@JvmField
|
||||
val POTTED_RED_APRICORN_SAPLING = this.create("potted_red_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(RED_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_YELLOW_APRICORN_SAPLING = this.create("potted_yellow_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(YELLOW_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_GREEN_APRICORN_SAPLING = this.create("potted_green_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(GREEN_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_BLUE_APRICORN_SAPLING = this.create("potted_blue_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(BLUE_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_PINK_APRICORN_SAPLING = this.create("potted_pink_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(PINK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_BLACK_APRICORN_SAPLING = this.create("potted_black_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(BLACK_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_WHITE_APRICORN_SAPLING = this.create("potted_white_apricorn_sapling", BlocksInvoker.createFlowerPotBlock(WHITE_APRICORN_SAPLING))
|
||||
@JvmField
|
||||
val POTTED_SACCHARINE_SAPLING = this.create("potted_saccharine_sapling", BlocksInvoker.createFlowerPotBlock(SACCHARINE_SAPLING))
|
||||
|
||||
@JvmField
|
||||
val HEARTY_GRAIN_BALE = this.create("hearty_grain_bale", HeartyGrainBaleBlock(BlockBehaviour.Properties.of().mapColor(MapColor.PLANT).instrument(NoteBlockInstrument.BANJO).strength(0.5F).sound(SoundType.GRASS)))
|
||||
@JvmField
|
||||
val TATAMI_BLOCK = this.create("tatami_block", TatamiBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).sound(SoundType.GRASS)))
|
||||
@JvmField
|
||||
val TATAMI_MAT = this.create("tatami_mat", TatamiMatBlock(BlockBehaviour.Properties.of().ignitedByLava().mapColor(MapColor.PLANT).sound(SoundType.GRASS)))
|
||||
|
||||
/**
|
||||
* Returns a map of all the blocks that can be stripped with an axe in the format of input - output.
|
||||
*
|
||||
|
||||
@@ -68,8 +68,6 @@ object CobblemonCommands {
|
||||
MarkGiveCommand.register(dispatcher)
|
||||
MarkTakeCommand.register(dispatcher)
|
||||
MarkGiveAllCommand.register(dispatcher)
|
||||
PcSearchCommand.register(dispatcher)
|
||||
PcTakeCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
|
||||
@@ -11,12 +11,10 @@ package com.cobblemon.mod.common
|
||||
import com.cobblemon.mod.common.block.PotComponent
|
||||
import com.cobblemon.mod.common.item.components.*
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.component.DataComponentType
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.codec.ByteBufCodecs
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
@@ -72,11 +70,6 @@ object CobblemonItemComponents : PlatformRegistry<Registry<DataComponentType<*>>
|
||||
.networkSynchronized(MobEffectsComponent.PACKET_CODEC)
|
||||
.build())
|
||||
|
||||
val CRAFTED: DataComponentType<Boolean> = create("crafted", DataComponentType.builder<Boolean>()
|
||||
.persistent(Codec.BOOL)
|
||||
.networkSynchronized(ByteBufCodecs.BOOL)
|
||||
.build())
|
||||
|
||||
fun register() {
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:pokemon_item"), POKEMON_ITEM)
|
||||
Registry.register(BuiltInRegistries.DATA_COMPONENT_TYPE, ResourceLocation.parse("cobblemon:bait"), BAIT)
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.item.ability.AbilityChanger
|
||||
import com.cobblemon.mod.common.api.mulch.MulchVariant
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.Natures
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
@@ -41,7 +40,6 @@ import com.cobblemon.mod.common.item.interactive.*
|
||||
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.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.core.Registry
|
||||
@@ -57,7 +55,6 @@ import net.minecraft.world.food.FoodProperties
|
||||
import net.minecraft.world.item.BlockItem
|
||||
import net.minecraft.world.item.HangingSignItem
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.Item.Properties
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.Rarity
|
||||
@@ -206,14 +203,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val CAMPFIRE_POT_YELLOW = campfirePotItem(CobblemonBlocks.YELLOW_CAMPFIRE_POT, "yellow")
|
||||
|
||||
@JvmField
|
||||
val HEARTY_GRAINS = compostableItem("hearty_grains", HeartyGrainsItem(CobblemonBlocks.HEARTY_GRAINS))
|
||||
@JvmField
|
||||
val HEARTY_GRAIN_BALE = compostableBlockItem("hearty_grain_bale", CobblemonBlocks.HEARTY_GRAIN_BALE, 0.85f)
|
||||
|
||||
@JvmField
|
||||
val TATAMI_BLOCK = blockItem("tatami_block", CobblemonBlocks.TATAMI_BLOCK)
|
||||
@JvmField
|
||||
val TATAMI_MAT = blockItem("tatami_mat", CobblemonBlocks.TATAMI_MAT)
|
||||
val Hearty_Grains = compostableItem("hearty_grains", HeartyGrainsItem(CobblemonBlocks.HEARTY_GRAINS))
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE = compostableItem("vivichoke")
|
||||
@@ -360,19 +350,19 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
|
||||
val aprijuices = mutableListOf<AprijuiceItem>()
|
||||
@JvmField
|
||||
val APRIJUICE_BLACK = aprijuiceItem(Apricorn.BLACK)
|
||||
@JvmField
|
||||
val APRIJUICE_RED = aprijuiceItem(Apricorn.RED)
|
||||
@JvmField
|
||||
val APRIJUICE_YELLOW = aprijuiceItem(Apricorn.YELLOW)
|
||||
@JvmField
|
||||
val APRIJUICE_GREEN = aprijuiceItem(Apricorn.GREEN)
|
||||
@JvmField
|
||||
val APRIJUICE_BLUE = aprijuiceItem(Apricorn.BLUE)
|
||||
@JvmField
|
||||
val APRIJUICE_PINK = aprijuiceItem(Apricorn.PINK)
|
||||
val APRIJUICE_GREEN = aprijuiceItem(Apricorn.GREEN)
|
||||
@JvmField
|
||||
val APRIJUICE_BLACK = aprijuiceItem(Apricorn.BLACK)
|
||||
val APRIJUICE_YELLOW = aprijuiceItem(Apricorn.YELLOW)
|
||||
@JvmField
|
||||
val APRIJUICE_WHITE = aprijuiceItem(Apricorn.WHITE)
|
||||
@JvmField
|
||||
val APRIJUICE_PINK = aprijuiceItem(Apricorn.PINK)
|
||||
|
||||
@JvmField
|
||||
val PONIGIRI = create("ponigiri", PonigiriItem())
|
||||
@@ -381,55 +371,138 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val SINISTER_TEA = create("sinister_tea", SinisterTeaItem())
|
||||
|
||||
@JvmField
|
||||
val POKE_PUFF = pokepuffItem("poke_puff")
|
||||
val POKE_PUFF = pokepuffItem("poke_puff") // todo make a PokePuffItem class for friendship boosting purposes
|
||||
|
||||
// FOODS
|
||||
@JvmField
|
||||
val SWEET_HEART = noSettingsItem("sweet_heart") // todo make a SweetHeartItem class for breeding purposes
|
||||
|
||||
@JvmField
|
||||
val TASTY_TAIL = noSettingsItem("tasty_tail")
|
||||
val TASTY_TAIL = create("tasty_tail", object : Item(Properties().stacksTo(16)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(8)
|
||||
.saturationModifier(12.8F)
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val PEWTER_CRUNCHIES = regionalFoodItem("pewter_crunchies", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f, false)
|
||||
@JvmField
|
||||
val PEWTER_CRUNCHIES = create("pewter_crunchies", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val RAGE_CANDY_BAR = regionalFoodItem("rage_candy_bar", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f, false)
|
||||
@JvmField
|
||||
val RAGE_CANDY_BAR = create("rage_candy_bar", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val LAVA_COOKIE = regionalFoodItem("lava_cookie", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
@JvmField
|
||||
val LAVA_COOKIE = create("lava_cookie", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val OLD_GATEAU = regionalFoodItem("old_gateau", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
@JvmField
|
||||
val OLD_GATEAU = create("old_gateau", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val CASTELIACONE = regionalFoodItem("casteliacone", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
@JvmField
|
||||
val CASTELIACONE = create("casteliacone", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val SHALOUR_SABLE = regionalFoodItem("shalour_sable", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
@JvmField
|
||||
val SHALOUR_SABLE = create("shalour_sable", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val LUMIOSE_GALETTE = regionalFoodItem("lumiose_galette", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
@JvmField
|
||||
val LUMIOSE_GALETTE = create("lumiose_galette", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val BIG_MALASADA = regionalFoodItem("big_malasada", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
@JvmField
|
||||
val BIG_MALASADA = create("big_malasada", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f, false, ItemStack(Items.BOWL, 1))
|
||||
/*@JvmField // todo see what we are doing for these (are there different kinds?)
|
||||
val CURRY = create("curry", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.usingConvertsTo(Items.BOWL)
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})*/
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val JUBILIFE_MUFFIN = regionalFoodItem("jubilife_muffin", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
@JvmField
|
||||
val JUBILIFE_MUFFIN = create("jubilife_muffin", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10) // todo get final values for this from vera
|
||||
.saturationModifier(1.2F) // todo get final values for this from vera
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F) // todo get final values for this from vera
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
@JvmField // todo get final values for this from vera
|
||||
val OPEN_FACED_SANDWICH = regionalFoodItem("open_faced_sandwich", 16, 10, 1.2f, MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1f)
|
||||
/*@JvmField // todo see what we are doing for these (are there different kinds?)
|
||||
val SANDWICH = create("sandwich", object : Item(Properties().stacksTo(16) // todo add all the effects and/or an item class for it for special interactions?
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(10)
|
||||
.saturationModifier(1.2F)
|
||||
.effect(MobEffectInstance(MobEffects.ABSORPTION, 900, 0), 1F)
|
||||
.alwaysEdible()
|
||||
.usingConvertsTo(Items.BOWL)
|
||||
.build())) {
|
||||
override fun finishUsingItem(stack: ItemStack, world: Level, user: LivingEntity): ItemStack {
|
||||
user.removeAllEffects()
|
||||
return super.finishUsingItem(stack, world, user)
|
||||
}
|
||||
})*/
|
||||
|
||||
// todo we might need to wait on these for later? These impact battles and may be harder to do
|
||||
// todo we might need to wait on these for later?
|
||||
/*@JvmField
|
||||
val CHOICE_DUMPLING = noSettingsItem("choice_dumpling") // todo make a ChoiceDumpingItem class for battle purposes
|
||||
val CHOICE_DUMPLING = noSettingsItem("choice_dumpling") // todo make a ChoiceDumpingItem class for breeding purposes
|
||||
@JvmField
|
||||
val SWAP_SNACK = noSettingsItem("swap_snack") // todo make a SwapSnackItem class for battle purposes
|
||||
val SWAP_SNACK = noSettingsItem("swap_snack") // todo make a SwapSnackItem class for breeding purposes
|
||||
@JvmField
|
||||
val TWICE_SPICED_BEETROOT = noSettingsItem("twice_spiced_beetroot") // todo make a TwiceSpiceBeetrootItem class for battle purposes
|
||||
val TWICE_SPICED_BEETROOT = noSettingsItem("twice_spiced_beetroot") // todo make a TwiceSpiceBeetrootItem class for breeding purposes
|
||||
*/
|
||||
@JvmField
|
||||
val POTATO_MOCHI = create("potato_mochi", object : Item(Properties().stacksTo(16)
|
||||
@@ -460,6 +533,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
.alwaysEdible()
|
||||
.build())) {})
|
||||
|
||||
// todo etc?
|
||||
|
||||
//@JvmField
|
||||
//val SCATTER_BANG = this.create("scatter_bang", ScatterBangItem(Item.Settings()))
|
||||
//@JvmField
|
||||
@@ -522,9 +597,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField val AUSPICIOUS_ARMOR = heldItem("auspicious_armor")
|
||||
@JvmField val MALICIOUS_ARMOR = heldItem("malicious_armor")
|
||||
@JvmField val SHELL_HELMET = heldItem("shell_helmet")
|
||||
@JvmField val METAL_ALLOY = noSettingsItem("metal_alloy")
|
||||
@JvmField val SCROLL_OF_DARKNESS = noSettingsItem("scroll_of_darkness")
|
||||
@JvmField val SCROLL_OF_WATERS = noSettingsItem("scroll_of_waters")
|
||||
|
||||
private val berries = mutableMapOf<ResourceLocation, BerryItem>()
|
||||
// Plants
|
||||
@@ -603,33 +675,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val GALARICA_NUTS = create("galarica_nuts", GalaricaNutItem())
|
||||
|
||||
// Hyper Training Items
|
||||
val hyperTrainingItems = mutableListOf<HyperTrainingItem>()
|
||||
@JvmField
|
||||
val HEALTH_CANDY = hyperTrainingItem("health_candy", 1, setOf(Stats.HP), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val MIGHTY_CANDY = hyperTrainingItem("mighty_candy", 1, setOf(Stats.ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val TOUGH_CANDY = hyperTrainingItem("tough_candy", 1, setOf(Stats.DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val SMART_CANDY = hyperTrainingItem("smart_candy", 1, setOf(Stats.SPECIAL_ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val COURAGE_CANDY = hyperTrainingItem("courage_candy", 1, setOf(Stats.SPECIAL_DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val QUICK_CANDY = hyperTrainingItem("quick_candy", 1, setOf(Stats.SPEED), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val SICKLY_CANDY = hyperTrainingItem("sickly_candy", -1, setOf(Stats.HP), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val WEAK_CANDY = hyperTrainingItem("weak_candy", -1, setOf(Stats.ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val BRITTLE_CANDY = hyperTrainingItem("brittle_candy", -1, setOf(Stats.DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val NUMB_CANDY = hyperTrainingItem("numb_candy", -1, setOf(Stats.SPECIAL_ATTACK), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val COWARD_CANDY = hyperTrainingItem("coward_candy", -1, setOf(Stats.SPECIAL_DEFENCE), 0..IVs.MAX_VALUE)
|
||||
@JvmField
|
||||
val SLOW_CANDY = hyperTrainingItem("slow_candy", -1, setOf(Stats.SPEED), 0..IVs.MAX_VALUE)
|
||||
|
||||
// Medicine
|
||||
@JvmField
|
||||
val RARE_CANDY = candyItem("rare_candy", Rarity.RARE) { _, pokemon -> pokemon.getExperienceToNextLevel() }
|
||||
@@ -951,8 +996,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val CHOICE_SCARF = heldItem("choice_scarf")
|
||||
@JvmField
|
||||
val CLEANSE_TAG = heldItem("cleanse_tag")
|
||||
@JvmField
|
||||
val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
// @JvmField
|
||||
// val CLEAR_AMULET = heldItem("clear_amulet")
|
||||
@JvmField
|
||||
val COVERT_CLOAK = heldItem("covert_cloak")
|
||||
@JvmField
|
||||
@@ -981,16 +1026,16 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val FOCUS_SASH = heldItem("focus_sash")
|
||||
@JvmField
|
||||
val GRASSY_SEED = heldItem("grassy_seed")
|
||||
@JvmField
|
||||
val GRIP_CLAW = heldItem("grip_claw")
|
||||
// @JvmField
|
||||
// val GRIP_CLAW = heldItem("grip_claw")
|
||||
@JvmField
|
||||
val HARD_STONE = heldItem("hard_stone")
|
||||
@JvmField
|
||||
val HEAVY_DUTY_BOOTS = heldItem("heavy_duty_boots")
|
||||
@JvmField
|
||||
val IRON_BALL = heldItem("iron_ball")
|
||||
@JvmField
|
||||
val LAGGING_TAIL = heldItem("lagging_tail")
|
||||
// @JvmField
|
||||
// val LAGGING_TAIL = heldItem("lagging_tail")
|
||||
@JvmField
|
||||
val LEFTOVERS = heldItem("leftovers")
|
||||
@JvmField
|
||||
@@ -1003,8 +1048,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val LOADED_DICE = heldItem("loaded_dice")
|
||||
@JvmField
|
||||
val LUCKY_EGG = heldItem("lucky_egg")
|
||||
@JvmField
|
||||
val LUMINOUS_MOSS = heldItem("luminous_moss")
|
||||
// @JvmField
|
||||
// val LUMINOUS_MOSS = heldItem("luminous_moss")
|
||||
@JvmField
|
||||
val MAGNET = heldItem("magnet")
|
||||
@JvmField
|
||||
@@ -1536,39 +1581,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return item
|
||||
}
|
||||
|
||||
private fun regionalFoodItem(
|
||||
name: String,
|
||||
stacksTo: Int,
|
||||
nutrition: Int,
|
||||
saturationModifier: Float,
|
||||
effect: MobEffectInstance? = null,
|
||||
effectChance: Float? = null,
|
||||
alwaysEdible: Boolean = false,
|
||||
convertsToOnUse: ItemStack? = null
|
||||
): RegionalFoodItem {
|
||||
val foodPropertiesBuilder = FoodProperties.Builder()
|
||||
.nutrition(nutrition)
|
||||
.saturationModifier(saturationModifier)
|
||||
|
||||
if (effect != null && effectChance != null) {
|
||||
foodPropertiesBuilder.effect(effect, effectChance)
|
||||
}
|
||||
|
||||
if (alwaysEdible == true) {
|
||||
foodPropertiesBuilder.alwaysEdible()
|
||||
}
|
||||
|
||||
if (convertsToOnUse != null && !convertsToOnUse.isEmpty) {
|
||||
foodPropertiesBuilder.usingConvertsTo(convertsToOnUse.item)
|
||||
}
|
||||
|
||||
val properties = Item.Properties()
|
||||
.stacksTo(stacksTo)
|
||||
.food(foodPropertiesBuilder.build())
|
||||
|
||||
return create(name, RegionalFoodItem(properties))
|
||||
}
|
||||
|
||||
private fun heldItem(name: String, remappedName: String? = null): CobblemonItem = create(
|
||||
name,
|
||||
CobblemonItem(Item.Properties()).also {
|
||||
@@ -1614,12 +1626,6 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
return item
|
||||
}
|
||||
|
||||
private fun hyperTrainingItem(name: String, increaseAmount: Int, targetStats: Set<Stat>, validRange: IntRange): HyperTrainingItem {
|
||||
val item = this.create(name, HyperTrainingItem(increaseAmount, targetStats, validRange))
|
||||
hyperTrainingItems.add(item)
|
||||
return item
|
||||
}
|
||||
|
||||
private fun apricornItem(name: String, apricornItem: ApricornItem): ApricornItem {
|
||||
val finalName = "${name}_apricorn"
|
||||
val item = this.create(finalName, apricornItem)
|
||||
|
||||
@@ -15,13 +15,13 @@ enum class CobblemonRecipeCategories {
|
||||
COOKING_POT_SEARCH("COOKING_POT_SEARCH"),
|
||||
COOKING_POT_FOODS("COOKING_POT_FOODS"),
|
||||
COOKING_POT_MEDICINES("COOKING_POT_MEDICINES"),
|
||||
COOKING_POT_COMPLEX_DISHES("COOKING_POT_COMPLEX_DISHES"),
|
||||
COOKING_POT_BAITS("COOKING_POT_BAITS"),
|
||||
COOKING_POT_MISC("COOKING_POT_MISC");
|
||||
|
||||
companion object {
|
||||
val customAggregateCategories: Map<RecipeBookCategories, List<RecipeBookCategories>> = mapOf(
|
||||
COOKING_POT_SEARCH.toVanillaCategory() to listOf(
|
||||
COOKING_POT_FOODS.toVanillaCategory(), COOKING_POT_MISC.toVanillaCategory(), COOKING_POT_MEDICINES.toVanillaCategory(), COOKING_POT_COMPLEX_DISHES.toVanillaCategory()
|
||||
COOKING_POT_FOODS.toVanillaCategory(), COOKING_POT_MISC.toVanillaCategory(), COOKING_POT_MEDICINES.toVanillaCategory(), COOKING_POT_BAITS.toVanillaCategory()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
+1
-2
@@ -32,7 +32,6 @@ class PokemonCriterion(
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: Pokemon): Boolean {
|
||||
var speciesCheck = (species.equals(context.species.resourceIdentifier.path) || species.equals(context.species.resourceIdentifier.toString())) || species.equals("any")
|
||||
return speciesCheck && properties.matches(context)
|
||||
return (species.equals(context.species.resourceIdentifier.path) || species.equals(context.species.resourceIdentifier.toString())) && properties.matches(context)
|
||||
}
|
||||
}
|
||||
@@ -29,12 +29,9 @@ private val bubbleColourMap = mapOf(
|
||||
|
||||
fun getColourMixFromSeasonings(seasonings: List<ItemStack>, forBubbles: Boolean = false): Int? {
|
||||
val flavors = seasonings
|
||||
.mapNotNull { Seasonings.getFlavoursFromItemStack(it) }
|
||||
.flatMap { it.entries }
|
||||
.groupingBy { it.key }
|
||||
.fold(0) { acc, entry -> acc + entry.value }
|
||||
|
||||
if (flavors.isEmpty()) return null
|
||||
.flatMap { Seasonings.getFlavoursFromItemStack(it).entries }
|
||||
.groupingBy { it.key }
|
||||
.fold(0) { acc, entry -> acc + entry.value }
|
||||
|
||||
val maxFlavorValue = flavors.values.maxOrNull()
|
||||
val dominantFlavors = flavors.filter { it.value == maxFlavorValue }.map { it.key }
|
||||
|
||||
@@ -52,6 +52,21 @@ object MobEffectUtils {
|
||||
}
|
||||
|
||||
private fun mergeAmplifiers(amplifiers: List<Int>): Int {
|
||||
return amplifiers.maxOrNull() ?: 0 // we do not want the power of the effects to combine, just take the highest one used of that type
|
||||
if (amplifiers.isEmpty()) return 0
|
||||
|
||||
val sorted = amplifiers.sortedDescending()
|
||||
var result = 0.0
|
||||
|
||||
for ((index, value) in sorted.withIndex()) {
|
||||
val multiplier = when (index) {
|
||||
0 -> 1.0
|
||||
1 -> 0.75
|
||||
2 -> 0.5
|
||||
else -> 0.25
|
||||
}
|
||||
result += (value + 1) * multiplier
|
||||
}
|
||||
|
||||
return ceil(result).toInt() - 1
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,6 @@ import net.minecraft.network.codec.ByteBufCodecs
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.Item
|
||||
import java.util.Optional
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
data class Seasoning(
|
||||
val ingredient: RegistryLikeCondition<Item>,
|
||||
@@ -41,23 +39,23 @@ data class Seasoning(
|
||||
val CODEC: Codec<Seasoning> = RecordCodecBuilder.create { builder ->
|
||||
builder.group(
|
||||
ITEM_REGISTRY_LIKE_CODEC.fieldOf("ingredient").forGetter { it.ingredient },
|
||||
Codec.unboundedMap(Flavour.CODEC, Codec.INT).optionalFieldOf("flavours").forGetter { Optional.ofNullable(it.flavours) },
|
||||
Codec.unboundedMap(Flavour.CODEC, Codec.INT).optionalFieldOf("flavours", null).forGetter { it.flavours },
|
||||
DyeColor.CODEC.fieldOf("colour").forGetter { it.colour },
|
||||
SpawnBait.Effect.CODEC.listOf().optionalFieldOf("baitEffects").forGetter { Optional.ofNullable(it.baitEffects) },
|
||||
Food.CODEC.optionalFieldOf("food").forGetter { Optional.ofNullable(it.food) },
|
||||
SerializableMobEffectInstance.CODEC.listOf().optionalFieldOf("mobEffects").forGetter { Optional.ofNullable(it.mobEffects) }
|
||||
).apply(builder) { item, flavours, colour, baitEffects, food, mobEffects ->
|
||||
Seasoning(
|
||||
item,
|
||||
flavours.getOrNull(),
|
||||
colour,
|
||||
baitEffects.getOrNull(),
|
||||
food.getOrNull(),
|
||||
mobEffects.getOrNull()
|
||||
)
|
||||
}
|
||||
SpawnBait.Effect.CODEC.listOf().optionalFieldOf("baitEffects", null).forGetter { it.baitEffects },
|
||||
Food.CODEC.optionalFieldOf("food", null).forGetter { it.food },
|
||||
SerializableMobEffectInstance.CODEC.listOf().optionalFieldOf("mobEffects", null).forGetter { it.mobEffects }
|
||||
).apply(builder, ::Seasoning)
|
||||
}
|
||||
|
||||
val STREAM_CODEC: StreamCodec<ByteBuf, Seasoning> = ByteBufCodecs.fromCodec(CODEC)
|
||||
|
||||
val BLANK_SEASONING = Seasoning(
|
||||
ingredient = RegistryLikeIdentifierCondition<Item>(cobblemonResource("blank")),
|
||||
flavours = Flavour.entries.associateWith { 0 },
|
||||
colour = DyeColor.WHITE,
|
||||
baitEffects = emptyList(),
|
||||
food = Food(),
|
||||
mobEffects = emptyList()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -12,12 +12,10 @@ import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
|
||||
import com.cobblemon.mod.common.api.cooking.Seasoning.Companion.BLANK_SEASONING
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBait
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBaitEffects
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBaitUtils
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.item.components.FoodComponent
|
||||
import com.cobblemon.mod.common.net.messages.client.cooking.SeasoningRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ItemLikeConditionAdapter
|
||||
@@ -71,27 +69,19 @@ object Seasonings : JsonDataRegistry<Seasoning> {
|
||||
this.seasonings.addAll(seasonings)
|
||||
}
|
||||
|
||||
fun getFlavoursFromItemStack(stack: ItemStack): Map<Flavour, Int>? {
|
||||
fun getFlavoursFromItemStack(stack: ItemStack): Map<Flavour, Int> {
|
||||
val holder = stack.itemHolder
|
||||
val seasoning = seasonings.find { it.ingredient.fits(holder) }
|
||||
val inherentFlavours = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours
|
||||
val seasoningFlavours = seasoning?.flavours
|
||||
val seasoning = seasonings.find { it.ingredient.fits(holder) } ?: BLANK_SEASONING
|
||||
val inherentFlavours = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours ?: emptyMap()
|
||||
val seasoningFlavours = seasoning.flavours ?: emptyMap()
|
||||
|
||||
if (seasoningFlavours.isNullOrEmpty() && inherentFlavours.isNullOrEmpty())
|
||||
return null
|
||||
|
||||
return (seasoningFlavours ?: emptyMap()).mapValues { (flavour, value) ->
|
||||
value + (inherentFlavours?.getOrDefault(flavour, 0) ?: 0)
|
||||
return seasoningFlavours.mapValues { (flavour, value) ->
|
||||
inherentFlavours.getOrDefault(flavour, 0) + value
|
||||
}
|
||||
}
|
||||
|
||||
fun hasFlavors(stack: ItemStack): Boolean {
|
||||
val flavors = getFlavoursFromItemStack(stack)
|
||||
return !flavors.isNullOrEmpty() && flavors.any { it.value != 0 }
|
||||
}
|
||||
|
||||
fun getFoodComponentFromItemStack(stack: ItemStack): FoodComponent? {
|
||||
return getFromItemStack(stack)?.food?.toComponent()
|
||||
fun getFoodFromItemStack(stack: ItemStack): Food? {
|
||||
return getFromItemStack(stack)?.food
|
||||
}
|
||||
|
||||
fun hasFood(stack: ItemStack): Boolean {
|
||||
@@ -108,17 +98,7 @@ object Seasonings : JsonDataRegistry<Seasoning> {
|
||||
}
|
||||
|
||||
fun getBaitEffectsFromItemStack(stack: ItemStack): List<SpawnBait.Effect> {
|
||||
val primaryEffects = SpawnBaitEffects.getEffectsFromItemStack(stack)
|
||||
return if (primaryEffects.isNotEmpty()) {
|
||||
primaryEffects
|
||||
} else {
|
||||
getFromItemStack(stack)?.baitEffects ?: emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
fun hasBaitEffects(stack: ItemStack): Boolean {
|
||||
return SpawnBaitEffects.getEffectsFromItemStack(stack).isNotEmpty() ||
|
||||
!(getFromItemStack(stack)?.baitEffects.isNullOrEmpty())
|
||||
return getFromItemStack(stack)?.baitEffects ?: emptyList()
|
||||
}
|
||||
|
||||
fun getFromItemStack(stack: ItemStack): Seasoning? {
|
||||
|
||||
-8
@@ -1,11 +1,3 @@
|
||||
/*
|
||||
* 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.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.fishing
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.SpawnBaitRegistrySyncPacket
|
||||
@@ -97,9 +96,8 @@ object SpawnBaitEffects : JsonDataRegistry<SpawnBait> {
|
||||
return null
|
||||
}
|
||||
|
||||
// if it has bait effects and is not listed as a seasoning then it is a bait
|
||||
fun isFishingBait(stack: ItemStack): Boolean {
|
||||
val holder = stack.itemHolder
|
||||
return effectsMap.values.any { it.item.fits(holder) }
|
||||
return stack.has(CobblemonItemComponents.BAIT_EFFECTS) || effectsMap.values.any { it.item.fits(holder) }
|
||||
}
|
||||
}
|
||||
@@ -17,20 +17,25 @@ object SpawnBaitUtils {
|
||||
return grouped.map { (key, groupEffects) ->
|
||||
val (type, subcategory) = key
|
||||
|
||||
val count = groupEffects.size
|
||||
val totalChance = groupEffects.sumOf { it.chance }
|
||||
val totalValue = groupEffects.sumOf { it.value }
|
||||
if (type == SpawnBait.Effects.RARITY_BUCKET) {
|
||||
// we want to keep the highest rarity bucket effect instead of merging them
|
||||
groupEffects.maxByOrNull { it.value }!!
|
||||
} else {
|
||||
val count = groupEffects.size
|
||||
val totalChance = groupEffects.sumOf { it.chance }
|
||||
val totalValue = groupEffects.sumOf { it.value }
|
||||
|
||||
val multiplier = when (count) {
|
||||
2 -> 0.8
|
||||
3 -> 0.6
|
||||
else -> 1.0
|
||||
val multiplier = when (count) {
|
||||
2 -> 0.8
|
||||
3 -> 0.6
|
||||
else -> 1.0
|
||||
}
|
||||
|
||||
val adjustedChance = (totalChance * multiplier).coerceAtMost(1.0)
|
||||
val adjustedValue = ceil(totalValue * multiplier)
|
||||
|
||||
SpawnBait.Effect(type, subcategory, adjustedChance, adjustedValue)
|
||||
}
|
||||
|
||||
val adjustedChance = (totalChance * multiplier).coerceAtMost(1.0)
|
||||
val adjustedValue = ceil(totalValue * multiplier)
|
||||
|
||||
SpawnBait.Effect(type, subcategory, adjustedChance, adjustedValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-8
@@ -12,7 +12,6 @@ import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
import com.cobblemon.mod.common.api.callback.MoveSelectCallbacks
|
||||
import com.cobblemon.mod.common.api.callback.PartyMoveSelectCallbacks
|
||||
import com.cobblemon.mod.common.api.moves.Move
|
||||
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
|
||||
@@ -93,13 +92,7 @@ interface PokemonAndMoveSelectingItem {
|
||||
}
|
||||
}
|
||||
|
||||
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
|
||||
return !pokemon.isFull()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean
|
||||
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
|
||||
|
||||
@@ -106,13 +106,7 @@ interface PokemonSelectingItem {
|
||||
}
|
||||
}
|
||||
|
||||
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
|
||||
return !pokemon.isFull()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean
|
||||
fun canUseOnBattlePokemon(stack: ItemStack, battlePokemon: BattlePokemon): Boolean = bagItem!!.canUse(stack, battlePokemon.actor.battle, battlePokemon)
|
||||
|
||||
fun interactWithSpecificBattle(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon): InteractionResultHolder<ItemStack> {
|
||||
@@ -137,8 +131,15 @@ interface PokemonSelectingItem {
|
||||
canSelect = { pk -> canUseOnPokemon(stack, pk) },
|
||||
handler = { pk ->
|
||||
if (stack.isHeld(player)) {
|
||||
applyToPokemon(player, stack, pk)
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
if (stack.`is`(CobblemonItemTags.POKE_FOOD)) {
|
||||
if (!pk.isFull()) {
|
||||
applyToPokemon(player, stack, pk)
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
}
|
||||
} else {
|
||||
applyToPokemon(player, stack, pk)
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pk.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.CobblemonUnlockableWallpapers
|
||||
import com.cobblemon.mod.common.Environment
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.BattleActor
|
||||
@@ -46,9 +45,6 @@ import com.cobblemon.mod.common.api.pokedex.SeenPercent
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.evolution.Evolution
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.scheduling.ClientTaskTracker
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
|
||||
import com.cobblemon.mod.common.api.storage.PokemonStore
|
||||
@@ -73,7 +69,6 @@ import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimati
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
@@ -102,7 +97,6 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.damagesource.DamageTypes
|
||||
@@ -204,15 +198,7 @@ object MoLangFunctions {
|
||||
runtime.environment.variable = params.environment.variable
|
||||
runtime.environment.context = params.environment.context
|
||||
val expression = params.getString(0).asExpressionLike()
|
||||
val delayInSeconds = params.getDoubleOrNull(1)?.toFloat() ?: 0.0f
|
||||
if (delayInSeconds > 0.0f) {
|
||||
val tracker = if (Cobblemon.implementation.environment() == Environment.SERVER) ServerTaskTracker else ClientTaskTracker
|
||||
tracker.after(delayInSeconds) {
|
||||
runtime.resolve(expression)
|
||||
}
|
||||
} else {
|
||||
runtime.resolve(expression)
|
||||
}
|
||||
runtime.resolve(expression)
|
||||
},
|
||||
"system_time_millis" to java.util.function.Function { _ ->
|
||||
DoubleValue(System.currentTimeMillis())
|
||||
@@ -359,27 +345,6 @@ object MoLangFunctions {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("play_sound_on_server") { params ->
|
||||
val sound = params.getString(0).asResource()
|
||||
val soundSource = params.getString(1).uppercase()
|
||||
val x = params.getDouble(2)
|
||||
val y = params.getDouble(3)
|
||||
val z = params.getDouble(4)
|
||||
val player = params.getOrNull<MoValue>(5)?.let {
|
||||
if (it is StringValue) world.getPlayerByUUID(UUID.fromString(it.value))
|
||||
else if (it is ObjectValue<*>) it.obj
|
||||
else null
|
||||
} as? ServerPlayer
|
||||
val volume = params.getDoubleOrNull(6)?.toFloat() ?: 1.0f
|
||||
val pitch = params.getDoubleOrNull(7)?.toFloat() ?: 1.0f
|
||||
|
||||
val packet = UnvalidatedPlaySoundS2CPacket(sound, SoundSource.valueOf(soundSource), x, y, z, volume, pitch)
|
||||
if (player != null) {
|
||||
packet.sendToPlayer(player)
|
||||
} else {
|
||||
packet.sendToPlayersAround(x, y, z, 16.0, world.dimension())
|
||||
}
|
||||
}
|
||||
map.put("get_entities_around") { params ->
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
@@ -440,15 +405,6 @@ object MoLangFunctions {
|
||||
val command = params.getString(0)
|
||||
player.server.commands.performPrefixedCommand(player.createCommandSourceStack(), command)
|
||||
}
|
||||
map.put("play_sound_on_server") { params ->
|
||||
val sound = params.getString(0).asResource()
|
||||
val soundSource = SoundSource.valueOf(params.getString(1).uppercase())
|
||||
val volume = params.getDoubleOrNull(2)?.toFloat() ?: 1.0f
|
||||
val pitch = params.getDoubleOrNull(3)?.toFloat() ?: 1.0f
|
||||
|
||||
val packet = UnvalidatedPlaySoundS2CPacket(sound, soundSource, player.x, player.y, player.z, volume, pitch)
|
||||
packet.sendToPlayer(player)
|
||||
}
|
||||
map.put("is_party_at_full_health") { _ ->
|
||||
DoubleValue(player.party().none(Pokemon::canBeHealed)) }
|
||||
map.put("can_heal_at_healer") { params ->
|
||||
@@ -663,9 +619,8 @@ object MoLangFunctions {
|
||||
map.put("biome") { _ -> entity.level().getBiome(entity.blockPosition()).asBiomeMoLangValue() }
|
||||
map.put("is_passenger") { DoubleValue(entity.isPassenger) }
|
||||
map.put("find_nearby_block") { params ->
|
||||
val input = params.getString(0)
|
||||
val isTag = input.contains("#")
|
||||
val type = input.replace("#", "").asIdentifierDefaultingNamespace(namespace = "minecraft")
|
||||
val type = params.getString(0).asIdentifierDefaultingNamespace(namespace = "minecraft")
|
||||
val isTag = type.path.startsWith("#")
|
||||
val range = params.getDoubleOrNull(1) ?: 10
|
||||
val blockPos = entity.level().getBlockStatesWithPos(AABB.ofSize(entity.position(), range.toDouble(), range.toDouble(), range.toDouble()))
|
||||
.filter { it.first.blockHolder.let { if (isTag) it.`is`(TagKey.create(Registries.BLOCK, type)) else it.`is`(type) } }
|
||||
@@ -721,17 +676,6 @@ object MoLangFunctions {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (entity is Schedulable) {
|
||||
map.put("run_molang_after") { params ->
|
||||
val expression = params.getString(0).asExpressionLike()
|
||||
val delayInSeconds = params.getDouble(1).toFloat()
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.cloneFrom(params.environment)
|
||||
entity.after(delayInSeconds) {
|
||||
runtime.resolve(expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
// q.entity.spawn_bedrock_particles(effect, locator, [player]) - sends to everyone nearby or just to the player if they're set. Locator is necessary even if unused on non-posables.
|
||||
map.put("spawn_bedrock_particles") { params ->
|
||||
val particle = params.getString(0).asResource()
|
||||
|
||||
@@ -1,56 +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
|
||||
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
object HiddenPowerUtil {
|
||||
val hiddenPowerTable = arrayOf(
|
||||
ElementalTypes.FIGHTING,
|
||||
ElementalTypes.FLYING,
|
||||
ElementalTypes.POISON,
|
||||
ElementalTypes.GROUND,
|
||||
ElementalTypes.ROCK,
|
||||
ElementalTypes.BUG,
|
||||
ElementalTypes.GHOST,
|
||||
ElementalTypes.STEEL,
|
||||
ElementalTypes.FIRE,
|
||||
ElementalTypes.WATER,
|
||||
ElementalTypes.GRASS,
|
||||
ElementalTypes.ELECTRIC,
|
||||
ElementalTypes.PSYCHIC,
|
||||
ElementalTypes.ICE,
|
||||
ElementalTypes.DRAGON,
|
||||
ElementalTypes.DARK
|
||||
)
|
||||
|
||||
fun getHiddenPowerType(pokemon: Pokemon?): ElementalType {
|
||||
if (pokemon == null) {
|
||||
return ElementalTypes.NORMAL
|
||||
}
|
||||
val ivs = pokemon.ivs
|
||||
val ivArray = arrayOf(
|
||||
ivs[Stats.HP],
|
||||
ivs[Stats.ATTACK],
|
||||
ivs[Stats.DEFENCE],
|
||||
ivs[Stats.SPEED],
|
||||
ivs[Stats.SPECIAL_ATTACK],
|
||||
ivs[Stats.SPECIAL_DEFENCE]
|
||||
).map { it ?: return@getHiddenPowerType ElementalTypes.NORMAL }
|
||||
var tableIndex = 0
|
||||
ivArray.forEachIndexed { index, it ->
|
||||
tableIndex += (it % 2) shl index
|
||||
}
|
||||
tableIndex = tableIndex * 15 / 63
|
||||
return hiddenPowerTable[tableIndex.coerceAtMost(hiddenPowerTable.size - 1)]
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategories
|
||||
import com.cobblemon.mod.common.api.moves.categories.DamageCategory
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.MoveTarget
|
||||
@@ -99,6 +100,24 @@ open class MoveTemplate(
|
||||
Moves::getByName,
|
||||
MoveTemplate::name
|
||||
) { id -> "No MoveTemplate for ID $id" }
|
||||
val hiddenPowerTable = arrayOf(
|
||||
ElementalTypes.FIGHTING,
|
||||
ElementalTypes.FLYING,
|
||||
ElementalTypes.POISON,
|
||||
ElementalTypes.GROUND,
|
||||
ElementalTypes.ROCK,
|
||||
ElementalTypes.BUG,
|
||||
ElementalTypes.GHOST,
|
||||
ElementalTypes.STEEL,
|
||||
ElementalTypes.FIRE,
|
||||
ElementalTypes.WATER,
|
||||
ElementalTypes.GRASS,
|
||||
ElementalTypes.ELECTRIC,
|
||||
ElementalTypes.PSYCHIC,
|
||||
ElementalTypes.ICE,
|
||||
ElementalTypes.DRAGON,
|
||||
ElementalTypes.DARK
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +146,21 @@ open class MoveTemplate(
|
||||
return this.elementalType
|
||||
}
|
||||
if (name == "hiddenpower") {
|
||||
return HiddenPowerUtil.getHiddenPowerType(pokemon)
|
||||
val ivs = pokemon.ivs
|
||||
val ivArray = arrayOf(
|
||||
ivs[Stats.HP],
|
||||
ivs[Stats.ATTACK],
|
||||
ivs[Stats.DEFENCE],
|
||||
ivs[Stats.SPEED],
|
||||
ivs[Stats.SPECIAL_ATTACK],
|
||||
ivs[Stats.SPECIAL_DEFENCE]
|
||||
).map { it ?: return@getEffectiveElementalType ElementalTypes.NORMAL }
|
||||
var tableIndex = 0
|
||||
ivArray.forEachIndexed { index, it ->
|
||||
tableIndex += (it % 2) shl index
|
||||
}
|
||||
tableIndex = tableIndex * 15 / 63
|
||||
return hiddenPowerTable[tableIndex.coerceAtMost(hiddenPowerTable.size - 1)]
|
||||
}
|
||||
// TODO: Handle ability suppression: clientactivebattlepokemon needs data about volatiles
|
||||
// TODO: Handle Liquid Voice: need to know what moves have the sound flag
|
||||
|
||||
@@ -96,8 +96,6 @@ object CobblemonPermissions {
|
||||
@JvmStatic
|
||||
val PC = this.create("${COMMAND_PREFIX}pc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
@JvmStatic
|
||||
val PC_SEARCH = this.create("${COMMAND_PREFIX}pcsearch", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
@JvmStatic
|
||||
val POKEBOX = this.create("${COMMAND_PREFIX}pokebox", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -43,7 +43,6 @@ import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.mojang.brigadier.StringReader
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.JsonOps
|
||||
import java.util.UUID
|
||||
import kotlin.math.min
|
||||
import kotlin.random.Random
|
||||
@@ -52,7 +51,6 @@ import net.minecraft.commands.arguments.item.ItemParser
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.NbtOps
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.network.chat.Component
|
||||
@@ -61,7 +59,6 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
/**
|
||||
* A grouping of typical, selectable properties for a Pokémon. This is serializable
|
||||
@@ -405,9 +402,6 @@ open class PokemonProperties {
|
||||
ivs.forEach { stat ->
|
||||
pokemon.setIV(stat.key, stat.value)
|
||||
}
|
||||
ivs.hyperTrainedIVs.forEach { stat ->
|
||||
pokemon.hyperTrainIV(stat.key, stat.value)
|
||||
}
|
||||
}
|
||||
evs?.let { evs ->
|
||||
evs.forEach { stat ->
|
||||
@@ -639,8 +633,8 @@ open class PokemonProperties {
|
||||
nature?.let { nbt.putString(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { nbt.putString(DataKeys.POKEMON_ABILITY, it) }
|
||||
status?.let { nbt.putString(DataKeys.POKEMON_STATUS_NAME, it) }
|
||||
ivs?.let { nbt.put(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().get()) }
|
||||
evs?.let { nbt.put(DataKeys.POKEMON_EVS, EVs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().get()) }
|
||||
ivs?.let { nbt.put(DataKeys.POKEMON_IVS, it.saveToNBT(CompoundTag())) }
|
||||
evs?.let { nbt.put(DataKeys.POKEMON_EVS, it.saveToNBT(CompoundTag())) }
|
||||
type?.let { nbt.putString(DataKeys.ELEMENTAL_TYPE, it) }
|
||||
teraType?.let { nbt.putString(DataKeys.POKEMON_TERA_TYPE, it) }
|
||||
dmaxLevel?.let { nbt.putInt(DataKeys.POKEMON_DMAX_LEVEL, it) }
|
||||
@@ -670,8 +664,8 @@ open class PokemonProperties {
|
||||
nature = if (tag.contains(DataKeys.POKEMON_NATURE)) tag.getString(DataKeys.POKEMON_NATURE) else null
|
||||
ability = if (tag.contains(DataKeys.POKEMON_ABILITY)) tag.getString(DataKeys.POKEMON_ABILITY) else null
|
||||
status = if (tag.contains(DataKeys.POKEMON_STATUS_NAME)) tag.getString(DataKeys.POKEMON_STATUS_NAME) else null
|
||||
ivs = if (tag.contains(DataKeys.POKEMON_IVS)) IVs.CODEC.decode(NbtOps.INSTANCE, tag.getCompound(DataKeys.POKEMON_IVS)).result().getOrNull()?.first else null
|
||||
evs = if (tag.contains(DataKeys.POKEMON_EVS)) EVs.CODEC.decode(NbtOps.INSTANCE, tag.getCompound(DataKeys.POKEMON_EVS)).result().getOrNull()?.first else null
|
||||
ivs = if (tag.contains(DataKeys.POKEMON_IVS)) IVs().loadFromNBT(tag.getCompound(DataKeys.POKEMON_IVS)) as IVs else null
|
||||
evs = if (tag.contains(DataKeys.POKEMON_EVS)) EVs().loadFromNBT(tag.getCompound(DataKeys.POKEMON_EVS)) as EVs else null
|
||||
type = if (tag.contains(DataKeys.ELEMENTAL_TYPE)) tag.getString(DataKeys.ELEMENTAL_TYPE) else null
|
||||
teraType = if (tag.contains(DataKeys.POKEMON_TERA_TYPE)) tag.getString(DataKeys.POKEMON_TERA_TYPE) else null
|
||||
dmaxLevel = if (tag.contains(DataKeys.POKEMON_DMAX_LEVEL)) tag.getInt(DataKeys.POKEMON_DMAX_LEVEL) else null
|
||||
@@ -703,8 +697,8 @@ open class PokemonProperties {
|
||||
nature?.let { json.addProperty(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { json.addProperty(DataKeys.POKEMON_ABILITY, it) }
|
||||
status?.let { json.addProperty(DataKeys.POKEMON_STATUS_NAME, it) }
|
||||
ivs?.let { json.add(DataKeys.POKEMON_IVS, IVs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().get()) }
|
||||
evs?.let { json.add(DataKeys.POKEMON_EVS, EVs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().get()) }
|
||||
ivs?.let { json.add(DataKeys.POKEMON_IVS, it.saveToJSON(JsonObject())) }
|
||||
evs?.let { json.add(DataKeys.POKEMON_EVS, it.saveToJSON(JsonObject())) }
|
||||
type?.let { json.addProperty(DataKeys.ELEMENTAL_TYPE, it) }
|
||||
teraType?.let { json.addProperty(DataKeys.POKEMON_TERA_TYPE, it) }
|
||||
dmaxLevel?.let { json.addProperty(DataKeys.POKEMON_DMAX_LEVEL, it) }
|
||||
@@ -735,8 +729,8 @@ open class PokemonProperties {
|
||||
nature = json.get(DataKeys.POKEMON_NATURE)?.asString
|
||||
ability = json.get(DataKeys.POKEMON_ABILITY)?.asString
|
||||
status = json.get(DataKeys.POKEMON_STATUS_NAME)?.asString
|
||||
ivs = json.getAsJsonObject(DataKeys.POKEMON_IVS)?.let { IVs.CODEC.decode(JsonOps.INSTANCE, it).result().getOrNull()?.first }
|
||||
evs = json.getAsJsonObject(DataKeys.POKEMON_EVS)?.let { EVs.CODEC.decode(JsonOps.INSTANCE, it).result().getOrNull()?.first }
|
||||
ivs = json.getAsJsonObject(DataKeys.POKEMON_IVS)?.let { IVs().loadFromJSON(it) } as? IVs
|
||||
evs = json.getAsJsonObject(DataKeys.POKEMON_EVS)?.let { EVs().loadFromJSON(it) } as? EVs
|
||||
type = json.get(DataKeys.ELEMENTAL_TYPE)?.asString
|
||||
teraType = json.get(DataKeys.POKEMON_TERA_TYPE)?.asString
|
||||
dmaxLevel = json.get(DataKeys.POKEMON_DMAX_LEVEL)?.asInt
|
||||
|
||||
+2
-4
@@ -39,9 +39,9 @@ interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBeha
|
||||
|
||||
fun speed(settings: Settings, state: State, vehicle: PokemonEntity, driver: Player): Float
|
||||
|
||||
fun clampPassengerRotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity) {}
|
||||
fun clampPassengerRotation(settings: Settings, state: State, entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun updatePassengerRotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity) {}
|
||||
fun updatePassengerRotation(settings: Settings, state: State, entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun rotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity): Vec2
|
||||
|
||||
@@ -88,8 +88,6 @@ interface RidingBehaviour<Settings : RidingBehaviourSettings, State : RidingBeha
|
||||
|
||||
fun shouldRotatePlayerHead(settings: Settings, state: State, vehicle: PokemonEntity): Boolean
|
||||
|
||||
fun maxUpStep(settings: Settings, state: State, vehicle: PokemonEntity): Float? = null
|
||||
|
||||
fun createDefaultState(settings: Settings): State
|
||||
|
||||
}
|
||||
+2
-2
@@ -23,8 +23,8 @@ import net.minecraft.world.phys.Vec3
|
||||
* @author landonjw
|
||||
*/
|
||||
open class RidingBehaviourState {
|
||||
open val rideVelocity: SidedRidingState<Vec3> = ridingState(Vec3.ZERO, Side.CLIENT)
|
||||
open val stamina: SidedRidingState<Float> = ridingState(1.0F, Side.CLIENT)
|
||||
open val rideVelocity: SidedRidingState<Vec3> = ridingState(Vec3.ZERO, Side.BOTH)
|
||||
open val stamina: SidedRidingState<Float> = ridingState(1.0F, Side.BOTH)
|
||||
|
||||
open fun reset() {
|
||||
rideVelocity.set(Vec3.ZERO, true)
|
||||
|
||||
+8
-13
@@ -8,28 +8,23 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.*
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.*
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.HorseBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.VehicleBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.BoatBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.BurstBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.DolphinBehaviour
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
object RidingBehaviours {
|
||||
val behaviours = mutableMapOf<ResourceLocation, RidingBehaviour<RidingBehaviourSettings, RidingBehaviourState>>()
|
||||
|
||||
init {
|
||||
register(BirdBehaviour.KEY, BirdBehaviour())
|
||||
register(BirdAirBehaviour.KEY, BirdAirBehaviour())
|
||||
register(DolphinBehaviour.KEY, DolphinBehaviour())
|
||||
register(HorseBehaviour.KEY, HorseBehaviour())
|
||||
register(BoatBehaviour.KEY, BoatBehaviour())
|
||||
register(GliderBehaviour.KEY, GliderBehaviour())
|
||||
register(GenericLandBehaviour.KEY, GenericLandBehaviour())
|
||||
register(GenericSwimBehaviour.KEY, GenericSwimBehaviour())
|
||||
register(GliderAirBehaviour.KEY, GliderAirBehaviour())
|
||||
register(HelicopterBehaviour.KEY, HelicopterBehaviour())
|
||||
register(JetBehaviour.KEY, JetBehaviour())
|
||||
register(BurstBehaviour.KEY, BurstBehaviour())
|
||||
register(VehicleBehaviour.KEY, VehicleBehaviour())
|
||||
register(JetAirBehaviour.KEY, JetAirBehaviour())
|
||||
register(SwimDashBehaviour.KEY, SwimDashBehaviour())
|
||||
register(VehicleLandBehaviour.KEY, VehicleLandBehaviour())
|
||||
register(HoverBehaviour.KEY, HoverBehaviour())
|
||||
register(CompositeBehaviour.KEY, CompositeBehaviour())
|
||||
}
|
||||
|
||||
+1
-16
@@ -26,7 +26,7 @@ import net.minecraft.world.phys.Vec3
|
||||
class RidingController<Settings : RidingBehaviourSettings, State : RidingBehaviourState>(val behaviour: RidingBehaviour<Settings, State>) : RidingBehaviour<Settings, State> {
|
||||
|
||||
override val key = behaviour.key
|
||||
|
||||
|
||||
override fun getRidingStyle(settings: Settings, state: State): RidingStyle {
|
||||
return behaviour.getRidingStyle(settings, state)
|
||||
}
|
||||
@@ -45,16 +45,6 @@ class RidingController<Settings : RidingBehaviourSettings, State : RidingBehavio
|
||||
return behaviour.speed(settings, state, vehicle, driver)
|
||||
}
|
||||
|
||||
override fun updatePassengerRotation(
|
||||
settings: Settings,
|
||||
state: State,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
) {
|
||||
if (!isActive(settings, state, vehicle)) return
|
||||
return behaviour.updatePassengerRotation(settings, state, vehicle, driver)
|
||||
}
|
||||
|
||||
override fun clampPassengerRotation(settings: Settings, state: State, vehicle: PokemonEntity, driver: LivingEntity) {
|
||||
if (!isActive(settings, state, vehicle)) return
|
||||
return behaviour.clampPassengerRotation(settings, state, vehicle, driver)
|
||||
@@ -185,11 +175,6 @@ class RidingController<Settings : RidingBehaviourSettings, State : RidingBehavio
|
||||
return behaviour.setRideBar(settings, state, vehicle, driver)
|
||||
}
|
||||
|
||||
override fun maxUpStep(settings: Settings, state: State, vehicle: PokemonEntity): Float? {
|
||||
if (!isActive(settings, state, vehicle)) return null
|
||||
return behaviour.maxUpStep(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: Settings): State {
|
||||
return behaviour.createDefaultState(settings)
|
||||
}
|
||||
|
||||
+46
-46
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
@@ -33,31 +33,31 @@ import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.*
|
||||
|
||||
class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
class BirdAirBehaviour : RidingBehaviour<BirdAirSettings, BirdAirState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("air/bird")
|
||||
}
|
||||
|
||||
override val key: ResourceLocation = KEY
|
||||
|
||||
override fun getRidingStyle(settings: BirdSettings, state: BirdState): RidingStyle {
|
||||
override fun getRidingStyle(settings: BirdAirSettings, state: BirdAirState): RidingStyle {
|
||||
return RidingStyle.AIR
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<BirdSettings, BirdState>(PoseType.HOVER)
|
||||
val poseProvider = PoseProvider<BirdAirSettings, BirdAirState>(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { _, state, _ -> state.rideVelocity.get().z > 0.2 })
|
||||
|
||||
override fun isActive(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Boolean {
|
||||
override fun isActive(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun pose(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): PoseType {
|
||||
override fun pose(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): PoseType {
|
||||
return poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -65,8 +65,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
@@ -74,8 +74,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
@@ -122,7 +122,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
/*
|
||||
* Calculates the change in the ride space vector due to player input and ride state
|
||||
*/
|
||||
fun calculateRideSpaceVel(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity, driver: Player) {
|
||||
fun calculateRideSpaceVel(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity, driver: Player) {
|
||||
//retrieve stats
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val glideTopSpeed = vehicle.runtime.resolveDouble(settings.glidespeedExpr)
|
||||
@@ -240,8 +240,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
deltaTime: Double
|
||||
@@ -282,8 +282,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
mouseY: Double,
|
||||
@@ -367,8 +367,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
@@ -376,8 +376,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -385,8 +385,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
@@ -395,8 +395,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
): Double {
|
||||
@@ -404,8 +404,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -420,16 +420,16 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
@@ -439,44 +439,44 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Double {
|
||||
override fun inertia(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
|
||||
override fun shouldRoll(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRoll(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Boolean {
|
||||
override fun turnOffOnGround(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Boolean {
|
||||
override fun dismountOnShift(settings: BirdAirSettings, state: BirdAirState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(
|
||||
settings: BirdSettings,
|
||||
state: BirdState,
|
||||
settings: BirdAirSettings,
|
||||
state: BirdAirState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: BirdSettings) = BirdState()
|
||||
override fun createDefaultState(settings: BirdAirSettings) = BirdAirState()
|
||||
|
||||
}
|
||||
|
||||
class BirdSettings : RidingBehaviourSettings {
|
||||
override val key = BirdBehaviour.KEY
|
||||
class BirdAirSettings : RidingBehaviourSettings {
|
||||
override val key = BirdAirBehaviour.KEY
|
||||
|
||||
var infiniteAltitude: Expression = "false".asExpression()
|
||||
private set
|
||||
@@ -518,7 +518,7 @@ class BirdSettings : RidingBehaviourSettings {
|
||||
}
|
||||
}
|
||||
|
||||
class BirdState : RidingBehaviourState() {
|
||||
class BirdAirState : RidingBehaviourState() {
|
||||
var gliding = ridingState(false, Side.CLIENT)
|
||||
var lastGlide = ridingState(-100L, Side.CLIENT)
|
||||
var currRollCorrectionForce = ridingState(0.0, Side.CLIENT)
|
||||
@@ -542,10 +542,10 @@ class BirdState : RidingBehaviourState() {
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "BirdState(rideVelocity=${rideVelocity.get()}, stamina=${stamina.get()}, gliding=${gliding.get()})"
|
||||
return "BirdAirState(rideVelocity=${rideVelocity.get()}, stamina=${stamina.get()}, gliding=${gliding.get()})"
|
||||
}
|
||||
|
||||
override fun copy() = BirdState().also {
|
||||
override fun copy() = BirdAirState().also {
|
||||
it.rideVelocity.set(this.rideVelocity.get(), forced = true)
|
||||
it.stamina.set(this.stamina.get(), forced = true)
|
||||
it.gliding.set(this.gliding.get(), forced = true)
|
||||
@@ -554,7 +554,7 @@ class BirdState : RidingBehaviourState() {
|
||||
}
|
||||
|
||||
override fun shouldSync(previous: RidingBehaviourState): Boolean {
|
||||
if (previous !is BirdState) return false
|
||||
if (previous !is BirdAirState) return false
|
||||
if (previous.gliding.get() != gliding.get()) return true
|
||||
return super.shouldSync(previous)
|
||||
}
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
@@ -32,7 +32,7 @@ import kotlin.math.sin
|
||||
|
||||
class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("liquid/dolphin")
|
||||
val KEY = cobblemonResource("swim/dolphin")
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
+59
-59
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
@@ -30,25 +30,25 @@ import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.*
|
||||
|
||||
class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
class GenericLandBehaviour : RidingBehaviour<GenericLandSettings, GenericLandState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("land/horse")
|
||||
val KEY = cobblemonResource("land/generic")
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
|
||||
override fun getRidingStyle(settings: HorseSettings, state: HorseState): RidingStyle {
|
||||
override fun getRidingStyle(settings: GenericLandSettings, state: GenericLandState): RidingStyle {
|
||||
return RidingStyle.LAND
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<HorseSettings, HorseState>(PoseType.STAND)
|
||||
val poseProvider = PoseProvider<GenericLandSettings, GenericLandState>(PoseType.STAND)
|
||||
.with(PoseOption(PoseType.WALK) { _, state, _ ->
|
||||
return@PoseOption abs(state.rideVelocity.get().z) > 0.0
|
||||
})
|
||||
|
||||
override fun isActive(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
@@ -66,16 +66,16 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun pose(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): PoseType {
|
||||
return this.poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -102,8 +102,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun updatePassengerRotation(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
) {
|
||||
@@ -128,8 +128,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun clampPassengerRotation(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
) {
|
||||
@@ -143,8 +143,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
|
||||
|
||||
override fun rotation(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
@@ -161,8 +161,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
* without it being instant.
|
||||
*/
|
||||
fun calcRotAmount(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Float {
|
||||
@@ -198,8 +198,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
|
||||
|
||||
override fun velocity(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
@@ -209,8 +209,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
private fun calculateRideSpaceVel(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Vec3 {
|
||||
@@ -293,8 +293,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
deltaTime: Double
|
||||
@@ -303,8 +303,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
mouseY: Double,
|
||||
@@ -324,8 +324,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
@@ -333,8 +333,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -343,8 +343,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
@@ -353,8 +353,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
): Double {
|
||||
@@ -362,8 +362,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -371,16 +371,16 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
@@ -392,58 +392,58 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override fun inertia(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Double {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
override fun shouldRoll(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(
|
||||
settings: HorseSettings,
|
||||
state: HorseState,
|
||||
settings: GenericLandSettings,
|
||||
state: GenericLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: HorseSettings) = HorseState()
|
||||
override fun createDefaultState(settings: GenericLandSettings) = GenericLandState()
|
||||
}
|
||||
|
||||
class HorseSettings : RidingBehaviourSettings {
|
||||
override val key = HorseBehaviour.KEY
|
||||
class GenericLandSettings : RidingBehaviourSettings {
|
||||
override val key = GenericLandBehaviour.KEY
|
||||
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
@@ -486,7 +486,7 @@ class HorseSettings : RidingBehaviourSettings {
|
||||
|
||||
}
|
||||
|
||||
class HorseState : RidingBehaviourState() {
|
||||
class GenericLandState : RidingBehaviourState() {
|
||||
var sprinting = ridingState(false, Side.CLIENT)
|
||||
var inAir = ridingState(false, Side.CLIENT)
|
||||
|
||||
@@ -508,7 +508,7 @@ class HorseState : RidingBehaviourState() {
|
||||
inAir.set(false, forced = true)
|
||||
}
|
||||
|
||||
override fun copy() = HorseState().also {
|
||||
override fun copy() = GenericLandState().also {
|
||||
it.rideVelocity.set(this.rideVelocity.get(), forced = true)
|
||||
it.stamina.set(this.stamina.get(), forced = true)
|
||||
it.sprinting.set(this.sprinting.get(), forced = true)
|
||||
@@ -516,7 +516,7 @@ class HorseState : RidingBehaviourState() {
|
||||
}
|
||||
|
||||
override fun shouldSync(previous: RidingBehaviourState): Boolean {
|
||||
if (previous !is HorseState) return false
|
||||
if (previous !is GenericLandState) return false
|
||||
if (previous.sprinting.get() != sprinting.get()) return true
|
||||
if (previous.inAir.get() != inAir.get()) return true
|
||||
return super.shouldSync(previous)
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
|
||||
class GenericSwimBehaviour : RidingBehaviour<GenericSwimSettings, RidingBehaviourState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("swim/generic")
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
|
||||
override fun getRidingStyle(settings: GenericSwimSettings, state: RidingBehaviourState): RidingStyle {
|
||||
return RidingStyle.LIQUID
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<GenericSwimSettings, RidingBehaviourState>(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { _, _, entity -> entity.isSwimming && entity.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override fun isActive(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any true
|
||||
}
|
||||
val blockState = vehicle.level().getBlockState(it)
|
||||
return@any !blockState.fluidState.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity): PoseType {
|
||||
return poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity, driver: Player): Float {
|
||||
return vehicle.runtime.resolveFloat(settings.speed)
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
): Vec3 {
|
||||
val runtime = vehicle.runtime
|
||||
val driveFactor = runtime.resolveFloat(settings.driveFactor)
|
||||
val strafeFactor = runtime.resolveFloat(settings.strafeFactor)
|
||||
val f = driver.xxa * strafeFactor
|
||||
var g = driver.zza * driveFactor
|
||||
if (g <= 0.0f) {
|
||||
g *= runtime.resolveFloat(settings.reverseDriveFactor)
|
||||
}
|
||||
|
||||
val velocity = Vec3(f.toDouble(), 0.0, g.toDouble())
|
||||
|
||||
return velocity
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
return Vec3.ZERO
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
mouseY: Double,
|
||||
mouseX: Double,
|
||||
mouseYSmoother: SmoothDouble,
|
||||
mouseXSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
|
||||
//Might need to add the smoothing here for default.
|
||||
val invertRoll = if (Cobblemon.config.invertRoll) -1 else 1
|
||||
val invertPitch = if (Cobblemon.config.invertPitch) -1 else 1
|
||||
return Vec3(0.0, mouseY * invertPitch, mouseX * invertRoll)
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
return vehicle.runtime.resolveBoolean(settings.canJump)
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
return 0.0f
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
val runtime = vehicle.runtime
|
||||
runtime.environment.query.addFunction("jump_strength") { DoubleValue(jumpStrength.toDouble()) }
|
||||
val jumpVector = settings.jumpVector.map { runtime.resolveFloat(it) }
|
||||
return Vec3(jumpVector[0].toDouble(), jumpVector[1].toDouble(), jumpVector[2].toDouble())
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
): Double {
|
||||
return regularGravity
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
return 1.0f
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
|
||||
override fun shouldRoll(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(settings: GenericSwimSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(
|
||||
settings: GenericSwimSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: GenericSwimSettings) = RidingBehaviourState()
|
||||
|
||||
}
|
||||
|
||||
class GenericSwimSettings : RidingBehaviourSettings {
|
||||
override val key = GenericSwimBehaviour.KEY
|
||||
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
|
||||
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
|
||||
private set
|
||||
|
||||
var speed = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
var driveFactor = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
var reverseDriveFactor = "0.25".asExpression()
|
||||
private set
|
||||
|
||||
var strafeFactor = "0.2".asExpression()
|
||||
private set
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeExpression(canJump)
|
||||
buffer.writeExpression(jumpVector[0])
|
||||
buffer.writeExpression(jumpVector[1])
|
||||
buffer.writeExpression(jumpVector[2])
|
||||
buffer.writeExpression(speed)
|
||||
buffer.writeExpression(driveFactor)
|
||||
buffer.writeExpression(reverseDriveFactor)
|
||||
buffer.writeExpression(strafeFactor)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
canJump = buffer.readExpression()
|
||||
jumpVector = listOf(
|
||||
buffer.readExpression(),
|
||||
buffer.readExpression(),
|
||||
buffer.readExpression()
|
||||
)
|
||||
speed = buffer.readExpression()
|
||||
driveFactor = buffer.readExpression()
|
||||
reverseDriveFactor = buffer.readExpression()
|
||||
strafeFactor = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
+27
-27
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
@@ -29,34 +29,34 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
class GliderAirBehaviour : RidingBehaviour<GliderAirSettings, RidingBehaviourState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("air/glider")
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
|
||||
override fun getRidingStyle(settings: GliderSettings, state: RidingBehaviourState): RidingStyle {
|
||||
override fun getRidingStyle(settings: GliderAirSettings, state: RidingBehaviourState): RidingStyle {
|
||||
return RidingStyle.AIR
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<GliderSettings, RidingBehaviourState>(PoseType.HOVER)
|
||||
val poseProvider = PoseProvider<GliderAirSettings, RidingBehaviourState>(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { _, _, entity -> entity.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override fun isActive(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
override fun isActive(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun pose(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): PoseType {
|
||||
override fun pose(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): PoseType {
|
||||
return poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity, driver: Player): Float {
|
||||
override fun speed(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity, driver: Player): Float {
|
||||
return vehicle.runtime.resolveFloat(settings.speed)
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
@@ -65,7 +65,7 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
@@ -80,7 +80,7 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
@@ -90,7 +90,7 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
@@ -109,12 +109,12 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
return Vec3(0.0, mouseY * invertPitch, mouseX * invertRoll)
|
||||
}
|
||||
|
||||
override fun canJump(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity, driver: Player): Boolean {
|
||||
override fun canJump(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity, driver: Player): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
@@ -123,7 +123,7 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
@@ -133,7 +133,7 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
@@ -142,7 +142,7 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
@@ -150,12 +150,12 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
return 1.0f
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
override fun useAngVelSmoothing(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: GliderSettings,
|
||||
settings: GliderAirSettings,
|
||||
state: RidingBehaviourState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
@@ -163,35 +163,35 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Double {
|
||||
override fun inertia(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
|
||||
override fun shouldRoll(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRoll(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
override fun turnOffOnGround(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
override fun dismountOnShift(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRotatePokemonHead(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRotatePlayerHead(settings: GliderAirSettings, state: RidingBehaviourState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: GliderSettings) = RidingBehaviourState()
|
||||
override fun createDefaultState(settings: GliderAirSettings) = RidingBehaviourState()
|
||||
}
|
||||
|
||||
class GliderSettings : RidingBehaviourSettings {
|
||||
override val key = GliderBehaviour.KEY
|
||||
class GliderAirSettings : RidingBehaviourSettings {
|
||||
override val key = GliderAirBehaviour.KEY
|
||||
|
||||
var glideSpeed: Expression = "0.1".asExpression()
|
||||
private set
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
+43
-43
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
@@ -30,21 +30,21 @@ import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.*
|
||||
|
||||
class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
class JetAirBehaviour : RidingBehaviour<JetAirSettings, JetAirState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("air/jet")
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
|
||||
override fun getRidingStyle(settings: JetSettings, state: JetState): RidingStyle {
|
||||
override fun getRidingStyle(settings: JetAirSettings, state: JetAirState): RidingStyle {
|
||||
return RidingStyle.AIR
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<JetSettings, JetState>(PoseType.HOVER)
|
||||
val poseProvider = PoseProvider<JetAirSettings, JetAirState>(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { _, state, _ -> state.rideVelocity.get().z > 0.1 })
|
||||
|
||||
override fun isActive(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Boolean {
|
||||
override fun isActive(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): Boolean {
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
//Need to check other fluids
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
@@ -59,11 +59,11 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(settings: JetSettings, state: JetState, vehicle: PokemonEntity): PoseType {
|
||||
override fun pose(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): PoseType {
|
||||
return poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(settings: JetSettings, state: JetState, vehicle: PokemonEntity, driver: Player): Float {
|
||||
override fun speed(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity, driver: Player): Float {
|
||||
//retrieve stats
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val staminaStat = vehicle.runtime.resolveDouble(settings.staminaExpr)
|
||||
@@ -104,8 +104,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
@@ -113,8 +113,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
@@ -153,8 +153,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
* Calculates the change in the ride space vector due to player input and ride state
|
||||
*/
|
||||
private fun calculateRideSpaceVel(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
) {
|
||||
@@ -186,8 +186,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
deltaTime: Double
|
||||
@@ -211,8 +211,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
mouseY: Double,
|
||||
@@ -273,8 +273,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
@@ -282,8 +282,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -291,8 +291,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
@@ -301,8 +301,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
): Double {
|
||||
@@ -310,8 +310,8 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -326,52 +326,52 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
return 1.0f + normalizedSpeed.pow(2).toFloat() * 0.2f
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Boolean {
|
||||
override fun useAngVelSmoothing(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Double {
|
||||
override fun inertia(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): Double {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
override fun shouldRoll(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRoll(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Boolean {
|
||||
override fun turnOffOnGround(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Boolean {
|
||||
override fun dismountOnShift(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(
|
||||
settings: JetSettings,
|
||||
state: JetState,
|
||||
settings: JetAirSettings,
|
||||
state: JetAirState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRotatePlayerHead(settings: JetAirSettings, state: JetAirState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: JetSettings) = JetState()
|
||||
override fun createDefaultState(settings: JetAirSettings) = JetAirState()
|
||||
}
|
||||
|
||||
class JetSettings : RidingBehaviourSettings {
|
||||
override val key = JetBehaviour.KEY
|
||||
class JetAirSettings : RidingBehaviourSettings {
|
||||
override val key = JetAirBehaviour.KEY
|
||||
|
||||
var gravity: Expression = "0".asExpression()
|
||||
private set
|
||||
@@ -428,7 +428,7 @@ class JetSettings : RidingBehaviourSettings {
|
||||
}
|
||||
}
|
||||
|
||||
class JetState : RidingBehaviourState() {
|
||||
class JetAirState : RidingBehaviourState() {
|
||||
var currSpeed = ridingState(0.0, Side.CLIENT)
|
||||
var currMouseXForce = ridingState(0.0, Side.CLIENT)
|
||||
var currMouseYForce = ridingState(0.0, Side.CLIENT)
|
||||
@@ -451,7 +451,7 @@ class JetState : RidingBehaviourState() {
|
||||
currMouseYForce.set(0.0, forced = true)
|
||||
}
|
||||
|
||||
override fun copy() = JetState().also {
|
||||
override fun copy() = JetAirState().also {
|
||||
it.currSpeed.set(currSpeed.get(), forced = true)
|
||||
it.stamina.set(stamina.get(), forced = true)
|
||||
it.rideVelocity.set(rideVelocity.get(), forced = true)
|
||||
@@ -460,7 +460,7 @@ class JetState : RidingBehaviourState() {
|
||||
}
|
||||
|
||||
override fun shouldSync(previous: RidingBehaviourState): Boolean {
|
||||
if (previous !is JetState) return false
|
||||
if (previous !is JetAirState) return false
|
||||
if (previous.currSpeed != currSpeed) return true
|
||||
return super.shouldSync(previous)
|
||||
}
|
||||
+44
-44
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
@@ -27,22 +27,22 @@ import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
|
||||
class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
class SwimDashBehaviour : RidingBehaviour<SwimDashSettings, SwimDashState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("liquid/burst")
|
||||
val KEY = cobblemonResource("swim/dash")
|
||||
const val DASH_TICKS: Int = 60
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
|
||||
override fun getRidingStyle(settings: BurstSettings, state: BurstState): RidingStyle {
|
||||
override fun getRidingStyle(settings: SwimDashSettings, state: SwimDashState): RidingStyle {
|
||||
return RidingStyle.LIQUID
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<BurstSettings, BurstState>(PoseType.FLOAT)
|
||||
val poseProvider = PoseProvider<SwimDashSettings, SwimDashState>(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { _, _, entity -> entity.isSwimming && entity.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override fun isActive(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Boolean {
|
||||
override fun isActive(settings: SwimDashSettings, state: SwimDashState, vehicle: PokemonEntity): Boolean {
|
||||
//This could be kinda weird... what if the top of the mon is in a fluid but the bottom isnt?
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
@@ -53,13 +53,13 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): PoseType {
|
||||
override fun pose(settings: SwimDashSettings, state: SwimDashState, vehicle: PokemonEntity): PoseType {
|
||||
return poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -77,8 +77,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
@@ -86,8 +86,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
@@ -102,8 +102,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
deltaTime: Double
|
||||
@@ -112,8 +112,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
mouseY: Double,
|
||||
@@ -132,8 +132,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
@@ -141,8 +141,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -150,8 +150,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
@@ -160,8 +160,8 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
): Double {
|
||||
@@ -169,64 +169,64 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
return 1.0f
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Boolean {
|
||||
override fun useAngVelSmoothing(settings: SwimDashSettings, state: SwimDashState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Double {
|
||||
override fun inertia(settings: SwimDashSettings, state: SwimDashState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
|
||||
override fun shouldRoll(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRoll(settings: SwimDashSettings, state: SwimDashState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Boolean {
|
||||
override fun turnOffOnGround(settings: SwimDashSettings, state: SwimDashState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(settings: BurstSettings, state: BurstState, vehicle: PokemonEntity): Boolean {
|
||||
override fun dismountOnShift(settings: SwimDashSettings, state: SwimDashState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(
|
||||
settings: BurstSettings,
|
||||
state: BurstState,
|
||||
settings: SwimDashSettings,
|
||||
state: SwimDashState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: BurstSettings) = BurstState()
|
||||
override fun createDefaultState(settings: SwimDashSettings) = SwimDashState()
|
||||
}
|
||||
|
||||
class BurstSettings : RidingBehaviourSettings {
|
||||
override val key = BurstBehaviour.KEY
|
||||
class SwimDashSettings : RidingBehaviourSettings {
|
||||
override val key = SwimDashBehaviour.KEY
|
||||
|
||||
var dashSpeed = 1F
|
||||
private set
|
||||
@@ -241,7 +241,7 @@ class BurstSettings : RidingBehaviourSettings {
|
||||
}
|
||||
}
|
||||
|
||||
class BurstState : RidingBehaviourState() {
|
||||
class SwimDashState : RidingBehaviourState() {
|
||||
var dashing = ridingState(false, Side.BOTH)
|
||||
var ticks = ridingState(0, Side.BOTH)
|
||||
|
||||
@@ -252,10 +252,10 @@ class BurstState : RidingBehaviourState() {
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "BurstState(dashing=${dashing.get()}, ticks=${ticks.get()})"
|
||||
return "SwimDashState(dashing=${dashing.get()}, ticks=${ticks.get()})"
|
||||
}
|
||||
|
||||
override fun copy() = BurstState().also {
|
||||
override fun copy() = SwimDashState().also {
|
||||
it.rideVelocity.set(rideVelocity.get(), forced = true)
|
||||
it.stamina.set(stamina.get(), forced = true)
|
||||
it.dashing.set(dashing.get(), forced = true)
|
||||
+46
-46
@@ -6,7 +6,7 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
@@ -31,7 +31,7 @@ import kotlin.math.absoluteValue
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
class VehicleLandBehaviour : RidingBehaviour<VehicleLandSettings, VehicleLandState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("land/vehicle")
|
||||
|
||||
@@ -54,14 +54,14 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
|
||||
override val key = KEY
|
||||
|
||||
override fun getRidingStyle(settings: VehicleSettings, state: VehicleState): RidingStyle {
|
||||
override fun getRidingStyle(settings: VehicleLandSettings, state: VehicleLandState): RidingStyle {
|
||||
return RidingStyle.LAND
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<VehicleSettings, VehicleState>(PoseType.STAND)
|
||||
val poseProvider = PoseProvider<VehicleLandSettings, VehicleLandState>(PoseType.STAND)
|
||||
.with(PoseOption(PoseType.WALK) { _, _, entity -> entity.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override fun isActive(settings: VehicleSettings, state: VehicleState, vehicle: PokemonEntity): Boolean {
|
||||
override fun isActive(settings: VehicleLandSettings, state: VehicleLandState, vehicle: PokemonEntity): Boolean {
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
//Need to check other fluids
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
@@ -76,13 +76,13 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun pose(settings: VehicleSettings, state: VehicleState, vehicle: PokemonEntity): PoseType {
|
||||
override fun pose(settings: VehicleLandSettings, state: VehicleLandState, vehicle: PokemonEntity): PoseType {
|
||||
return poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -101,8 +101,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
@@ -113,8 +113,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
@@ -134,8 +134,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
deltaTime: Double
|
||||
@@ -144,8 +144,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
mouseY: Double,
|
||||
@@ -164,8 +164,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
@@ -173,8 +173,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -182,8 +182,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
@@ -195,8 +195,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
): Double {
|
||||
@@ -204,8 +204,8 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
@@ -213,67 +213,67 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: VehicleSettings, state: VehicleState, vehicle: PokemonEntity): Double {
|
||||
override fun inertia(settings: VehicleLandSettings, state: VehicleLandState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
|
||||
override fun shouldRoll(settings: VehicleSettings, state: VehicleState, vehicle: PokemonEntity): Boolean {
|
||||
override fun shouldRoll(settings: VehicleLandSettings, state: VehicleLandState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(
|
||||
settings: VehicleSettings,
|
||||
state: VehicleState,
|
||||
settings: VehicleLandSettings,
|
||||
state: VehicleLandState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun createDefaultState(settings: VehicleSettings) = VehicleState()
|
||||
override fun createDefaultState(settings: VehicleLandSettings) = VehicleLandState()
|
||||
}
|
||||
|
||||
class VehicleSettings : RidingBehaviourSettings {
|
||||
override val key = VehicleBehaviour.KEY
|
||||
class VehicleLandSettings : RidingBehaviourSettings {
|
||||
override val key = VehicleLandBehaviour.KEY
|
||||
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
@@ -329,7 +329,7 @@ class VehicleSettings : RidingBehaviourSettings {
|
||||
}
|
||||
}
|
||||
|
||||
class VehicleState : RidingBehaviourState() {
|
||||
class VehicleLandState : RidingBehaviourState() {
|
||||
var currSpeed = ridingState(0.0, Side.BOTH)
|
||||
var deltaRotation = ridingState(Vec2.ZERO, Side.BOTH)
|
||||
|
||||
@@ -340,10 +340,10 @@ class VehicleState : RidingBehaviourState() {
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "VehicleState(currSpeed=${currSpeed.get()}, deltaRotation=${deltaRotation.get()})"
|
||||
return "VehicleLandState(currSpeed=${currSpeed.get()}, deltaRotation=${deltaRotation.get()})"
|
||||
}
|
||||
|
||||
override fun copy() = VehicleState().also {
|
||||
override fun copy() = VehicleLandState().also {
|
||||
it.rideVelocity.set(rideVelocity.get(), forced = true)
|
||||
it.stamina.set(stamina.get(), forced = true)
|
||||
it.currSpeed.set(currSpeed.get(), forced = true)
|
||||
-383
@@ -1,383 +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.riding.behaviour.types.liquid
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
companion object {
|
||||
val KEY = cobblemonResource("liquid/boat")
|
||||
val TOP_SPEED = 2.0
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
|
||||
override fun getRidingStyle(settings: BoatSettings, state: BoatState): RidingStyle {
|
||||
return RidingStyle.LIQUID
|
||||
}
|
||||
|
||||
val poseProvider = PoseProvider<BoatSettings, BoatState>(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { _, _, entity -> entity.isSwimming && entity.entityData.get(PokemonEntity.MOVING) })
|
||||
|
||||
override fun isActive(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Boolean {
|
||||
if (state.jumpBuffer.get() != -1) {
|
||||
return true
|
||||
}
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any true
|
||||
}
|
||||
val blockState = vehicle.level().getBlockState(it)
|
||||
return@any !blockState.fluidState.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
) {
|
||||
if (state.jumpBuffer.get() > 5) {
|
||||
if ((vehicle.isInWater || vehicle.isUnderWater || vehicle.onGround())) {
|
||||
state.jumpBuffer.set(-1)
|
||||
}
|
||||
}
|
||||
else if (state.jumpBuffer.get() > -1) {
|
||||
state.jumpBuffer.set(state.jumpBuffer.get() + 1)
|
||||
}
|
||||
|
||||
if (driver.zza == 0f && (vehicle.isInWater || vehicle.isUnderWater)) {
|
||||
if (state.staminaBuffer.get() >= 20) {
|
||||
val staminaIncrease = vehicle.getRideStat(RidingStat.STAMINA, RidingStyle.LIQUID, 1.0, 2.0)
|
||||
state.stamina.set(min(1.0f, state.stamina.get() + 0.01f * staminaIncrease.toFloat()))
|
||||
}
|
||||
}
|
||||
else if (abs(state.rideVelocity.get().z) > 0.1) {
|
||||
consumeStamina(vehicle, state, 0.01f)
|
||||
}
|
||||
state.staminaBuffer.set(state.staminaBuffer.get() + 1)
|
||||
super.tick(settings, state, vehicle, driver, input)
|
||||
}
|
||||
|
||||
override fun pose(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): PoseType {
|
||||
return poseProvider.select(settings, state, vehicle)
|
||||
}
|
||||
|
||||
override fun speed(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity, driver: Player): Float {
|
||||
return state.rideVelocity.get().length().toFloat()
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Vec2 {
|
||||
state.deltaRotation.set(state.deltaRotation.get() * 0.8)
|
||||
return Vec2(vehicle.xRot, vehicle.yRot + state.deltaRotation.get().toFloat())
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
): Vec3 {
|
||||
applyStrafeRotation(vehicle, driver, state)
|
||||
|
||||
var velocity = state.rideVelocity.get()
|
||||
velocity = applyVelocityFromInput(velocity, vehicle, driver, state)
|
||||
velocity = applyGravity(velocity, vehicle, settings, state)
|
||||
velocity = applyJump(velocity, vehicle, driver, state)
|
||||
state.rideVelocity.set(velocity)
|
||||
return state.rideVelocity.get()
|
||||
}
|
||||
|
||||
private fun applyVelocityFromInput(velocity: Vec3, vehicle: PokemonEntity, driver: Player, state: BoatState): Vec3 {
|
||||
val speed = vehicle.getRideStat(RidingStat.SPEED, RidingStyle.LIQUID, 0.8, TOP_SPEED)
|
||||
val acceleration = vehicle.getRideStat(RidingStat.ACCELERATION, RidingStyle.LIQUID, 0.05, 0.5)
|
||||
|
||||
if (state.jumpBuffer.get() != -1 || !(vehicle.isInWater || vehicle.isUnderWater)) {
|
||||
return velocity
|
||||
}
|
||||
|
||||
val forwardInput = driver.zza.toDouble()
|
||||
val delta = when {
|
||||
!hasStamina(state) || forwardInput == 0.0 -> -velocity.z * 0.04
|
||||
forwardInput < 0.0 -> when {
|
||||
velocity.z < 0.0 -> forwardInput * acceleration * 0.5
|
||||
else -> min(forwardInput * acceleration * 0.5, -velocity.z * 0.04) // We never want it to be slower to reverse than no input
|
||||
}
|
||||
else -> forwardInput * acceleration
|
||||
}
|
||||
|
||||
return Vec3(
|
||||
velocity.x,
|
||||
velocity.y,
|
||||
Mth.clamp(velocity.z + delta, -speed * 0.25, speed)
|
||||
)
|
||||
}
|
||||
|
||||
private fun applyJump(velocity: Vec3, vehicle: PokemonEntity, driver: Player, state: BoatState): Vec3 {
|
||||
if (!driver.jumping) return velocity // Not jumping
|
||||
if (state.jumpBuffer.get() != -1) return velocity // Already jumped very recently
|
||||
if (!hasStamina(state)) return velocity // Has no stamina
|
||||
|
||||
val jumpStrength = vehicle.getRideStat(RidingStat.JUMP, RidingStyle.LIQUID, 1.0, 2.5)
|
||||
state.jumpBuffer.set(0)
|
||||
consumeStamina(vehicle, state, 0.05f)
|
||||
return Vec3(velocity.x, velocity.y + jumpStrength, velocity.z)
|
||||
}
|
||||
|
||||
private fun applyGravity(velocity: Vec3, vehicle: PokemonEntity, settings: BoatSettings, state: BoatState): Vec3 {
|
||||
if (state.jumpBuffer.get() == -1 && vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return Vec3(velocity.x, -0.05, velocity.z)
|
||||
}
|
||||
val terminalVelocity = vehicle.runtime.resolveDouble(settings.terminalVelocity)
|
||||
val gravity = (9.8 / ( 20.0)) * 0.2
|
||||
return Vec3(velocity.x, max(velocity.y - gravity, terminalVelocity), velocity.z)
|
||||
}
|
||||
|
||||
private fun applyStrafeRotation(vehicle: PokemonEntity, driver: Player, state: BoatState) {
|
||||
val skill = vehicle.getRideStat(RidingStat.SKILL, RidingStyle.LIQUID, 0.5, 1.5)
|
||||
val strafe = driver.xxa
|
||||
if (abs(strafe) > 0) {
|
||||
val increase = if (strafe > 0) -1 else 1
|
||||
state.deltaRotation.set(state.deltaRotation.get() + increase * skill)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasStamina(state: BoatState): Boolean {
|
||||
return state.stamina.get() != 0f
|
||||
}
|
||||
|
||||
private fun consumeStamina(vehicle: PokemonEntity, state: BoatState, drain: Float) {
|
||||
val stamina = vehicle.getRideStat(RidingStat.STAMINA, RidingStyle.LIQUID, 1.0, 5.0)
|
||||
state.stamina.set(max(0f, state.stamina.get() - drain / stamina.toFloat()))
|
||||
state.staminaBuffer.set(0)
|
||||
}
|
||||
|
||||
override fun updatePassengerRotation(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
) {
|
||||
driver.yRot += state.deltaRotation.get().toFloat() * 0.887f
|
||||
driver.yHeadRot += state.deltaRotation.get().toFloat() * 0.887f
|
||||
clampPassengerRotation(settings, state, vehicle, driver)
|
||||
}
|
||||
|
||||
override fun clampPassengerRotation(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
) {
|
||||
driver.setYBodyRot(vehicle.yRot)
|
||||
val f: Float = Mth.wrapDegrees(driver.yRot - vehicle.yRot)
|
||||
val g = Mth.clamp(f, -105.0f, 105.0f)
|
||||
driver.yRotO += g - f
|
||||
driver.yRot = driver.yRot + g - f
|
||||
driver.setYHeadRot(driver.yRot)
|
||||
vehicle.setYHeadRot(driver.yRot)
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
return Vec3.ZERO
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
mouseY: Double,
|
||||
mouseX: Double,
|
||||
mouseYSmoother: SmoothDouble,
|
||||
mouseXSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
|
||||
//Might need to add the smoothing here for default.
|
||||
val invertRoll = if (Cobblemon.config.invertRoll) -1 else 1
|
||||
val invertPitch = if (Cobblemon.config.invertPitch) -1 else 1
|
||||
return Vec3(0.0, mouseY * invertPitch, mouseX * invertRoll)
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
return (state.stamina.get() / 1.0f)
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
return Vec3.ZERO
|
||||
}
|
||||
|
||||
override fun gravity(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
regularGravity: Double
|
||||
): Double {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
override fun rideFovMultiplier(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
if (state.rideVelocity.get().z > TOP_SPEED * 0.8) {
|
||||
return Mth.lerp((state.rideVelocity.get().z - (TOP_SPEED * 0.8)) / (TOP_SPEED * 0.2), 1.0, 1.2).toFloat()
|
||||
}
|
||||
return 1.0f
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun useRidingAltPose(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): ResourceLocation {
|
||||
return cobblemonResource("no_pose")
|
||||
}
|
||||
|
||||
override fun inertia(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Double {
|
||||
return 0.5
|
||||
}
|
||||
|
||||
override fun shouldRoll(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun turnOffOnGround(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun dismountOnShift(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun shouldRotatePokemonHead(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return vehicle.runtime.resolveBoolean(settings.rotatePokemonHead)
|
||||
}
|
||||
|
||||
override fun shouldRotatePlayerHead(
|
||||
settings: BoatSettings,
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun maxUpStep(settings: BoatSettings, state: BoatState, vehicle: PokemonEntity) = 0f
|
||||
|
||||
override fun createDefaultState(settings: BoatSettings) = BoatState()
|
||||
|
||||
}
|
||||
|
||||
class BoatSettings : RidingBehaviourSettings {
|
||||
override val key = BoatBehaviour.KEY
|
||||
|
||||
var terminalVelocity = "-2.0".asExpression()
|
||||
private set
|
||||
|
||||
var rotatePokemonHead = "true".asExpression()
|
||||
private set
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeExpression(terminalVelocity)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
terminalVelocity = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
class BoatState : RidingBehaviourState() {
|
||||
val deltaRotation = ridingState(0.0, Side.CLIENT)
|
||||
val jumpBuffer = ridingState(-1, Side.CLIENT)
|
||||
val staminaBuffer = ridingState(0, Side.CLIENT)
|
||||
|
||||
override fun copy() = BoatState().also {
|
||||
it.deltaRotation.set(deltaRotation.get(), true)
|
||||
it.rideVelocity.set(rideVelocity.get(), true)
|
||||
it.stamina.set(stamina.get(), true)
|
||||
it.jumpBuffer.set(jumpBuffer.get(), true)
|
||||
it.staminaBuffer.set(staminaBuffer.get(), true)
|
||||
}
|
||||
|
||||
override fun shouldSync(previous: RidingBehaviourState): Boolean {
|
||||
if (previous !is BoatState) return false
|
||||
return super.shouldSync(previous)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.spawning.detail
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.npc.NPCClass
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnBucket
|
||||
import com.cobblemon.mod.common.api.spawning.position.SpawnablePosition
|
||||
@@ -17,7 +16,6 @@ import com.cobblemon.mod.common.api.spawning.selection.SpawnSelectionData
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlin.math.ceil
|
||||
|
||||
/**
|
||||
* A [SpawnDetail] describing an [NPCEntity] spawn.
|
||||
@@ -39,16 +37,6 @@ class NPCSpawnDetail : SpawnDetail() {
|
||||
val minLevel: Expression = "1".asExpression()
|
||||
val maxLevel: Expression = "100".asExpression()
|
||||
|
||||
|
||||
override fun autoLabel() {
|
||||
val npcClass = this.npcClass
|
||||
|
||||
struct.addFunction("class") { StringValue(npcClass.resourceIdentifier.toString()) }
|
||||
labels.add(npcClass.resourceIdentifier.toString())
|
||||
|
||||
super.autoLabel()
|
||||
}
|
||||
|
||||
override fun createSpawnAction(
|
||||
spawnablePosition: SpawnablePosition,
|
||||
bucket: SpawnBucket,
|
||||
|
||||
@@ -151,11 +151,6 @@ open class PlayerPartyStore(
|
||||
removeList.add(it)
|
||||
}
|
||||
removeList.forEach { pokemon.evolutionProxy.server().remove(it) }
|
||||
|
||||
// Metabolism for Fullness
|
||||
if (pokemon.currentFullness > 0) {
|
||||
pokemon.tickMetabolism()
|
||||
}
|
||||
}
|
||||
// Friendship
|
||||
// ToDo expand this down the line just a very basic implementation for the first releases
|
||||
|
||||
@@ -44,17 +44,7 @@ class Search(
|
||||
"legendary" -> PokemonFilter { pokemon -> pokemon.isLegendary() }
|
||||
"mythical" -> PokemonFilter { pokemon -> pokemon.isMythical() }
|
||||
"ultrabeast", "ultra_beast" -> PokemonFilter { pokemon -> pokemon.isUltraBeast() }
|
||||
else -> {
|
||||
val nameFilter = filter.lowercase(Locale.ROOT)
|
||||
PokemonFilter { pokemon ->
|
||||
// search by partial name
|
||||
if (pokemon.species.resourceIdentifier.path.contains(nameFilter)) {
|
||||
return@PokemonFilter true
|
||||
}
|
||||
// search by exactly match in different props
|
||||
return@PokemonFilter PokemonProperties.parse(filter).matches(pokemon)
|
||||
}
|
||||
}
|
||||
else -> PokemonFilter { pokemon -> PokemonProperties.parse(filter).matches(pokemon) }
|
||||
}
|
||||
|
||||
if (inverted) {
|
||||
|
||||
@@ -28,7 +28,6 @@ object CobblemonItemTags {
|
||||
@JvmField val APRICORN_POKE_BALLS = create("apricorn_poke_balls")
|
||||
@JvmField val APRICORN_SPROUTS = create("apricorn_sprouts")
|
||||
@JvmField val APRICORNS = create("apricorns")
|
||||
@JvmField val APRIJUICES = create("aprijuices")
|
||||
/** This tag is only used for a Torterra aspect based easter egg evolution at the moment.
|
||||
* It simply includes the 'minecraft:azalea' and 'minecraft:flowering_azalea' items by default. */
|
||||
@JvmField val AZALEA_TREE = create("azalea_tree")
|
||||
@@ -52,7 +51,6 @@ object CobblemonItemTags {
|
||||
@JvmField val FIRE_STONE_ORES = create("fire_stone_ores")
|
||||
@JvmField val FOSSIL_MACHINE_PARTS = create("fossil_machine_parts")
|
||||
@JvmField val FOSSILS = create("fossils")
|
||||
@JvmField val FULL_HEAL_INGREDIENTS = create("full_heal_ingredients")
|
||||
@JvmField val GILDED_CHESTS = create("gilded_chests")
|
||||
@JvmField val HANGING_SIGNS = create("hanging_signs")
|
||||
@JvmField val HERBS = create("herbs")
|
||||
@@ -62,7 +60,6 @@ object CobblemonItemTags {
|
||||
@JvmField val MINT_LEAF = create("mint_leaf")
|
||||
@JvmField val MINT_SEEDS = create("mint_seeds")
|
||||
@JvmField val MINTS = create("mints")
|
||||
@JvmField val MOCHIS = create("mochis")
|
||||
@JvmField val MOON_STONE_ORES = create("moon_stone_ores")
|
||||
@JvmField val MUTATED_BERRIES = create("mutated_berries")
|
||||
@JvmField val PLANTS = create("plants")
|
||||
@@ -78,17 +75,14 @@ object CobblemonItemTags {
|
||||
@JvmField val RED_TUMBLESTONE_BRICKS = create("red_tumblestone_bricks")
|
||||
@JvmField val RED_TUMBLESTONES = create("red_tumblestones")
|
||||
@JvmField val REMEDIES = create("remedies")
|
||||
@JvmField val REMEDY_BERRIES = create("remedy_berries")
|
||||
@JvmField val RESTORES = create("restores")
|
||||
@JvmField val REVIVES = create("revives")
|
||||
@JvmField val SANDWICH_VEGGIE = create("sandwich_veggies")
|
||||
@JvmField val SEEDS = create("seeds")
|
||||
@JvmField val SHINY_STONE_ORES = create("shiny_stone_ores")
|
||||
@JvmField val SIGNS = create("signs")
|
||||
@JvmField val SKY_TUMBLESTONE_BRICKS = create("sky_tumblestone_bricks")
|
||||
@JvmField val SKY_TUMBLESTONES = create("sky_tumblestones")
|
||||
@JvmField val SUN_STONE_ORES = create("sun_stone_ores")
|
||||
@JvmField val SUPER_POTION_INGREDIENTS = create("super_potion_ingredients")
|
||||
@JvmField val SWEETS = create("sweets")
|
||||
@JvmField val TEACUPS = create("teacups")
|
||||
@JvmField val TEAPOTS = create("teapots")
|
||||
|
||||
@@ -13,7 +13,6 @@ import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPostEvent
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
|
||||
import com.cobblemon.mod.common.api.moves.HiddenPowerUtil
|
||||
import com.cobblemon.mod.common.api.pokemon.helditem.HeldItemProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
@@ -97,7 +96,7 @@ object BattleRegistry {
|
||||
// Gender
|
||||
packedTeamBuilder.append("${pk.gender.showdownName}|")
|
||||
// IVs
|
||||
val ivsInOrder = Stats.PERMANENT.map { pk.ivs.getEffectiveBattleIV(it) }.joinToString(separator = ",")
|
||||
val ivsInOrder = Stats.PERMANENT.map { pk.ivs.getOrDefault(it) }.joinToString(separator = ",")
|
||||
packedTeamBuilder.append("$ivsInOrder|")
|
||||
// Shiny
|
||||
packedTeamBuilder.append("${if (pk.shiny) "S" else ""}|")
|
||||
@@ -112,9 +111,7 @@ object BattleRegistry {
|
||||
val pokeball = pokemon.effectedPokemon.caughtBall.name.path.replace("_", "")
|
||||
packedTeamBuilder.append("$pokeball,")
|
||||
// Hidden Power Type
|
||||
// This is empty if the pokemon is not Hyper Trained, and the provided type corresponds to base IVs and not battle IVs.
|
||||
val hiddenPowerType = if (pk.ivs.hyperTrainedIVs.any()) HiddenPowerUtil.getHiddenPowerType(pk).name.replaceFirstChar { it.uppercase() } else ""
|
||||
packedTeamBuilder.append("$hiddenPowerType,")
|
||||
packedTeamBuilder.append(",")
|
||||
// Gigantamax
|
||||
packedTeamBuilder.append("${if (pk.gmaxFactor) "G" else ""},")
|
||||
// DynamaxLevel
|
||||
|
||||
+2
-4
@@ -28,10 +28,8 @@ class SideEndInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
val side = if (message.argumentAt(0)?.get(1) == '1') battle.side1 else battle.side2
|
||||
val effect = message.effectAt(1) ?: return@dispatchWaiting
|
||||
battle.sides.forEach {
|
||||
val isAllySide = it == side
|
||||
val positionSpecificKey = if (isAllySide) "sideend.ally.${effect.id}" else "sideend.opponent.${effect.id}"
|
||||
val lang = battleLang(positionSpecificKey)
|
||||
|
||||
val subject = if (it == side) battleLang("side_subject.ally") else battleLang("side_subject.opponent")
|
||||
val lang = battleLang("sideend.${effect.id}", subject)
|
||||
it.broadcastChatMessage(lang)
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -29,10 +29,8 @@ class SideStartInstruction(val message: BattleMessage): InterpreterInstruction {
|
||||
val side = if (message.argumentAt(0)?.get(1) == '1') battle.side1 else battle.side2
|
||||
val effect = message.effectAt(1) ?: return@dispatchWaiting
|
||||
battle.sides.forEach {
|
||||
val isAllySide = it == side
|
||||
val positionSpecificKey = if (isAllySide) "sidestart.ally.${effect.id}" else "sidestart.opponent.${effect.id}"
|
||||
val lang = battleLang(positionSpecificKey)
|
||||
|
||||
val subject = if (it == side) battleLang("side_subject.ally") else battleLang("side_subject.opponent")
|
||||
val lang = battleLang("sidestart.${effect.id}", subject)
|
||||
it.broadcastChatMessage(lang)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,18 @@ package com.cobblemon.mod.common.block
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
@@ -24,6 +30,24 @@ import net.minecraft.world.phys.shapes.VoxelShape
|
||||
class BigRootBlock(settings: Properties) : RootBlock(settings) {
|
||||
override fun getShape(state: BlockState, world: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape = AABB
|
||||
|
||||
override fun useWithoutItem(
|
||||
state: BlockState,
|
||||
world: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
blockHitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
val stack = player.getItemInHand(InteractionHand.MAIN_HAND)
|
||||
if (stack.`is`(Items.SHEARS)) {
|
||||
this.attemptShear(world, state, pos) {
|
||||
player.onEquippedItemBroken(stack.item, EquipmentSlot.MAINHAND)
|
||||
stack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND)
|
||||
}
|
||||
return InteractionResult.sidedSuccess(world.isClientSide)
|
||||
}
|
||||
return super.useWithoutItem(state, world, pos, player, blockHitResult)
|
||||
}
|
||||
|
||||
override fun shearedResultingState(): BlockState = Blocks.HANGING_ROOTS.defaultBlockState()
|
||||
|
||||
override fun shearedDrop(): ItemStack = Items.STRING.defaultInstance
|
||||
|
||||
@@ -1,104 +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.block
|
||||
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.RotatedPillarBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
|
||||
class HeartyGrainBaleBlock(properties: Properties) : RotatedPillarBlock(properties) {
|
||||
|
||||
private var owner: LivingEntity? = null
|
||||
|
||||
init {
|
||||
this.registerDefaultState(
|
||||
this.stateDefinition.any()
|
||||
.setValue(AXIS, Direction.Axis.Y)
|
||||
)
|
||||
}
|
||||
|
||||
override fun setPlacedBy(
|
||||
level: Level,
|
||||
pos: BlockPos,
|
||||
state: BlockState,
|
||||
placer: LivingEntity?,
|
||||
itemStack: ItemStack
|
||||
) {
|
||||
owner = placer
|
||||
super.setPlacedBy(level, pos, state, placer, itemStack)
|
||||
}
|
||||
|
||||
override fun getShape(
|
||||
state: BlockState,
|
||||
level: BlockGetter,
|
||||
pos: BlockPos,
|
||||
context: CollisionContext
|
||||
): VoxelShape {
|
||||
return SHAPE
|
||||
}
|
||||
|
||||
override fun getCollisionShape(
|
||||
state: BlockState,
|
||||
level: BlockGetter,
|
||||
pos: BlockPos,
|
||||
context: CollisionContext
|
||||
): VoxelShape {
|
||||
return super.getCollisionShape(state, level, pos, context)
|
||||
}
|
||||
|
||||
override fun updateShape(
|
||||
state: BlockState,
|
||||
direction: Direction,
|
||||
neighborState: BlockState,
|
||||
level: LevelAccessor,
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
return if (!state.canSurvive(level, pos)) {
|
||||
Blocks.AIR.defaultBlockState()
|
||||
} else {
|
||||
super.updateShape(state, direction, neighborState, level, pos, neighborPos)
|
||||
}
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(AXIS)
|
||||
}
|
||||
|
||||
override fun isPathfindable(
|
||||
state: BlockState,
|
||||
type: PathComputationType
|
||||
): Boolean = false
|
||||
|
||||
companion object {
|
||||
val AXIS: EnumProperty<Direction.Axis> = BlockStateProperties.AXIS
|
||||
|
||||
private val SHAPE: VoxelShape = Shapes.block()
|
||||
}
|
||||
|
||||
override fun fallOn(level: Level, state: BlockState, pos: BlockPos, entity: Entity, fallDistance: Float) {
|
||||
entity.causeFallDamage(fallDistance, 0.3f, level.damageSources().fall())
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonBlockTags
|
||||
import com.mojang.serialization.MapCodec
|
||||
@@ -17,7 +16,9 @@ import net.minecraft.core.Direction
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.tags.FluidTags
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import net.minecraft.world.level.Level
|
||||
@@ -30,7 +31,6 @@ import net.minecraft.world.level.block.SimpleWaterloggedBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties
|
||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf
|
||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||
import net.minecraft.world.level.block.state.properties.IntegerProperty
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
@@ -45,13 +45,13 @@ class HeartyGrainsBlock(settings: Properties) : CropBlock(settings), SimpleWater
|
||||
|
||||
override fun getMaxAge(): Int = MATURE_AGE
|
||||
|
||||
private val ageAfterHarvest = 4
|
||||
private val ageAfterHarvest = 3
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(AGE, HALF, WATERLOGGED)
|
||||
builder.add(AGE, PART, WATERLOGGED)
|
||||
}
|
||||
|
||||
override fun getBaseSeedId(): ItemLike = CobblemonItems.HEARTY_GRAINS
|
||||
override fun getBaseSeedId(): ItemLike = CobblemonItems.Hearty_Grains
|
||||
|
||||
override fun getShape(state: BlockState, world: BlockGetter, pos: BlockPos, context: CollisionContext): VoxelShape {
|
||||
return AGE_TO_SHAPE[this.getAge(state)]
|
||||
@@ -62,39 +62,45 @@ class HeartyGrainsBlock(settings: Properties) : CropBlock(settings), SimpleWater
|
||||
}
|
||||
|
||||
override fun randomTick(state: BlockState, world: ServerLevel, pos: BlockPos, random: RandomSource) {
|
||||
if (state.getValue(HALF) == DoubleBlockHalf.UPPER || !canGrow(world, pos, state)) return
|
||||
if (state.getValue(PART) == Part.UPPER || this.isMaxAge(state) || !canGrow(world, pos)) return
|
||||
|
||||
if (hasSufficientLight(world, pos) && random.nextInt(7) == 0) {
|
||||
grow(world, pos, state, 1)
|
||||
val lightLevel = world.getMaxLocalRawBrightness(pos)
|
||||
if (lightLevel >= 9 && random.nextInt(7) == 0) {
|
||||
val newAge = state.getValue(AGE) + 1
|
||||
world.setBlock(pos, state.setValue(AGE, newAge), UPDATE_CLIENTS)
|
||||
|
||||
if (newAge == MATURE_AGE) {
|
||||
val abovePos = pos.above()
|
||||
if (world.getBlockState(abovePos).isAir) {
|
||||
world.setBlock(
|
||||
abovePos,
|
||||
this.defaultBlockState().setValue(AGE, newAge).setValue(PART, Part.UPPER),
|
||||
UPDATE_CLIENTS
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun canGrow(world: LevelReader, pos: BlockPos, state: BlockState): Boolean {
|
||||
return !this.isMaxAge(state) && canSurvive(state, world, pos) && (state.getValue(HALF) == DoubleBlockHalf.UPPER || canGrowInto(world, pos.above()))
|
||||
}
|
||||
|
||||
private fun canGrowInto(world: LevelReader, pos: BlockPos): Boolean {
|
||||
val blockState = world.getBlockState(pos)
|
||||
return blockState.isAir || blockState.`is`(CobblemonBlocks.HEARTY_GRAINS)
|
||||
private fun canGrow(world: LevelReader, pos: BlockPos): Boolean {
|
||||
return canSurvive(defaultBlockState().setValue(PART, Part.LOWER), world, pos)
|
||||
}
|
||||
|
||||
override fun playerWillDestroy(world: Level, pos: BlockPos, state: BlockState, player: Player): BlockState {
|
||||
if (!world.isClientSide) {
|
||||
if (state.getValue(HALF) == DoubleBlockHalf.UPPER) {
|
||||
val belowPos = pos.below()
|
||||
val belowState = world.getBlockState(belowPos)
|
||||
world.destroyBlock(pos, true) // Break the lower block without drops
|
||||
world.setBlock(
|
||||
belowPos,
|
||||
belowState.setValue(AGE, ageAfterHarvest), // Reset age to simulate regrowth preparation
|
||||
UPDATE_CLIENTS
|
||||
)
|
||||
} else if (state.getValue(HALF) == DoubleBlockHalf.LOWER) {
|
||||
val abovePos = pos.above()
|
||||
val aboveState = world.getBlockState(abovePos)
|
||||
if (aboveState.block is HeartyGrainsBlock && aboveState.getValue(HALF) == DoubleBlockHalf.UPPER) {
|
||||
world.destroyBlock(abovePos, true) // Break the upper block without drops
|
||||
}
|
||||
if (state.getValue(PART) == Part.UPPER && state.block is HeartyGrainsBlock) {
|
||||
val belowPos = pos.below()
|
||||
val belowState = world.getBlockState(belowPos)
|
||||
world.destroyBlock(pos, true) // Break the lower block without drops
|
||||
world.setBlock(
|
||||
belowPos,
|
||||
belowState.setValue(AGE, ageAfterHarvest), // Reset age to simulate regrowth preparation
|
||||
UPDATE_CLIENTS
|
||||
)
|
||||
} else if (state.getValue(PART) == Part.LOWER) {
|
||||
val abovePos = pos.above()
|
||||
val aboveState = world.getBlockState(abovePos)
|
||||
if (aboveState.block is HeartyGrainsBlock && aboveState.getValue(PART) == Part.UPPER) {
|
||||
world.destroyBlock(abovePos, true) // Break the upper block without drops
|
||||
}
|
||||
}
|
||||
return super.playerWillDestroy(world, pos, state, player)
|
||||
@@ -121,42 +127,22 @@ class HeartyGrainsBlock(settings: Properties) : CropBlock(settings), SimpleWater
|
||||
)
|
||||
}
|
||||
|
||||
override fun isValidBonemealTarget(level: LevelReader, pos: BlockPos, state: BlockState): Boolean {
|
||||
val posAndState = getLowerHalf(level, pos, state)
|
||||
return if (posAndState == null) false else this.canGrow(
|
||||
level,
|
||||
posAndState.first,
|
||||
posAndState.second
|
||||
)
|
||||
override fun isValidBonemealTarget(world: LevelReader, pos: BlockPos, state: BlockState): Boolean {
|
||||
return !this.isMaxAge(state) && state.getValue(PART) == Part.LOWER
|
||||
}
|
||||
|
||||
override fun performBonemeal(level: ServerLevel, random: RandomSource, pos: BlockPos, state: BlockState) {
|
||||
val posAndState = getLowerHalf(level, pos, state)
|
||||
if (posAndState != null) {
|
||||
grow(level, posAndState.first, posAndState.second, getBonemealAgeIncrease(level))
|
||||
}
|
||||
}
|
||||
override fun growCrops(world: Level, pos: BlockPos, state: BlockState) {
|
||||
if (!canGrow(world, pos)) return
|
||||
|
||||
fun grow(world: Level, pos: BlockPos, state: BlockState, increment: Int) {
|
||||
if (!canGrow(world, pos, state)) return
|
||||
|
||||
val newAge = (this.getAge(state) + increment).coerceAtMost(this.maxAge)
|
||||
val newAge = (this.getAge(state) + this.getBonemealAgeIncrease(world)).coerceAtMost(this.maxAge)
|
||||
world.setBlock(pos, state.setValue(this.ageProperty, newAge), UPDATE_CLIENTS)
|
||||
|
||||
if (newAge >= 5) {
|
||||
if (newAge == MATURE_AGE && state.getValue(PART) == Part.LOWER) {
|
||||
val abovePos = pos.above()
|
||||
val stateAbove = world.getBlockState(abovePos)
|
||||
if (stateAbove.isAir) {
|
||||
if (world.getBlockState(abovePos).isAir) {
|
||||
world.setBlock(
|
||||
abovePos,
|
||||
this.defaultBlockState().setValue(AGE, newAge).setValue(HALF, DoubleBlockHalf.UPPER),
|
||||
UPDATE_CLIENTS
|
||||
)
|
||||
}
|
||||
else if (stateAbove.getValue(HALF) == DoubleBlockHalf.UPPER) {
|
||||
world.setBlock(
|
||||
abovePos,
|
||||
stateAbove.setValue(AGE, newAge),
|
||||
this.defaultBlockState().setValue(AGE, newAge).setValue(PART, Part.UPPER),
|
||||
UPDATE_CLIENTS
|
||||
)
|
||||
}
|
||||
@@ -166,8 +152,8 @@ class HeartyGrainsBlock(settings: Properties) : CropBlock(settings), SimpleWater
|
||||
override fun getBonemealAgeIncrease(world: Level): Int = 1
|
||||
|
||||
override fun canSurvive(state: BlockState, world: LevelReader, pos: BlockPos): Boolean {
|
||||
return when (state.getValue(HALF)) {
|
||||
DoubleBlockHalf.LOWER -> {
|
||||
return when (state.getValue(PART)) {
|
||||
Part.LOWER -> {
|
||||
val floor = world.getBlockState(pos.below())
|
||||
val fluidState = world.getFluidState(pos)
|
||||
|
||||
@@ -184,57 +170,45 @@ class HeartyGrainsBlock(settings: Properties) : CropBlock(settings), SimpleWater
|
||||
// Check for valid soil or survival conditions
|
||||
isSubmergedInWater || isWaterlogged || isNearWater || floor.`is`(CobblemonBlockTags.HEARTY_GRAINS_PLANTABLE) || floor.`is`(Blocks.MUD) || floor.`is`(Blocks.FARMLAND)
|
||||
}
|
||||
DoubleBlockHalf.UPPER -> {
|
||||
getLowerHalf(world, pos, state) != null
|
||||
Part.UPPER -> {
|
||||
val below = world.getBlockState(pos.below())
|
||||
below.block is HeartyGrainsBlock && below.getValue(PART) == Part.LOWER
|
||||
// Upper part survives only if the lower part is valid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLowerHalf(level: LevelReader, pos: BlockPos, state: BlockState): Pair<BlockPos, BlockState>? {
|
||||
if (isLower(state)) {
|
||||
return Pair(pos, state)
|
||||
} else {
|
||||
val blockPos = pos.below()
|
||||
val blockState = level.getBlockState(blockPos)
|
||||
return if (isLower(blockState)) Pair(
|
||||
blockPos,
|
||||
blockState
|
||||
) else null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isLower(state: BlockState): Boolean =
|
||||
state.`is`(CobblemonBlocks.HEARTY_GRAINS) && state.getValue(HALF) == DoubleBlockHalf.LOWER
|
||||
|
||||
|
||||
|
||||
override fun codec(): MapCodec<out CropBlock> = CODEC
|
||||
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::HeartyGrainsBlock)
|
||||
const val MATURE_AGE = 7
|
||||
const val MATURE_AGE = 4
|
||||
val WATERLOGGED = BlockStateProperties.WATERLOGGED
|
||||
val AGE: IntegerProperty = BlockStateProperties.AGE_7
|
||||
val HALF: EnumProperty<DoubleBlockHalf> = BlockStateProperties.DOUBLE_BLOCK_HALF
|
||||
val AGE: IntegerProperty = BlockStateProperties.AGE_4
|
||||
val PART: EnumProperty<Part> = EnumProperty.create("part", Part::class.java)
|
||||
|
||||
val AGE_TO_SHAPE = arrayOf(
|
||||
box(0.0, 0.0, 0.0, 16.0, 3.0, 16.0), // Stage 0
|
||||
box(0.0, 0.0, 0.0, 16.0, 5.0, 16.0), // Stage 1
|
||||
box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0), // Stage 2
|
||||
box(0.0, 0.0, 0.0, 16.0, 10.0, 16.0), // Stage 3
|
||||
box(0.0, 0.0, 0.0, 16.0, 16.0, 16.0), // Stage 4
|
||||
box(0.0, 0.0, 0.0, 16.0, 16.0, 16.0), // Stage 5
|
||||
box(0.0, 0.0, 0.0, 16.0, 16.0, 16.0), // Stage 6
|
||||
box(0.0, 0.0, 0.0, 16.0, 16.0, 16.0) // Stage 7
|
||||
box(2.0, 0.0, 0.0, 16.0, 17.0, 16.0), // Stage 1
|
||||
box(2.0, 0.0, 0.0, 16.0, 17.0, 16.0), // Stage 2
|
||||
box(2.0, 0.0, 0.0, 16.0, 17.0, 16.0), // Stage 3
|
||||
box(2.0, 0.0, 0.0, 16.0, 17.0, 16.0), // Stage 4 (Bottom)
|
||||
box(2.0, 0.0, 0.0, 16.0, 17.0, 16.0) // Stage 5 (Bottom)
|
||||
)
|
||||
}
|
||||
|
||||
enum class Part : StringRepresentable {
|
||||
LOWER, UPPER;
|
||||
|
||||
override fun getSerializedName(): String = name.lowercase()
|
||||
}
|
||||
|
||||
init {
|
||||
this.registerDefaultState(
|
||||
this.stateDefinition.any()
|
||||
.setValue(AGE, 0)
|
||||
.setValue(HALF, DoubleBlockHalf.LOWER)
|
||||
.setValue(PART, Part.LOWER)
|
||||
.setValue(WATERLOGGED, false)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,12 +19,7 @@ import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.LevelReader
|
||||
@@ -34,7 +29,6 @@ import net.minecraft.world.level.block.BonemealableBlock
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.gameevent.GameEvent
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
|
||||
@Suppress("OVERRIDE_DEPRECATION", "UNUSED_PARAMETER", "MemberVisibilityCanBePrivate", "DEPRECATION")
|
||||
abstract class RootBlock(settings: Properties) : Block(settings), BonemealableBlock, ShearableBlock {
|
||||
@@ -48,23 +42,6 @@ abstract class RootBlock(settings: Properties) : Block(settings), BonemealableBl
|
||||
}
|
||||
}
|
||||
|
||||
override fun useWithoutItem(
|
||||
state: BlockState,
|
||||
world: Level,
|
||||
pos: BlockPos,
|
||||
player: Player,
|
||||
blockHitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
val stack = player.getItemInHand(InteractionHand.MAIN_HAND)
|
||||
if (stack.`is`(Items.SHEARS)) {
|
||||
this.attemptShear(world, state, pos) {
|
||||
stack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND)
|
||||
}
|
||||
return InteractionResult.sidedSuccess(world.isClientSide)
|
||||
}
|
||||
return super.useWithoutItem(state, world, pos, player, blockHitResult)
|
||||
}
|
||||
|
||||
fun hasReachedSpreadCap(world: Level, pos: BlockPos): Boolean {
|
||||
var nearby = 0
|
||||
val nearbyPositions = BlockPos.betweenClosed(pos.offset(-4, -1, -4), pos.offset(4, 1, 4)).iterator()
|
||||
@@ -90,8 +67,7 @@ abstract class RootBlock(settings: Properties) : Block(settings), BonemealableBl
|
||||
pos: BlockPos,
|
||||
neighborPos: BlockPos
|
||||
): BlockState {
|
||||
return if (direction == Direction.UP && !this.canSurvive(state, world, pos)) Blocks.AIR.defaultBlockState()
|
||||
else super.updateShape(state, direction, neighborState, world, pos, neighborPos)
|
||||
return if (direction == Direction.UP && !this.canSurvive(state, world, pos)) Blocks.AIR.defaultBlockState() else super.updateShape(state, direction, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun isValidBonemealTarget(world: LevelReader, pos: BlockPos, state: BlockState) = this.canSpread(world, pos, state)
|
||||
@@ -141,7 +117,6 @@ abstract class RootBlock(settings: Properties) : Block(settings), BonemealableBl
|
||||
popResource(world, pos, shearedDrop)
|
||||
}
|
||||
world.gameEvent(null, GameEvent.SHEAR, pos)
|
||||
successCallback.invoke()
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -175,12 +150,12 @@ abstract class RootBlock(settings: Properties) : Block(settings), BonemealableBl
|
||||
/**
|
||||
* Picks the [BlockState] that results from a spread of this block.
|
||||
*
|
||||
* @param random The [RandomSource] instance used during a spread attempt.
|
||||
* @param random The [Random] instance used during a spread attempt.
|
||||
* @return The [BlockState] that will represent the spread root.
|
||||
*/
|
||||
protected fun spreadingRoot(random: RandomSource): BlockState =
|
||||
if (random.nextFloat() < Cobblemon.config.energyRootChance) CobblemonBlocks.ENERGY_ROOT.defaultBlockState()
|
||||
else CobblemonBlocks.BIG_ROOT.defaultBlockState()
|
||||
else this.defaultBlockState()
|
||||
|
||||
/**
|
||||
* Checks if the given coordinates allow for a root to be placed with some context.
|
||||
@@ -194,7 +169,7 @@ abstract class RootBlock(settings: Properties) : Block(settings), BonemealableBl
|
||||
protected fun canGoOn(state: BlockState, world: LevelReader, pos: BlockPos, ceilingValidator: (ceiling: BlockState) -> Boolean): Boolean {
|
||||
val up = pos.above()
|
||||
val upState = world.getBlockState(up)
|
||||
return upState.isFaceSturdy(world, up, Direction.DOWN) && ceilingValidator(upState)
|
||||
return upState.isFaceSturdy(world, up, Direction.DOWN) && ceilingValidator(upState) // todo (techdaan): ensure this is the right mapping
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,65 +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.block
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import net.minecraft.world.level.block.CarpetBlock
|
||||
|
||||
class TatamiBlock(settings: Properties) : Block(settings) {
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HORIZONTAL_FACING, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
|
||||
return defaultBlockState().setValue(HORIZONTAL_FACING, blockPlaceContext.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HORIZONTAL_FACING)
|
||||
}
|
||||
|
||||
override fun getShape(
|
||||
state: BlockState,
|
||||
blockGetter: BlockGetter,
|
||||
pos: BlockPos,
|
||||
collisionContext: CollisionContext
|
||||
): VoxelShape {
|
||||
return HITBOX
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun rotate(state: BlockState, rotation: Rotation): BlockState {
|
||||
return state.setValue(HORIZONTAL_FACING, rotation.rotate(state.getValue(HORIZONTAL_FACING)))
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun isPathfindable(state: BlockState, type: PathComputationType): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::TatamiBlock)
|
||||
|
||||
val HITBOX = Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0, 1.0)
|
||||
}
|
||||
}
|
||||
@@ -1,65 +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.block
|
||||
|
||||
import com.mojang.serialization.MapCodec
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties.HORIZONTAL_FACING
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import net.minecraft.world.level.block.CarpetBlock
|
||||
|
||||
class TatamiMatBlock(settings: Properties) : CarpetBlock(settings) {
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any()
|
||||
.setValue(HORIZONTAL_FACING, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
|
||||
return defaultBlockState().setValue(HORIZONTAL_FACING, blockPlaceContext.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HORIZONTAL_FACING)
|
||||
}
|
||||
|
||||
override fun getShape(
|
||||
state: BlockState,
|
||||
blockGetter: BlockGetter,
|
||||
pos: BlockPos,
|
||||
collisionContext: CollisionContext
|
||||
): VoxelShape {
|
||||
return HITBOX
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun rotate(state: BlockState, rotation: Rotation): BlockState {
|
||||
return state.setValue(HORIZONTAL_FACING, rotation.rotate(state.getValue(HORIZONTAL_FACING)))
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun isPathfindable(state: BlockState, type: PathComputationType): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::TatamiMatBlock)
|
||||
|
||||
val HITBOX = Shapes.box(0.0, 0.0, 0.0, 1.0, 0.0625, 1.0)
|
||||
}
|
||||
}
|
||||
+1
-15
@@ -12,7 +12,6 @@ import com.cobblemon.mod.common.CobblemonMenuType
|
||||
import com.cobblemon.mod.common.CobblemonRecipeTypes
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.block.entity.CampfireBlockEntity
|
||||
import com.cobblemon.mod.common.client.tooltips.itemTakesSeasoningData
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase
|
||||
import net.minecraft.recipebook.ServerPlaceRecipe
|
||||
@@ -110,15 +109,11 @@ class CookingPotMenu : RecipeBookMenu<CraftingInput, CookingPotRecipeBase>, Cont
|
||||
}
|
||||
|
||||
override fun handlePlacement(placeAll: Boolean, recipe: RecipeHolder<*>, player: ServerPlayer) {
|
||||
// Check if the recipe value implements CookingPotRecipeBase
|
||||
val recipeValue = recipe.value()
|
||||
if (recipeValue is CookingPotRecipeBase) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val castedRecipe = recipe as RecipeHolder<CookingPotRecipeBase>
|
||||
|
||||
// Save seasoning contents in case the next recipe absorbs seasoning data
|
||||
val seasoningSlots = CampfireBlockEntity.SEASONING_SLOTS
|
||||
val preservedSeasonings = seasoningSlots.map { container.getItem(it).copy() }
|
||||
|
||||
this.beginPlacingRecipe()
|
||||
try {
|
||||
val serverPlaceRecipe = ServerPlaceRecipe(this)
|
||||
@@ -126,15 +121,6 @@ class CookingPotMenu : RecipeBookMenu<CraftingInput, CookingPotRecipeBase>, Cont
|
||||
} finally {
|
||||
this.finishPlacingRecipe(castedRecipe)
|
||||
}
|
||||
|
||||
// Check if new result item supports seasoning
|
||||
val result = castedRecipe.value().result
|
||||
if (itemTakesSeasoningData(result)) {
|
||||
seasoningSlots.forEachIndexed { index, slot ->
|
||||
container.setItem(slot, preservedSeasonings[index])
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
throw IllegalArgumentException("Unsupported recipe type: ${recipeValue::class.java.name}")
|
||||
}
|
||||
|
||||
+1
-3
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.block.campfirepot
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.entity.player.Player
|
||||
@@ -24,9 +23,8 @@ class CookingPotResultSlot(
|
||||
) : Slot(container, index, x, y) {
|
||||
|
||||
override fun onTake(player: Player, stack: ItemStack) {
|
||||
stack.set(CobblemonItemComponents.CRAFTED, true)
|
||||
|
||||
val menu = player.containerMenu
|
||||
|
||||
if (menu is CookingPotMenu) {
|
||||
menu.broadcastChanges()
|
||||
player.playNotifySound(CobblemonSounds.CAMPFIRE_POT_USE, SoundSource.MASTER, 1.0f, 1.0f)
|
||||
|
||||
-10
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.api.pasture.PastureLinkManager
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.textClickHandlers
|
||||
import com.cobblemon.mod.common.block.PastureBlock
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
@@ -97,15 +96,6 @@ class PokemonPastureBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
if (blockEntity.ticksUntilCheck <= 0) {
|
||||
blockEntity.checkPokemon()
|
||||
}
|
||||
|
||||
// for every tethered pokemon tick metabolism if fullness is above 0
|
||||
val tetheredPokemonList = blockEntity.tetheredPokemon.filter { it.getPokemon() != null }
|
||||
for (tetheredPokemon in tetheredPokemonList) {
|
||||
val pokemon = tetheredPokemon.getPokemon()!!
|
||||
if (pokemon.currentFullness > 0) {
|
||||
pokemon.tickMetabolism()
|
||||
}
|
||||
}
|
||||
blockEntity.togglePastureOn(blockEntity.getInRangeViewerCount(world, blockEntity.blockPos) > 0)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -118,17 +118,17 @@ class RestorationTankBlockEntity(
|
||||
}
|
||||
|
||||
override fun getSlotsForFace(side: Direction): IntArray {
|
||||
return intArrayOf(0, 1, 2, 3, 4, 5, 6, 7)
|
||||
return if (side == Direction.DOWN) intArrayOf(0, 1, 2, 3, 4, 5, 6, 7) else intArrayOf()
|
||||
}
|
||||
|
||||
override fun canPlaceItemThroughFace(slot: Int, stack: ItemStack, direction: Direction?): Boolean {
|
||||
if (tankEntity.multiblockStructure is FossilMultiblockStructure) {
|
||||
if (direction != Direction.DOWN) {
|
||||
val structure = tankEntity.multiblockStructure as FossilMultiblockStructure
|
||||
val canUtilize = stack.let { NaturalMaterials.isNaturalMaterial(it) }
|
||||
val canUtilize = stack?.let { NaturalMaterials.isNaturalMaterial(it) } == true
|
||||
&& structure.organicMaterialInside < FossilMultiblockStructure.MATERIAL_TO_START
|
||||
&& !structure.hasCreatedPokemon
|
||||
val returnItem = NaturalMaterials.getReturnItem(stack) ?: return canUtilize
|
||||
&& structure.hasCreatedPokemon
|
||||
val returnItem = NaturalMaterials.getReturnItem(stack!!) ?: return canUtilize
|
||||
if (canUtilize) {
|
||||
// See if there's room
|
||||
for (i in items.indices) {
|
||||
|
||||
@@ -170,12 +170,13 @@ object CobblemonClient {
|
||||
|
||||
private fun registerTooltipManagers() {
|
||||
TooltipManager.registerTooltipGenerator(CobblemonTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(RecipeSeasoningAbsorbtionTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(FishingBaitTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(SeasoningTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(FishingRodTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(SeasoningTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(AprijuiceTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(PokePuffTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(FoodTooltipGenerator)
|
||||
TooltipManager.registerTooltipGenerator(MobEffectTooltipGenerator)
|
||||
}
|
||||
|
||||
fun registerFlywheelRenderers() {
|
||||
@@ -218,13 +219,6 @@ object CobblemonClient {
|
||||
CobblemonBlocks.RED_APRICORN_SAPLING,
|
||||
CobblemonBlocks.WHITE_APRICORN_SAPLING,
|
||||
CobblemonBlocks.YELLOW_APRICORN_SAPLING,
|
||||
CobblemonBlocks.POTTED_BLACK_APRICORN_SAPLING,
|
||||
CobblemonBlocks.POTTED_BLUE_APRICORN_SAPLING,
|
||||
CobblemonBlocks.POTTED_GREEN_APRICORN_SAPLING,
|
||||
CobblemonBlocks.POTTED_PINK_APRICORN_SAPLING,
|
||||
CobblemonBlocks.POTTED_RED_APRICORN_SAPLING,
|
||||
CobblemonBlocks.POTTED_WHITE_APRICORN_SAPLING,
|
||||
CobblemonBlocks.POTTED_YELLOW_APRICORN_SAPLING,
|
||||
CobblemonBlocks.BLACK_APRICORN,
|
||||
CobblemonBlocks.BLUE_APRICORN,
|
||||
CobblemonBlocks.GREEN_APRICORN,
|
||||
@@ -274,7 +268,6 @@ object CobblemonClient {
|
||||
CobblemonBlocks.SACCHARINE_HANGING_SIGN,
|
||||
CobblemonBlocks.SACCHARINE_WALL_HANGING_SIGN,
|
||||
CobblemonBlocks.SACCHARINE_SAPLING,
|
||||
CobblemonBlocks.POTTED_SACCHARINE_SAPLING,
|
||||
CobblemonBlocks.LURE_CAKE,
|
||||
CobblemonBlocks.POKE_CAKE,
|
||||
CobblemonBlocks.LECTERN,
|
||||
|
||||
+4
-9
@@ -15,8 +15,6 @@ import com.cobblemon.mod.common.api.pokemon.feature.SynchronizedSpeciesFeaturePr
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.italicise
|
||||
import com.cobblemon.mod.common.api.text.onHover
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
@@ -90,10 +88,6 @@ class StatWidget(
|
||||
private val speedLabel = lang("ui.stats.speed")
|
||||
}
|
||||
|
||||
var effectiveBattleIVs: Map<Stat, Int> = Stats.PERMANENT.associateWith { stat ->
|
||||
pokemon.ivs.getEffectiveBattleIV(stat)
|
||||
}
|
||||
|
||||
var statTabIndex = tabIndex
|
||||
val renderableFeatures = SpeciesFeatures
|
||||
.getFeaturesFor(pokemon.species)
|
||||
@@ -357,6 +351,7 @@ class StatWidget(
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
|
||||
when (statOptions.get(statTabIndex)) {
|
||||
STATS -> drawStatHexagon(
|
||||
mapOf(
|
||||
@@ -371,7 +366,7 @@ class StatWidget(
|
||||
maximum = 400
|
||||
)
|
||||
IV -> drawStatHexagon(
|
||||
effectiveBattleIVs,
|
||||
pokemon.ivs.associate { it.key to it.value },
|
||||
colour = Vector3f(216F/255, 100F/255, 1F),
|
||||
maximum = 31
|
||||
)
|
||||
@@ -499,9 +494,9 @@ class StatWidget(
|
||||
}
|
||||
|
||||
private fun getStatValueAsText(stat: Stat): MutableComponent {
|
||||
val value = when (statOptions.get(statTabIndex)) {
|
||||
val value = when(statOptions.get(statTabIndex)) {
|
||||
STATS -> if (stat == Stats.HP) "${pokemon.currentHealth} / ${pokemon.maxHealth}" else pokemon.getStat(stat).toString()
|
||||
IV -> if (pokemon.ivs.isHyperTrained(stat)) "${pokemon.ivs[stat]} (${pokemon.ivs.hyperTrainedIVs[stat]})" else pokemon.ivs[stat].toString()
|
||||
IV -> pokemon.ivs.getOrDefault(stat).toString()
|
||||
EV -> pokemon.evs.getOrDefault(stat).toString()
|
||||
else -> "0"
|
||||
}
|
||||
|
||||
+1
-1
@@ -102,4 +102,4 @@ class WailordModel(root: ModelPart) : PokemonPosableModel(root) {
|
||||
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, sleep, battleidle)) bedrockStateful("wailord", "faint") else
|
||||
if (state.isPosedIn(floating, swimming)) bedrockStateful("wailord", "faint_water")
|
||||
else null
|
||||
}
|
||||
}
|
||||
+2
-4
@@ -58,10 +58,8 @@ object MountedPlayerRenderer {
|
||||
|
||||
val offset = Vector3f(0f, player.bbHeight / 2, 0f).mul(-1f)
|
||||
|
||||
if (entity.beamMode == 0) {
|
||||
matrix.rotate(locator.matrix.getRotation(AxisAngle4f()))
|
||||
matrix.rotate(Axis.YP.rotationDegrees(180 + yBodyRot))
|
||||
}
|
||||
matrix.rotate(locator.matrix.getRotation(AxisAngle4f()))
|
||||
matrix.rotate(Axis.YP.rotationDegrees(180 + yBodyRot))
|
||||
matrix.translate(offset)
|
||||
|
||||
matrix.translate(Vector3f(0f, 0.35f, 0f))
|
||||
|
||||
+2
-3
@@ -144,7 +144,7 @@ class PokemonRenderer(
|
||||
|
||||
|
||||
if (entity.passengers.isNotEmpty()) {
|
||||
renderRiding(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
|
||||
renderRiding(entity, partialTicks, poseMatrix, buffer, packedLight)
|
||||
}
|
||||
else {
|
||||
super.render(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
|
||||
@@ -173,7 +173,6 @@ class PokemonRenderer(
|
||||
|
||||
fun renderRiding(
|
||||
entity: PokemonEntity,
|
||||
entityYaw: Float,
|
||||
partialTicks: Float,
|
||||
poseMatrix: PoseStack,
|
||||
buffer: MultiBufferSource,
|
||||
@@ -201,7 +200,7 @@ class PokemonRenderer(
|
||||
matrix.mul(transformationMatrix)
|
||||
}
|
||||
|
||||
super.render(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
|
||||
super.render(entity, 0f, partialTicks, poseMatrix, buffer, packedLight)
|
||||
poseMatrix.popPose()
|
||||
}
|
||||
|
||||
|
||||
+6
-3
@@ -9,14 +9,17 @@
|
||||
package com.cobblemon.mod.common.client.tooltips
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.item.AprijuiceItem
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object AprijuiceTooltipGenerator : TooltipGenerator() {
|
||||
override fun generateCategoryTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
if (stack.item !is AprijuiceItem) return null
|
||||
return mutableListOf(seasoningHeader)
|
||||
}
|
||||
|
||||
override fun generateAdditionalTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
if (stack.item !is AprijuiceItem) return null
|
||||
|
||||
@@ -27,7 +30,7 @@ object AprijuiceTooltipGenerator : TooltipGenerator() {
|
||||
val quality = flavourComponent.getQuality()
|
||||
resultLines.add(lang("cooking.cooking_quality", quality.getLang()))
|
||||
|
||||
SeasoningTooltipGenerator.generateAdditionalTooltip(stack, lines)
|
||||
resultLines.addAll(generateAdditionalFlavorTooltip(flavourComponent.flavours))
|
||||
|
||||
return resultLines
|
||||
}
|
||||
|
||||
+78
-1
@@ -28,8 +28,15 @@ import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object FishingBaitTooltipGenerator : TooltipGenerator() {
|
||||
private val fishingBaitHeader by lazy { lang("fishing_bait_effect_header").blue() }
|
||||
private val fishingBaitItemClass by lazy { lang("item_class.fishing_bait").blue() }
|
||||
|
||||
private val Genders = mapOf<Gender, Component>(
|
||||
Gender.MALE to lang("gender.male"),
|
||||
Gender.FEMALE to lang("gender.female"),
|
||||
Gender.GENDERLESS to lang("gender.genderless"),
|
||||
)
|
||||
|
||||
override fun generateCategoryTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
if (stack.get(DataComponents.HIDE_ADDITIONAL_TOOLTIP) != null) {
|
||||
return null
|
||||
@@ -46,7 +53,77 @@ object FishingBaitTooltipGenerator : TooltipGenerator() {
|
||||
}
|
||||
val resultLines = mutableListOf<Component>()
|
||||
|
||||
if (SpawnBaitEffects.isFishingBait(stack)) resultLines.add(this.fishingBaitItemClass)
|
||||
// Determine the FishingBait or combined effects from poke_bait
|
||||
val rawEffects = mutableListOf<SpawnBait.Effect>().apply {
|
||||
if (stack.item is PokerodItem) {
|
||||
addAll(SpawnBaitEffects.getEffectsFromRodItemStack(stack))
|
||||
} else {
|
||||
addAll(SpawnBaitEffects.getEffectsFromItemStack(stack))
|
||||
}
|
||||
|
||||
// Check for Seasoning-based Bait effects
|
||||
if (Seasonings.isSeasoning(stack)) {
|
||||
val seasoningEffects = Seasonings.getBaitEffectsFromItemStack(stack)
|
||||
if (seasoningEffects.isNotEmpty()) {
|
||||
addAll(seasoningEffects)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val baitEffects = SpawnBaitUtils.mergeEffects(rawEffects)
|
||||
|
||||
if (baitEffects.isEmpty()) return null
|
||||
|
||||
resultLines.add(this.fishingBaitHeader)
|
||||
|
||||
val formatter = DecimalFormat("0.##")
|
||||
|
||||
baitEffects.forEach { effect ->
|
||||
val effectType = effect.type.path.toString()
|
||||
val effectSubcategory = effect.subcategory?.path
|
||||
val effectChance = effect.chance * 100
|
||||
var effectValue = when (effectType) {
|
||||
"bite_time" -> (effect.value * 100).toInt()
|
||||
else -> effect.value.toInt()
|
||||
}
|
||||
|
||||
val subcategoryString: Component = if (effectSubcategory != null) {
|
||||
when (effectType) {
|
||||
"nature", "ev", "iv" -> com.cobblemon.mod.common.api.pokemon.stats.Stats.getStat(
|
||||
effectSubcategory
|
||||
).displayName
|
||||
|
||||
"gender_chance" -> Genders[Gender.valueOf(effectSubcategory.toUpperCase())]
|
||||
|
||||
"typing" -> ElementalTypes.get(effectSubcategory)?.displayName
|
||||
|
||||
"egg_group" -> {
|
||||
val effectSubcategory = effect.subcategory.path
|
||||
val eggGroup = effectSubcategory?.let { EggGroup.fromIdentifier(it) }
|
||||
eggGroup?.let {
|
||||
val langKey = "egg_group.${it.name.lowercase()}"
|
||||
lang(langKey)
|
||||
} ?: Component.literal(effectSubcategory ?: "Unknown").gold()
|
||||
}
|
||||
|
||||
else -> Component.empty()
|
||||
} ?: Component.literal("cursed").obfuscate()
|
||||
} else Component.literal("cursed").obfuscate()
|
||||
|
||||
// Adjust shiny chance effectValue
|
||||
if (effectType == "shiny_reroll") {
|
||||
effectValue++
|
||||
}
|
||||
|
||||
resultLines.add(
|
||||
lang(
|
||||
"fishing_bait_effects.$effectType.tooltip",
|
||||
Component.literal(formatter.format(effectChance)).yellow(),
|
||||
subcategoryString.copy().gold(),
|
||||
Component.literal(formatter.format(effectValue)).green()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return resultLines
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.tooltips
|
||||
|
||||
import com.cobblemon.mod.common.api.cooking.Flavour
|
||||
import com.cobblemon.mod.common.api.text.*
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
val seasoningHeader by lazy { lang("item_class.seasoning").blue() }
|
||||
private val flavorSubHeader by lazy { lang("seasoning_flavor_header").blue() }
|
||||
|
||||
fun generateAdditionalFlavorTooltip(flavours: Map<Flavour, Int>): MutableList<Component> {
|
||||
val resultLines = mutableListOf<Component>()
|
||||
resultLines.add(flavorSubHeader)
|
||||
|
||||
val combinedFlavorsLine = Component.literal("")
|
||||
flavours.forEach { (flavour, value) ->
|
||||
var flavourText = lang("seasoning_flavor.${flavour.name.lowercase()}").withStyle(flavour.chatFormatting)
|
||||
|
||||
if (combinedFlavorsLine.string.isNotEmpty()) {
|
||||
combinedFlavorsLine.append(" ")
|
||||
}
|
||||
|
||||
combinedFlavorsLine.append(flavourText).append(" $value")
|
||||
}
|
||||
|
||||
resultLines.add(combinedFlavorsLine)
|
||||
return resultLines
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.tooltips
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object FoodTooltipGenerator : TooltipGenerator() {
|
||||
private val foodHeader by lazy { lang("item_class.food").blue() }
|
||||
|
||||
override fun generateCategoryTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
val food = stack.get(CobblemonItemComponents.FOOD) ?: return null
|
||||
return mutableListOf(foodHeader)
|
||||
}
|
||||
|
||||
override fun generateAdditionalTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
val food = stack.get(CobblemonItemComponents.FOOD) ?: return null
|
||||
|
||||
return mutableListOf(
|
||||
lang("tooltip.food.hunger", Component.literal("${food.hunger}").yellow()),
|
||||
lang("tooltip.food.saturation", Component.literal("%.2f".format(food.saturation)).green())
|
||||
)
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.tooltips
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.effect.MobEffectUtil
|
||||
|
||||
object MobEffectTooltipGenerator : TooltipGenerator() {
|
||||
private val effectHeader by lazy { lang("item_class.mob_effect").blue() }
|
||||
|
||||
override fun generateCategoryTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
val effects = stack.get(CobblemonItemComponents.MOB_EFFECTS)?.mobEffects ?: return null
|
||||
return if (effects.isNotEmpty()) mutableListOf(effectHeader) else null
|
||||
}
|
||||
|
||||
override fun generateAdditionalTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
val effects = stack.get(CobblemonItemComponents.MOB_EFFECTS)?.mobEffects ?: return null
|
||||
if (effects.isEmpty()) return null
|
||||
|
||||
val tickRate = Minecraft.getInstance().level?.tickRateManager()?.tickrate() ?: 20.0f
|
||||
val result = mutableListOf<Component>()
|
||||
|
||||
// Always add the header FIRST, even for additional tooltip
|
||||
result.add(effectHeader)
|
||||
|
||||
for (instance in effects) {
|
||||
val name = instance.effect.value().descriptionId
|
||||
val duration = MobEffectUtil.formatDuration(instance, 1.0f, tickRate) // Already a Component
|
||||
val amplifierRoman = getRomanNumeral(instance.amplifier + 1)
|
||||
|
||||
result.add(
|
||||
lang(
|
||||
"tooltip.mob_effect_entry",
|
||||
Component.translatable(name).yellow(),
|
||||
Component.literal(amplifierRoman).green(),
|
||||
duration.string.green()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getRomanNumeral(number: Int): String {
|
||||
if (number <= 0) return number.toString() // no Roman numeral for zero or negatives
|
||||
|
||||
val numerals = listOf(
|
||||
1000 to "M",
|
||||
900 to "CM",
|
||||
500 to "D",
|
||||
400 to "CD",
|
||||
100 to "C",
|
||||
90 to "XC",
|
||||
50 to "L",
|
||||
40 to "XL",
|
||||
10 to "X",
|
||||
9 to "IX",
|
||||
5 to "V",
|
||||
4 to "IV",
|
||||
1 to "I"
|
||||
)
|
||||
|
||||
var remaining = number
|
||||
val result = StringBuilder()
|
||||
|
||||
for ((value, numeral) in numerals) {
|
||||
while (remaining >= value) {
|
||||
result.append(numeral)
|
||||
remaining -= value
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString()
|
||||
}
|
||||
}
|
||||
+3
@@ -28,8 +28,11 @@ object PokePuffTooltipGenerator : TooltipGenerator() {
|
||||
override fun generateAdditionalTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
if (stack.item !is PokePuffItem) return null
|
||||
|
||||
// val flavourComponent = stack.get(CobblemonItemComponents.FLAVOUR) ?: return null
|
||||
val resultLines = mutableListOf<Component>()
|
||||
|
||||
// resultLines.addAll(generateAdditionalFlavorTooltip(flavourComponent.flavours))
|
||||
|
||||
val dominantFlavour = PokePuffUtils.getDominantFlavour(stack)
|
||||
if (dominantFlavour != null) {
|
||||
val friendshipLiked = PokePuffUtils.getFriendshipChangeLiked(stack)
|
||||
|
||||
-41
@@ -1,41 +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.tooltips
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.item.AprijuiceItem
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object RecipeSeasoningAbsorbtionTooltipGenerator : TooltipGenerator() {
|
||||
override fun generateCategoryTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
// Skip if this is a crafting result preview. Vera wanted to be able to give extra context to things not fully crafted for added guidance in crafting UIs
|
||||
if (stack.get(CobblemonItemComponents.CRAFTED) == true) {
|
||||
return mutableListOf()
|
||||
}
|
||||
|
||||
if (itemTakesSeasoningData(stack)) {
|
||||
val accepted = mutableListOf<Component>()
|
||||
|
||||
if (recipeUsesFlavor(stack)) accepted.add(flavorHeader)
|
||||
if (recipeUsesFood(stack)) accepted.add(foodHeader)
|
||||
if (recipeUsesMobEffect(stack)) accepted.add(mobEffectHeader)
|
||||
if (recipeUsesBaitEffect(stack)) accepted.add(baitEffectHeader)
|
||||
|
||||
if (accepted.isNotEmpty()) {
|
||||
return mutableListOf(generateSeasoningAbsorbtionTooltip(accepted))
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
+5
-81
@@ -8,97 +8,21 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.tooltips
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.text.blue
|
||||
import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
object SeasoningTooltipGenerator : TooltipGenerator() {
|
||||
override fun generateCategoryTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
val isSeasoningIngredient = Seasonings.isSeasoning(stack)
|
||||
val flavors = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours
|
||||
val food = stack.get(CobblemonItemComponents.FOOD)
|
||||
val baitEffects = stack.get(CobblemonItemComponents.BAIT_EFFECTS)?.effects
|
||||
val mobEffects = stack.get(CobblemonItemComponents.MOB_EFFECTS)?.mobEffects
|
||||
|
||||
val result = mutableListOf<Component>()
|
||||
|
||||
if (!isSeasoningIngredient && flavors == null && food == null && baitEffects == null && mobEffects == null) return null // exit early if there is nothing to show to save time
|
||||
|
||||
// This is where we label something as either an ingredient OR an item with Seasoning data. To help users know if something can be used IN the Pot or came FROM a pot at a glance
|
||||
|
||||
if (isSeasoningIngredient) {
|
||||
// Flavor
|
||||
if (Seasonings.hasFlavors(stack)) result.add(flavorSeasoningHeader)
|
||||
|
||||
// Food
|
||||
if (Seasonings.hasFood(stack)) result.add(foodSeasoningHeader)
|
||||
|
||||
// Mob Effects
|
||||
if (Seasonings.hasMobEffect(stack)) result.add(mobEffectSeasoningHeader)
|
||||
|
||||
// Bait Effects
|
||||
if (Seasonings.hasBaitEffects(stack)) result.add(baitEffectSeasoningHeader)
|
||||
} else { // these are output items that have Seasoning Component data on them
|
||||
// Flavor
|
||||
if (!flavors.isNullOrEmpty()) result.add(lang("seasoning_flavor_header").blue())
|
||||
|
||||
// Food
|
||||
if (food != null) result.add(lang("seasoning_food_header").blue())
|
||||
|
||||
// Mob Effects
|
||||
if (!mobEffects.isNullOrEmpty()) result.add(lang("seasoning_mob_effect_header").blue())
|
||||
|
||||
// Bait Effects
|
||||
if (!baitEffects.isNullOrEmpty()) result.add(lang("seasoning_bait_effect_header").blue())
|
||||
}
|
||||
|
||||
return if (result.isNotEmpty()) result else null
|
||||
if (!Seasonings.isSeasoning(stack)) return null
|
||||
return mutableListOf(seasoningHeader)
|
||||
}
|
||||
|
||||
override fun generateAdditionalTooltip(stack: ItemStack, lines: MutableList<Component>): MutableList<Component>? {
|
||||
if (stack.get(DataComponents.HIDE_ADDITIONAL_TOOLTIP) != null) {
|
||||
val flavors = Seasonings.getFlavoursFromItemStack(stack)
|
||||
if (flavors.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val isSeasoningIngredient = Seasonings.isSeasoning(stack)
|
||||
val flavors = stack.get(CobblemonItemComponents.FLAVOUR)?.flavours
|
||||
val food = stack.get(CobblemonItemComponents.FOOD)
|
||||
val baitEffects = stack.get(CobblemonItemComponents.BAIT_EFFECTS)?.effects
|
||||
val mobEffects = stack.get(CobblemonItemComponents.MOB_EFFECTS)?.mobEffects
|
||||
|
||||
if (!isSeasoningIngredient && flavors == null && food == null && baitEffects == null && mobEffects == null) return null // exit early if there is nothing to show to save time
|
||||
|
||||
val result = mutableListOf<Component>()
|
||||
|
||||
// this is where we want to replace the headers with the info and data for each seasoning category we want to show
|
||||
|
||||
// Flavor
|
||||
val flavorData = Seasonings.getFlavoursFromItemStack(stack).takeIf { !it.isNullOrEmpty() } ?: flavors
|
||||
|
||||
if (flavorData != null && flavorData.any { it.value != 0 }) {
|
||||
result.addAll(generateAdditionalFlavorTooltip(flavorData))
|
||||
}
|
||||
|
||||
// Food
|
||||
if (Seasonings.hasFood(stack) || food != null) {
|
||||
result.addAll(generateAdditionalFoodTooltip(stack))
|
||||
}
|
||||
|
||||
// Mob Effects
|
||||
if (Seasonings.hasMobEffect(stack) || mobEffects != null) {
|
||||
result.addAll(generateAdditionalMobEffectTooltip(stack))
|
||||
}
|
||||
|
||||
// Bait Effects
|
||||
if (Seasonings.hasBaitEffects(stack) || baitEffects != null) {
|
||||
result.addAll(generateAdditionalBaitEffectTooltip(stack))
|
||||
}
|
||||
|
||||
return if (result.isNotEmpty()) result else null
|
||||
return generateAdditionalFlavorTooltip(flavors)
|
||||
}
|
||||
}
|
||||
-301
@@ -1,301 +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.tooltips
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.CobblemonRecipeTypes
|
||||
import com.cobblemon.mod.common.api.cooking.Flavour
|
||||
import com.cobblemon.mod.common.api.cooking.Food
|
||||
import com.cobblemon.mod.common.api.cooking.PokePuffUtils
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBait
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBaitEffects
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBaitUtils
|
||||
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
|
||||
import com.cobblemon.mod.common.api.text.*
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.item.components.FoodComponent
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase
|
||||
import com.cobblemon.mod.common.item.interactive.PokerodItem
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.effect.MobEffectUtil
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.RecipeManager
|
||||
import net.minecraft.world.level.Level
|
||||
import java.text.DecimalFormat
|
||||
|
||||
val cookingPotRecipeAbsorbHeader by lazy { lang("item_class.cooking_pot_recipe_absorbs").gray() }
|
||||
val seasoningsHeader by lazy { lang("item_class.seasonings").gray() }
|
||||
val flavorSeasoningHeader by lazy { lang("item_class.flavor_seasoning").blue() }
|
||||
val flavorHeader by lazy { lang("seasoning_flavor_header").gray() }
|
||||
val flavorInfoSubHeader by lazy { lang("seasoning_flavor_info_header").blue() }
|
||||
val baitEffectSeasoningHeader by lazy { lang("item_class.bait_effect_seasoning").blue() }
|
||||
val baitEffectHeader by lazy { lang("seasoning_bait_effect_header").gray() }
|
||||
val baitEffectInfoSubHeader by lazy { lang("seasoning_bait_effect_info_header").blue() }
|
||||
val foodSeasoningHeader by lazy { lang("item_class.food_seasoning").blue() }
|
||||
val foodHeader by lazy { lang("seasoning_food_header").gray() }
|
||||
val foodInfoSubHeader by lazy { lang("seasoning_food_info_header").blue() }
|
||||
val mobEffectSeasoningHeader by lazy { lang("item_class.mob_effect_seasoning").blue() }
|
||||
val mobEffectHeader by lazy { lang("seasoning_mob_effect_header").gray() }
|
||||
val mobEffectInfoSubHeader by lazy { lang("seasoning_mob_effect_info_header").blue() }
|
||||
|
||||
private fun recipeUsesProcessor(stack: ItemStack, processorType: String): Boolean {
|
||||
val level = Minecraft.getInstance().level ?: return false
|
||||
val recipeManager = level.recipeManager
|
||||
|
||||
val allCookingRecipes = recipeManager.getAllRecipesFor(CobblemonRecipeTypes.COOKING_POT_COOKING) +
|
||||
recipeManager.getAllRecipesFor(CobblemonRecipeTypes.COOKING_POT_SHAPELESS)
|
||||
|
||||
return allCookingRecipes
|
||||
.any { recipe ->
|
||||
stack.item == recipe.value.result.item &&
|
||||
recipe.value.seasoningProcessors.any { it.type == processorType }
|
||||
}
|
||||
}
|
||||
|
||||
fun itemTakesSeasoningData(stack: ItemStack): Boolean {
|
||||
return recipeUsesFlavor(stack) || recipeUsesFood(stack) || recipeUsesMobEffect(stack) || recipeUsesBaitEffect(stack)
|
||||
}
|
||||
|
||||
fun recipeUsesFlavor(stack: ItemStack): Boolean {
|
||||
return recipeUsesProcessor(stack, "flavour")
|
||||
}
|
||||
|
||||
fun recipeUsesFood(stack: ItemStack): Boolean {
|
||||
return recipeUsesProcessor(stack, "food")
|
||||
}
|
||||
|
||||
fun recipeUsesMobEffect(stack: ItemStack): Boolean {
|
||||
return recipeUsesProcessor(stack, "mob_effects")
|
||||
}
|
||||
|
||||
fun recipeUsesBaitEffect(stack: ItemStack): Boolean {
|
||||
return recipeUsesProcessor(stack, "spawn_bait")
|
||||
}
|
||||
|
||||
fun generateSeasoningAbsorbtionTooltip(accepted: List<Component>): Component {
|
||||
if (accepted.isEmpty()) return Component.empty()
|
||||
if (accepted.size == 1) return lang("item_class.cooking_pot_recipe_absorbs")
|
||||
.append(" ").append(accepted[0]).append(" ")
|
||||
.append(seasoningsHeader).gray()
|
||||
|
||||
val result = Component.literal("")
|
||||
|
||||
result.append(lang("item_class.cooking_pot_recipe_absorbs")).append(" ").gray()
|
||||
|
||||
for ((index, component) in accepted.withIndex()) {
|
||||
when (index) {
|
||||
accepted.lastIndex -> {
|
||||
result.append("and ").append(component)
|
||||
}
|
||||
accepted.lastIndex - 1 -> {
|
||||
result.append(component).append(", ")
|
||||
}
|
||||
else -> {
|
||||
result.append(component).append(", ")
|
||||
}
|
||||
}
|
||||
if (index == accepted.lastIndex) {
|
||||
result.append(" ").append(seasoningsHeader).gray()
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun generateAdditionalFlavorTooltip(flavours: Map<Flavour, Int>): MutableList<Component> {
|
||||
val resultLines = mutableListOf<Component>()
|
||||
resultLines.add(flavorInfoSubHeader)
|
||||
|
||||
val combinedFlavorsLine = Component.literal("")
|
||||
flavours.filter { it.key != Flavour.MILD }.forEach { (flavour, value) ->
|
||||
var flavourText = lang("seasoning_flavor.${flavour.name.lowercase()}").withStyle(flavour.chatFormatting)
|
||||
|
||||
if (combinedFlavorsLine.string.isNotEmpty()) {
|
||||
combinedFlavorsLine.append(" ")
|
||||
}
|
||||
|
||||
combinedFlavorsLine.append(flavourText).append(" $value")
|
||||
}
|
||||
|
||||
resultLines.add(combinedFlavorsLine)
|
||||
return resultLines
|
||||
}
|
||||
|
||||
fun generateAdditionalMobEffectTooltip(stack: ItemStack): MutableList<Component> {
|
||||
val effects: List<MobEffectInstance> =
|
||||
Seasonings.getMobEffectsFromItemStack(stack)
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.map { it.toInstance() }
|
||||
?: stack.get(CobblemonItemComponents.MOB_EFFECTS)?.mobEffects
|
||||
?: return mutableListOf()
|
||||
|
||||
val tickRate = Minecraft.getInstance().level?.tickRateManager()?.tickrate() ?: 20.0f
|
||||
val resultLines = mutableListOf<Component>()
|
||||
|
||||
resultLines.add(mobEffectInfoSubHeader)
|
||||
|
||||
for (instance in effects) {
|
||||
val effect = instance.effect.value()
|
||||
val name = Component.translatable(effect.descriptionId)
|
||||
|
||||
val color = if (effect.isBeneficial) ChatFormatting.AQUA else ChatFormatting.RED
|
||||
val duration = MobEffectUtil.formatDuration(instance, 1.0f, tickRate)
|
||||
val amplifierRoman = getRomanNumeral(instance.amplifier + 1)
|
||||
|
||||
resultLines.add(
|
||||
lang(
|
||||
"tooltip.mob_effect_entry",
|
||||
name.copy().withStyle(color),
|
||||
Component.literal(amplifierRoman).withStyle(color),
|
||||
duration.string.green()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return resultLines
|
||||
}
|
||||
|
||||
fun generateAdditionalFoodTooltip(stack: ItemStack): MutableList<Component> {
|
||||
val food = Seasonings.getFoodComponentFromItemStack(stack) ?: stack.get(CobblemonItemComponents.FOOD)
|
||||
|
||||
val resultLines = mutableListOf<Component>()
|
||||
|
||||
if (food != null) {
|
||||
resultLines.add(foodInfoSubHeader)
|
||||
|
||||
resultLines.add(
|
||||
lang("tooltip.food.hunger", Component.literal("${food.hunger}").yellow())
|
||||
)
|
||||
|
||||
resultLines.add(
|
||||
lang("tooltip.food.saturation", Component.literal("%.2f".format(food.saturation)).green())
|
||||
)
|
||||
}
|
||||
|
||||
return resultLines
|
||||
}
|
||||
|
||||
fun generateAdditionalBaitEffectTooltip(stack: ItemStack): MutableList<Component> {
|
||||
val resultLines = mutableListOf<Component>()
|
||||
|
||||
val rawEffects = mutableListOf<SpawnBait.Effect>().apply {
|
||||
if (stack.item is PokerodItem) {
|
||||
addAll(SpawnBaitEffects.getEffectsFromRodItemStack(stack))
|
||||
} else {
|
||||
addAll(SpawnBaitEffects.getEffectsFromItemStack(stack))
|
||||
}
|
||||
|
||||
if (Seasonings.isSeasoning(stack)) {
|
||||
val seasoningEffects = Seasonings.getBaitEffectsFromItemStack(stack)
|
||||
if (seasoningEffects.isNotEmpty()) {
|
||||
addAll(seasoningEffects)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val baitEffects = SpawnBaitUtils.mergeEffects(rawEffects)
|
||||
|
||||
if (baitEffects.isNotEmpty()) {
|
||||
resultLines.add(baitEffectInfoSubHeader)
|
||||
|
||||
val formatter = DecimalFormat("0.##")
|
||||
|
||||
val genders = mapOf(
|
||||
Gender.MALE to lang("gender.male"),
|
||||
Gender.FEMALE to lang("gender.female"),
|
||||
Gender.GENDERLESS to lang("gender.genderless")
|
||||
)
|
||||
|
||||
for (effect in baitEffects) {
|
||||
val effectType = effect.type.path
|
||||
val effectSubcategory = effect.subcategory?.path
|
||||
val effectChance = effect.chance * 100
|
||||
var effectValue = when (effectType) {
|
||||
"bite_time" -> (effect.value * 100).toInt()
|
||||
else -> effect.value.toInt()
|
||||
}
|
||||
|
||||
val subcategoryString: Component = if (effectSubcategory != null) {
|
||||
when (effectType) {
|
||||
"nature", "ev", "iv" ->
|
||||
com.cobblemon.mod.common.api.pokemon.stats.Stats.getStat(effectSubcategory).displayName
|
||||
|
||||
"gender_chance" ->
|
||||
genders[Gender.valueOf(effectSubcategory.uppercase())]
|
||||
|
||||
"typing" ->
|
||||
ElementalTypes.get(effectSubcategory)?.displayName
|
||||
|
||||
"egg_group" -> {
|
||||
val eggGroup = EggGroup.fromIdentifier(effectSubcategory)
|
||||
eggGroup?.let {
|
||||
lang("egg_group.${it.name.lowercase()}")
|
||||
} ?: Component.literal(effectSubcategory).gold()
|
||||
}
|
||||
|
||||
else -> Component.empty()
|
||||
} ?: Component.literal("cursed").obfuscate()
|
||||
} else Component.literal("cursed").obfuscate()
|
||||
|
||||
if (effectType == "shiny_reroll") {
|
||||
effectValue++
|
||||
}
|
||||
|
||||
resultLines.add(
|
||||
lang(
|
||||
"fishing_bait_effects.$effectType.tooltip",
|
||||
Component.literal(formatter.format(effectChance)).yellow(),
|
||||
subcategoryString.copy().gold(),
|
||||
Component.literal(formatter.format(effectValue)).green()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return resultLines
|
||||
}
|
||||
|
||||
private fun getRomanNumeral(number: Int): String {
|
||||
if (number <= 0) return number.toString()
|
||||
|
||||
val numerals = listOf(
|
||||
1000 to "M",
|
||||
900 to "CM",
|
||||
500 to "D",
|
||||
400 to "CD",
|
||||
100 to "C",
|
||||
90 to "XC",
|
||||
50 to "L",
|
||||
40 to "XL",
|
||||
10 to "X",
|
||||
9 to "IX",
|
||||
5 to "V",
|
||||
4 to "IV",
|
||||
1 to "I"
|
||||
)
|
||||
|
||||
var remaining = number
|
||||
val result = StringBuilder()
|
||||
|
||||
for ((value, numeral) in numerals) {
|
||||
while (remaining >= value) {
|
||||
result.append(numeral)
|
||||
remaining -= value
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString()
|
||||
}
|
||||
@@ -1,120 +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.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.text.*
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands.literal
|
||||
import net.minecraft.commands.Commands.argument
|
||||
import net.minecraft.commands.arguments.EntityArgument
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
|
||||
object PcSearchCommand {
|
||||
|
||||
private const val NAME = "pcsearch"
|
||||
private const val PROPERTIES = "properties"
|
||||
private const val OTHER = "other"
|
||||
private val IN_BATTLE_EXCEPTION = SimpleCommandExceptionType(lang("pc.inbattle").red())
|
||||
|
||||
fun register(dispatcher: CommandDispatcher<CommandSourceStack>) {
|
||||
dispatcher.register(
|
||||
literal(NAME)
|
||||
.permission(CobblemonPermissions.PC_SEARCH)
|
||||
.then(
|
||||
argument(PROPERTIES, PokemonPropertiesArgumentType.properties())
|
||||
.executes { execute(it, it.source.playerOrException) }
|
||||
)
|
||||
.then(
|
||||
literal("other")
|
||||
.then(
|
||||
argument(OTHER, EntityArgument.player())
|
||||
.then(
|
||||
argument(PROPERTIES, PokemonPropertiesArgumentType.properties())
|
||||
.executes { execute(it, EntityArgument.getPlayer(it, OTHER)) }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatField(label: MutableComponent, value: MutableComponent): MutableComponent {
|
||||
return label.add(": ").aqua().add(value.yellow())
|
||||
}
|
||||
|
||||
private fun execute(context: CommandContext<CommandSourceStack>, player: ServerPlayer): Int {
|
||||
if (player.isInBattle()) {
|
||||
throw IN_BATTLE_EXCEPTION.create()
|
||||
}
|
||||
|
||||
val pokemonProperties = PokemonPropertiesArgumentType.getPokemonProperties(context, PROPERTIES)
|
||||
|
||||
val pc = player.pc()
|
||||
val matchingPokemon = mutableListOf<MutableComponent>()
|
||||
|
||||
pc.boxes.forEachIndexed { boxIndex, box ->
|
||||
val nonEmptySlots = box.getNonEmptySlots()
|
||||
|
||||
for ((slotIndex, pokemon) in nonEmptySlots) {
|
||||
if (pokemonProperties.matches(pokemon)) {
|
||||
val boxNumber = boxIndex + 1
|
||||
val displayName = pokemon.species.translatedName
|
||||
val level = pokemon.level
|
||||
|
||||
val baseText = commandLang("pcsearch.entry", displayName, lang("label.lv", level)).yellow()
|
||||
|
||||
val hoverText = Component.literal("")
|
||||
.add(formatField(lang("ui.info.species"), displayName))
|
||||
.add(" ").add(lang("label.lv", level))
|
||||
.add("\n").add(formatField(lang("ui.info.gender"), lang("gender.${pokemon.gender.name.lowercase()}")))
|
||||
.add("\n").add(formatField(lang("ui.info.nature"), pokemon.nature.displayName.asTranslated()))
|
||||
.add("\n").add(formatField(lang("ui.info.ability"), pokemon.ability.displayName.asTranslated()))
|
||||
.add("\n").add(lang("ui.stats.ivs").add(": ").aqua().add(
|
||||
"${pokemon.ivs[Stats.HP]}/${pokemon.ivs[Stats.ATTACK]}/${pokemon.ivs[Stats.DEFENCE]}/${pokemon.ivs[Stats.SPEED]}/${pokemon.ivs[Stats.SPECIAL_ATTACK]}/${pokemon.ivs[Stats.SPECIAL_DEFENCE]}".yellow()
|
||||
))
|
||||
.add("\n").add(lang("ui.stats.evs").add(": ").aqua().add(
|
||||
"${pokemon.evs[Stats.HP]}/${pokemon.evs[Stats.ATTACK]}/${pokemon.evs[Stats.DEFENCE]}/${pokemon.evs[Stats.SPEED]}/${pokemon.evs[Stats.SPECIAL_ATTACK]}/${pokemon.evs[Stats.SPECIAL_DEFENCE]}".yellow()
|
||||
))
|
||||
|
||||
if (pokemon.shiny) {
|
||||
hoverText.add("\n").add(commandLang("pcsearch.tooltip.shiny").gold())
|
||||
}
|
||||
|
||||
baseText.onHover(hoverText)
|
||||
|
||||
val locationText = commandLang("pcsearch.location", boxNumber, slotIndex + 1).green()
|
||||
.onHover(commandLang("pcsearch.takepokemon"))
|
||||
.suggest("/pctake ${player.name.string} $boxNumber ${slotIndex + 1}")
|
||||
|
||||
matchingPokemon.add(baseText.add(locationText))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingPokemon.isEmpty()) {
|
||||
context.source.sendSystemMessage(commandLang("pcsearch.nomatch", pokemonProperties.originalString, player.name.string))
|
||||
} else {
|
||||
context.source.sendSystemMessage(commandLang("pcsearch.found", player.name.string))
|
||||
matchingPokemon.forEach { result ->
|
||||
context.source.sendSystemMessage(result)
|
||||
}
|
||||
}
|
||||
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -1,98 +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.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCPosition
|
||||
import com.cobblemon.mod.common.api.storage.pc.POKEMON_PER_BOX
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
import net.minecraft.commands.arguments.EntityArgument
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object PcTakeCommand {
|
||||
private val IN_BATTLE_EXCEPTION = SimpleCommandExceptionType(lang("pc.inbattle").red())
|
||||
|
||||
fun register(dispatcher : CommandDispatcher<CommandSourceStack>) {
|
||||
val command = Commands.literal("pctake")
|
||||
.permission(CobblemonPermissions.TAKE_POKEMON)
|
||||
.then(
|
||||
Commands.argument("player", EntityArgument.player())
|
||||
.then(
|
||||
Commands.argument("box", IntegerArgumentType.integer(1))
|
||||
.then(
|
||||
Commands.argument("slot", IntegerArgumentType.integer(1, 30))
|
||||
.executes(::execute)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
dispatcher.register(command)
|
||||
}
|
||||
|
||||
private fun execute(context: CommandContext<CommandSourceStack>) : Int {
|
||||
val executor = context.source.entity as? ServerPlayer
|
||||
val target = EntityArgument.getPlayer(context, "player")
|
||||
return executeWithTarget(context, target, executor)
|
||||
}
|
||||
|
||||
private fun executeWithTarget(context: CommandContext<CommandSourceStack>, target: ServerPlayer, executor: ServerPlayer?) : Int {
|
||||
try {
|
||||
if (target.isInBattle()) {
|
||||
throw IN_BATTLE_EXCEPTION.create()
|
||||
}
|
||||
|
||||
val box = IntegerArgumentType.getInteger(context, "box")
|
||||
val slot = IntegerArgumentType.getInteger(context, "slot")
|
||||
val pc = target.pc()
|
||||
|
||||
if (box > POKEMON_PER_BOX) {
|
||||
context.source.sendFailure(commandLang("pctake.too_many_boxes", POKEMON_PER_BOX))
|
||||
return 0
|
||||
}
|
||||
|
||||
val boxIndex = box - 1
|
||||
val slotIndex = slot - 1
|
||||
|
||||
if (slotIndex < 0 || slotIndex >= POKEMON_PER_BOX) {
|
||||
context.source.sendFailure(commandLang("pctake.invalid_slot"))
|
||||
return 0
|
||||
}
|
||||
|
||||
val pokemon = pc.boxes[boxIndex][slotIndex]
|
||||
if (pokemon == null) {
|
||||
context.source.sendFailure(commandLang("pctake.no_pokemon", box, slot))
|
||||
return 0
|
||||
}
|
||||
|
||||
pc.remove(PCPosition(boxIndex, slotIndex))
|
||||
|
||||
if (executor != null && executor != target) {
|
||||
val toParty = executor.party()
|
||||
toParty.add(pokemon)
|
||||
context.source.sendSuccess({ commandLang("pctake.taken_other", pokemon.species.name, target.name.string) }, true)
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
|
||||
context.source.sendSuccess({ commandLang("pctake.removed", pokemon.species.name, box, slot) }, true)
|
||||
return Command.SINGLE_SUCCESS
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.mojang.datafixers.DSL.TypeReference
|
||||
import com.mojang.datafixers.DataFixer
|
||||
import com.mojang.datafixers.DataFixerBuilder
|
||||
import com.mojang.datafixers.schemas.Schema
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
@@ -27,10 +26,10 @@ import java.util.concurrent.Executors
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate", "unused")
|
||||
object CobblemonSchemas {
|
||||
private val SAME: (Int, Schema) -> Schema = ::Schema
|
||||
|
||||
private val RESULT: DataFixerBuilder.Result = this.create()
|
||||
|
||||
const val DATA_VERSION = 2
|
||||
const val DATA_VERSION = 1
|
||||
|
||||
/**
|
||||
* The Cobblemon [DataFixer].
|
||||
@@ -83,8 +82,6 @@ object CobblemonSchemas {
|
||||
builder.addFixer(ShoulderStateJsonFix(schema1))
|
||||
builder.addFixer(NicknameFix(schema1))
|
||||
builder.addFixer(RaisedPPStagesFix(schema1))
|
||||
val schema2 = builder.addSchema(2, SAME)
|
||||
builder.addFixer(HypertrainIVFix(schema2))
|
||||
}
|
||||
|
||||
private class CobblemonDataFixerCodec<R>(private val baseCodec: Codec<R>, private val typeReference: TypeReference) : Codec<R> {
|
||||
|
||||
@@ -1,27 +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.datafixer.fix
|
||||
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.mojang.datafixers.schemas.Schema
|
||||
import com.mojang.serialization.Dynamic
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
class HypertrainIVFix(outputSchema: Schema) : PokemonFix(outputSchema) {
|
||||
|
||||
override fun fixPokemonData(dynamic: Dynamic<*>): Dynamic<*> {
|
||||
var baseDynamic = dynamic
|
||||
val oldIVs = baseDynamic.get(DataKeys.POKEMON_IVS).get().result().getOrNull() ?: return baseDynamic
|
||||
baseDynamic = baseDynamic.remove(DataKeys.POKEMON_IVS)
|
||||
val newIVs = baseDynamic.createMap(mapOf(baseDynamic.createString(DataKeys.POKEMON_IVS_BASE) to oldIVs,
|
||||
baseDynamic.createString(DataKeys.POKEMON_IVS_HYPERTRAINED) to baseDynamic.createMap(emptyMap())))
|
||||
baseDynamic = baseDynamic.set(DataKeys.POKEMON_IVS, newIVs)
|
||||
return baseDynamic
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,6 @@ import net.minecraft.world.item.ItemUtils
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LightLayer
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.gameevent.GameEvent
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
@@ -785,10 +784,7 @@ open class PokemonEntity(
|
||||
pokemon = this.createSidedPokemon()
|
||||
health = 0F
|
||||
}
|
||||
} else if(pokemon.storeCoordinates.get() == null) {
|
||||
// when the vanilla /data merge command is used, it will also run through this load method
|
||||
// and if we are not careful here, the pokemon instance will get rebuilt from scratch
|
||||
// this will fuck with storages, as they are tied to these very pokemon instances and their observables
|
||||
} else {
|
||||
val ops = registryAccess().createSerializationContext(NbtOps.INSTANCE)
|
||||
pokemon = try {
|
||||
this.sidedCodec().decode(ops, nbt.getCompound(DataKeys.POKEMON)).orThrow.first
|
||||
@@ -991,6 +987,29 @@ open class PokemonEntity(
|
||||
player.setItemInHand(hand, milkBucket)
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
//Camerupt gives Lava Bucket if player uses Bucket on it
|
||||
else if (pokemon.species.name == "Camerupt" && pokemon.lastMilked >= 900) {
|
||||
player.playSound(SoundEvents.GOAT_MILK, 1.0f, 1.0f)
|
||||
val lavaBucket = ItemUtils.createFilledResult(itemStack, player, Items.LAVA_BUCKET.defaultInstance)
|
||||
player.setItemInHand(hand, lavaBucket)
|
||||
pokemon.milk()
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
//Gogoat gives Milk Bucket if player uses Bucket on it
|
||||
else if (pokemon.species.name == "Gogoat" && pokemon.gender.name == "FEMALE") {
|
||||
player.playSound(SoundEvents.GOAT_MILK, 1.0f, 1.0f)
|
||||
val milkBucket = ItemUtils.createFilledResult(itemStack, player, Items.MILK_BUCKET.defaultInstance)
|
||||
player.setItemInHand(hand, milkBucket)
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
//Bouffalant gives Milk Bucket if player uses Bucket on it
|
||||
else if (pokemon.species.name == "Bouffalant" && pokemon.gender.name == "FEMALE") {
|
||||
player.playSound(SoundEvents.GOAT_MILK, 1.0f, 1.0f)
|
||||
val milkBucket = ItemUtils.createFilledResult(itemStack, player, Items.MILK_BUCKET.defaultInstance)
|
||||
player.setItemInHand(hand, milkBucket)
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
|
||||
} else if (itemStack.`is`(Items.BOWL)) {
|
||||
if (pokemon.aspects.any { it.contains("mooshtank") }) {
|
||||
player.playSound(SoundEvents.MOOSHROOM_MILK, 1.0f, 1.0f)
|
||||
@@ -1026,7 +1045,32 @@ open class PokemonEntity(
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
}
|
||||
//Shuckle uses it's fullness to dispense Berry Juice if a player uses Wooden Bowl on it
|
||||
else if (pokemon.species.name == "Shuckle" && pokemon.currentFullness > 0 && pokemon.lastMilked >= 300) {
|
||||
player.playSound(SoundEvents.MOOSHROOM_MILK, 1.0f, 1.0f)
|
||||
val berryJuice = ItemUtils.createFilledResult(itemStack, player, CobblemonItems.BERRY_JUICE.defaultInstance)
|
||||
player.setItemInHand(hand, berryJuice)
|
||||
pokemon.currentFullness--
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
} else if (itemStack.`is`(Items.GLASS_BOTTLE)) {
|
||||
if ((pokemon.species.name == "Vespiquen") && pokemon.lastMilked >= 500) {
|
||||
player.playSound(SoundEvents.GOAT_MILK, 1.0f, 1.0f)
|
||||
val honeyBottle = ItemUtils.createFilledResult(itemStack, player, Items.HONEY_BOTTLE.defaultInstance)
|
||||
player.setItemInHand(hand, honeyBottle)
|
||||
pokemon.milk()
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
//Miltank gives MooMoo Milk if player uses Glass Bottle on it
|
||||
else if (pokemon.species.name == "Miltank" && pokemon.lastMilked >= 500) {
|
||||
player.playSound(SoundEvents.MOOSHROOM_MILK, 1.0f, 1.0f)
|
||||
val moomooMilk = ItemUtils.createFilledResult(itemStack, player, CobblemonItems.MOOMOO_MILK.defaultInstance)
|
||||
player.setItemInHand(hand, moomooMilk)
|
||||
pokemon.milk()
|
||||
return InteractionResult.sidedSuccess(level().isClientSide)
|
||||
}
|
||||
}
|
||||
|
||||
// Flowers used on brown MooshTanks
|
||||
else if (itemStack.`is`(Items.ALLIUM) ||
|
||||
itemStack.`is`(Items.AZURE_BLUET) ||
|
||||
@@ -2091,13 +2135,6 @@ open class PokemonEntity(
|
||||
}
|
||||
}
|
||||
|
||||
override fun maxUpStep(): Float {
|
||||
val upStep = ifRidingAvailableSupply(fallback = null) { behaviour, settings, state ->
|
||||
behaviour.maxUpStep(settings, state, this)
|
||||
}
|
||||
return upStep ?: super.maxUpStep()
|
||||
}
|
||||
|
||||
override fun getRiddenSpeed(controller: Player): Float {
|
||||
return ifRidingAvailableSupply(fallback = 0.05f) { behaviour, settings, state ->
|
||||
behaviour.speed(settings, state,this, controller)
|
||||
|
||||
@@ -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,13 @@ object ServerTickHandler {
|
||||
// Party tick
|
||||
for (player in server.playerList.players) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,7 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
|
||||
}
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
val boosts = getBoosts(stack, pokemon)
|
||||
return boosts.isNotEmpty() && boosts.any { pokemon.canAddRideBoost(it.key, it.value) } && super.canUseOnPokemon(stack, pokemon)
|
||||
return getBoosts(stack, pokemon).any { pokemon.canAddRideBoost(it.key, it.value) }
|
||||
}
|
||||
|
||||
fun getBoosts(stack: ItemStack, pokemon: Pokemon): Map<RidingStat, Float> {
|
||||
@@ -102,13 +101,24 @@ class AprijuiceItem(val type: Apricorn): CobblemonItem(Properties().stacksTo(16)
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
val boosts = getBoosts(stack, pokemon)
|
||||
|
||||
if (!canUseOnPokemon(stack, pokemon) || boosts.isEmpty() || pokemon.isFull()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
val boosts = getBoosts(stack, pokemon)
|
||||
|
||||
// Feed the Pokémon 1 fullness point
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
|
||||
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
boosts.forEach { (stat, value) ->
|
||||
pokemon.addRideBoost(stat, value)
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ class PokePuffItem : Item(Properties().stacksTo(16)), PokemonSelectingItem {
|
||||
}
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack> {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
if (pokemon.isFull()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ class PokePuffItem : Item(Properties().stacksTo(16)), PokemonSelectingItem {
|
||||
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
return getFriendshipDelta(stack, pokemon) != 0 && super.canUseOnPokemon(stack, pokemon)
|
||||
return getFriendshipDelta(stack, pokemon) != 0
|
||||
}
|
||||
|
||||
private fun getFriendshipDelta(stack: ItemStack, pokemon: Pokemon): Int {
|
||||
|
||||
@@ -1,89 +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.item
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeIdentifierCondition
|
||||
import com.cobblemon.mod.common.api.cooking.Flavour
|
||||
import com.cobblemon.mod.common.api.cooking.PokePuffUtils
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Nature
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
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.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.UseAnim
|
||||
import net.minecraft.world.level.Level
|
||||
|
||||
class RegionalFoodItem(properties: Properties) : Item(properties), PokemonSelectingItem {
|
||||
override val bagItem = null
|
||||
|
||||
override fun use(world: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
val stack = player.getItemInHand(hand)
|
||||
|
||||
// Allow eating normally if player needs food
|
||||
if (player.foodData.needsFood()) {
|
||||
player.startUsingItem(hand)
|
||||
return InteractionResultHolder.consume(stack)
|
||||
}
|
||||
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
override fun interactLivingEntity(stack: ItemStack, player: Player, target: LivingEntity, hand: InteractionHand): InteractionResult {
|
||||
if (player.level().isClientSide) return InteractionResult.PASS
|
||||
|
||||
if (player is ServerPlayer && target is PokemonEntity) {
|
||||
val pokemon = target.pokemon
|
||||
if (pokemon.status != null) {
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.PASS
|
||||
}
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack> {
|
||||
if (pokemon.status != null) {
|
||||
pokemon.status = null
|
||||
pokemon.entity?.playSound(SoundEvents.GENERIC_EAT, 1F, 1F)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
override fun getUseAnimation(stack: ItemStack): UseAnim = UseAnim.EAT
|
||||
|
||||
override fun getUseDuration(stack: ItemStack, entity: LivingEntity): Int = 32
|
||||
|
||||
override fun getEatingSound(): SoundEvent = SoundEvents.GENERIC_EAT
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
return pokemon.status != null && pokemon.currentHealth > 0
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ class RevivalHerbItem(block: RevivalHerbBlock) : ItemNameBlockItem(block, Proper
|
||||
override val returnItem = Items.AIR
|
||||
override fun canUse(stack: ItemStack, battle: PokemonBattle, target: BattlePokemon) = target.health <= 0
|
||||
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?): String {
|
||||
battlePokemon.effectedPokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop("revival_herb", runtime))
|
||||
battlePokemon.effectedPokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(runtime))
|
||||
return "revive 0.25"
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ class RevivalHerbItem(block: RevivalHerbBlock) : ItemNameBlockItem(block, Proper
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_HERB_USE, 1F, 1F)
|
||||
|
||||
pokemon.currentHealth = amount
|
||||
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop("revival_herb", runtime))
|
||||
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(runtime))
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
|
||||
+11
-5
@@ -35,16 +35,13 @@ import net.minecraft.world.level.Level
|
||||
*/
|
||||
class FriendshipRaisingBerryItem(block: BerryBlock, val stat: Stat) : BerryItem(block), PokemonSelectingItem {
|
||||
override val bagItem = null
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = (pokemon.evs.getOrDefault(stat) > 0 || pokemon.friendship < Cobblemon.config.maxPokemonFriendship)
|
||||
&& super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.evs.getOrDefault(stat) > 0 || pokemon.friendship < Cobblemon.config.maxPokemonFriendship
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack> {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
if (pokemon.isFull()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
@@ -58,6 +55,15 @@ class FriendshipRaisingBerryItem(block: BerryBlock, val stat: Stat) : BerryItem(
|
||||
return if (increasedFriendship || decreasedEVs) {
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
|
||||
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
|
||||
@@ -45,19 +45,29 @@ class HealingBerryItem(block: BerryBlock, val amount: () -> ExpressionLike): Ber
|
||||
}
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = !pokemon.isFainted() && !pokemon.isFullHealth()
|
||||
&& super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
if (pokemon.isFullHealth() || pokemon.isFainted() || pokemon.isFull()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
|
||||
|
||||
pokemon.currentHealth = Integer.min(pokemon.currentHealth + genericRuntime.resolveInt(amount(), pokemon), pokemon.hp)
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
pokemon.currentHealth = Integer.min(pokemon.currentHealth + genericRuntime.resolveInt(amount(), pokemon), pokemon.maxHealth)
|
||||
//pokemon.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
@@ -66,7 +76,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)
|
||||
battlePokemon.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
@@ -48,16 +48,23 @@ class PPRestoringBerryItem(block: BerryBlock, val amount: () -> ExpressionLike):
|
||||
|
||||
override fun canUseOnMove(stack: ItemStack, move: Move) = move.currentPp < move.maxPp
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.moveSet.any { canUseOnMove(stack, it) }
|
||||
&& super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon, move: Move) {
|
||||
if (canUseOnPokemon(stack, pokemon) && canUseOnMove(stack, move)) {
|
||||
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, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
@@ -67,7 +74,7 @@ class PPRestoringBerryItem(block: BerryBlock, val amount: () -> ExpressionLike):
|
||||
|
||||
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon, move: Move) {
|
||||
super.applyToBattlePokemon(player, stack, battlePokemon, move)
|
||||
battlePokemon.originalPokemon.feedPokemon(1)
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
+12
-4
@@ -48,20 +48,28 @@ class PortionHealingBerryItem(block: BerryBlock, val canCauseConfusion: Boolean,
|
||||
}
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = !pokemon.isFainted() && !pokemon.isFullHealth()
|
||||
&& super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
if (pokemon.isFullHealth() || pokemon.isFainted() || pokemon.isFull()) {
|
||||
return InteractionResultHolder.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)
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
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 ->
|
||||
amount = event.amount
|
||||
@@ -76,7 +84,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)
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
+11
-7
@@ -39,19 +39,23 @@ class StatusCuringBerryItem(block: BerryBlock, vararg val status: Status): Berry
|
||||
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "cure_status${status.takeIf { it.isNotEmpty() }?.let { " ${it.joinToString(separator = " ") { it.showdownName } }" } ?: "" }"
|
||||
}
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.status?.let { it.status in status || status.isEmpty() } == true &&
|
||||
pokemon.currentHealth > 0 &&
|
||||
super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.status?.let { it.status in status || status.isEmpty() } == true && pokemon.currentHealth > 0
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
return if (canUseOnPokemon(stack, pokemon)) {
|
||||
val currentStatus = pokemon.status?.status
|
||||
return if (currentStatus != null && (status.isEmpty() || currentStatus in status)) {
|
||||
pokemon.feedPokemon(1)
|
||||
pokemon.status = null
|
||||
|
||||
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
pokemon.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
@@ -64,7 +68,7 @@ class StatusCuringBerryItem(block: BerryBlock, vararg val status: Status): Berry
|
||||
|
||||
override fun applyToBattlePokemon(player: ServerPlayer, stack: ItemStack, battlePokemon: BattlePokemon) {
|
||||
super.applyToBattlePokemon(player, stack, battlePokemon)
|
||||
battlePokemon.originalPokemon.feedPokemon(1)
|
||||
battlePokemon.entity?.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ enum class CookingPotBookCategory(
|
||||
) : StringRepresentable {
|
||||
FOODS("foods", 0),
|
||||
MEDICINES("medicines", 1),
|
||||
COMPLEX_DISHES("complex_dishes", 2),
|
||||
BAITS("baits", 2),
|
||||
MISC("misc", 3);
|
||||
|
||||
override fun getSerializedName() = categoryName
|
||||
|
||||
+8
-6
@@ -37,20 +37,22 @@ class CookingPotShapelessRecipe(
|
||||
override fun canCraftInDimensions(width: Int, height: Int) = width * height >= ingredients.size
|
||||
|
||||
override fun matches(input: CraftingInput, level: Level): Boolean {
|
||||
val remaining = ingredients.toMutableList()
|
||||
|
||||
// Match ingredients in any order
|
||||
val matchedIngredients = mutableListOf<Ingredient>()
|
||||
for (item in input.items()) {
|
||||
if (item.isEmpty) continue
|
||||
|
||||
val matchIndex = remaining.indexOfFirst { it.test(item) }
|
||||
if (matchIndex != -1) {
|
||||
remaining.removeAt(matchIndex)
|
||||
// Find matching ingredient
|
||||
val matchingIngredient = ingredients.find { it.test(item) && it !in matchedIngredients }
|
||||
if (matchingIngredient != null) {
|
||||
matchedIngredients.add(matchingIngredient)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return remaining.isEmpty()
|
||||
val matches = matchedIngredients.size == ingredients.size
|
||||
return matches
|
||||
}
|
||||
|
||||
class Serializer : RecipeSerializer<CookingPotShapelessRecipe> {
|
||||
|
||||
@@ -107,8 +107,7 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.VIVICHOKE)
|
||||
entries.accept(CobblemonItems.VIVICHOKE_SEEDS)
|
||||
entries.accept(CobblemonItems.GALARICA_NUTS)
|
||||
entries.accept(CobblemonItems.HEARTY_GRAINS)
|
||||
entries.accept(CobblemonItems.TASTY_TAIL)
|
||||
entries.accept(CobblemonItems.Hearty_Grains)
|
||||
entries.accept(CobblemonItems.BUGWORT)
|
||||
|
||||
entries.accept(CobblemonItems.RED_APRICORN)
|
||||
@@ -292,10 +291,6 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.SACCHARINE_LEAVES)
|
||||
//entries.accept(CobblemonItems.SACCHARINE_SAPLING)
|
||||
|
||||
entries.accept(CobblemonItems.HEARTY_GRAIN_BALE)
|
||||
|
||||
entries.accept(CobblemonItems.TATAMI_BLOCK)
|
||||
entries.accept(CobblemonItems.TATAMI_MAT)
|
||||
|
||||
entries.accept(CobblemonItems.TUMBLESTONE_BLOCK)
|
||||
entries.accept(CobblemonItems.BLACK_TUMBLESTONE_BLOCK)
|
||||
@@ -396,23 +391,6 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.STAR_SWEET)
|
||||
entries.accept(CobblemonItems.RIBBON_SWEET)
|
||||
|
||||
entries.accept(CobblemonItems.CANDIED_APPLE)
|
||||
entries.accept(CobblemonItems.CANDIED_BERRY)
|
||||
entries.accept(CobblemonItems.FRIED_RICE)
|
||||
entries.accept(CobblemonItems.POTATO_MOCHI)
|
||||
|
||||
entries.accept(CobblemonItems.PEWTER_CRUNCHIES)
|
||||
entries.accept(CobblemonItems.RAGE_CANDY_BAR)
|
||||
entries.accept(CobblemonItems.LAVA_COOKIE)
|
||||
entries.accept(CobblemonItems.JUBILIFE_MUFFIN)
|
||||
entries.accept(CobblemonItems.OLD_GATEAU)
|
||||
entries.accept(CobblemonItems.CASTELIACONE)
|
||||
entries.accept(CobblemonItems.LUMIOSE_GALETTE)
|
||||
entries.accept(CobblemonItems.SHALOUR_SABLE)
|
||||
entries.accept(CobblemonItems.BIG_MALASADA)
|
||||
entries.accept(CobblemonItems.SMOKED_TAIL_CURRY)
|
||||
entries.accept(CobblemonItems.OPEN_FACED_SANDWICH)
|
||||
|
||||
entries.accept(CobblemonItems.BERRY_JUICE)
|
||||
entries.accept(CobblemonItems.REMEDY)
|
||||
entries.accept(CobblemonItems.FINE_REMEDY)
|
||||
@@ -483,19 +461,6 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.EXPERIENCE_CANDY_XL)
|
||||
entries.accept(CobblemonItems.RARE_CANDY)
|
||||
|
||||
entries.accept(CobblemonItems.HEALTH_CANDY)
|
||||
entries.accept(CobblemonItems.MIGHTY_CANDY)
|
||||
entries.accept(CobblemonItems.TOUGH_CANDY)
|
||||
entries.accept(CobblemonItems.SMART_CANDY)
|
||||
entries.accept(CobblemonItems.COURAGE_CANDY)
|
||||
entries.accept(CobblemonItems.QUICK_CANDY)
|
||||
entries.accept(CobblemonItems.SICKLY_CANDY)
|
||||
entries.accept(CobblemonItems.WEAK_CANDY)
|
||||
entries.accept(CobblemonItems.BRITTLE_CANDY)
|
||||
entries.accept(CobblemonItems.NUMB_CANDY)
|
||||
entries.accept(CobblemonItems.COWARD_CANDY)
|
||||
entries.accept(CobblemonItems.SLOW_CANDY)
|
||||
|
||||
entries.accept(CobblemonItems.LONELY_MINT)
|
||||
entries.accept(CobblemonItems.ADAMANT_MINT)
|
||||
entries.accept(CobblemonItems.NAUGHTY_MINT)
|
||||
@@ -573,9 +538,6 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.AUSPICIOUS_ARMOR)
|
||||
entries.accept(CobblemonItems.MALICIOUS_ARMOR)
|
||||
entries.accept(CobblemonItems.SHELL_HELMET)
|
||||
entries.accept(CobblemonItems.METAL_ALLOY)
|
||||
entries.accept(CobblemonItems.SCROLL_OF_DARKNESS)
|
||||
entries.accept(CobblemonItems.SCROLL_OF_WATERS)
|
||||
}
|
||||
|
||||
private fun heldItemEntries(displayContext: ItemDisplayParameters, entries: Output) {
|
||||
@@ -596,7 +558,6 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.CHOICE_SCARF)
|
||||
entries.accept(CobblemonItems.CHOICE_SPECS)
|
||||
entries.accept(CobblemonItems.CLEANSE_TAG)
|
||||
entries.accept(CobblemonItems.CLEAR_AMULET)
|
||||
entries.accept(CobblemonItems.COVERT_CLOAK)
|
||||
entries.accept(CobblemonItems.DAMP_ROCK)
|
||||
entries.accept(CobblemonItems.DEEP_SEA_SCALE)
|
||||
@@ -614,21 +575,18 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.FLOAT_STONE)
|
||||
entries.accept(CobblemonItems.FOCUS_BAND)
|
||||
entries.accept(CobblemonItems.FOCUS_SASH)
|
||||
entries.accept(CobblemonItems.GRIP_CLAW)
|
||||
entries.accept(CobblemonItems.HARD_STONE)
|
||||
entries.accept(CobblemonItems.HEAT_ROCK)
|
||||
entries.accept(CobblemonItems.HEAVY_DUTY_BOOTS)
|
||||
entries.accept(CobblemonItems.ICY_ROCK)
|
||||
entries.accept(CobblemonItems.IRON_BALL)
|
||||
entries.accept(CobblemonItems.KINGS_ROCK)
|
||||
entries.accept(CobblemonItems.LAGGING_TAIL)
|
||||
entries.accept(CobblemonItems.LEFTOVERS)
|
||||
entries.accept(CobblemonItems.LIFE_ORB)
|
||||
entries.accept(CobblemonItems.LIGHT_BALL)
|
||||
entries.accept(CobblemonItems.LIGHT_CLAY)
|
||||
entries.accept(CobblemonItems.LOADED_DICE)
|
||||
entries.accept(CobblemonItems.LUCKY_EGG)
|
||||
entries.accept(CobblemonItems.LUMINOUS_MOSS)
|
||||
entries.accept(CobblemonItems.MAGNET)
|
||||
entries.accept(CobblemonItems.MENTAL_HERB)
|
||||
entries.accept(CobblemonItems.METAL_COAT)
|
||||
@@ -752,26 +710,11 @@ object CobblemonItemGroups {
|
||||
injector.putAfter(CobblemonItems.STAR_SWEET, CobblemonItems.FLOWER_SWEET)
|
||||
injector.putAfter(CobblemonItems.RIBBON_SWEET, CobblemonItems.STAR_SWEET)
|
||||
|
||||
injector.putAfter(CobblemonItems.CANDIED_APPLE, CobblemonItems.RIBBON_SWEET)
|
||||
injector.putAfter(CobblemonItems.CANDIED_BERRY, CobblemonItems.CANDIED_APPLE)
|
||||
injector.putAfter(CobblemonItems.FRIED_RICE, CobblemonItems.CANDIED_BERRY)
|
||||
injector.putAfter(CobblemonItems.POTATO_MOCHI, CobblemonItems.FRIED_RICE)
|
||||
|
||||
injector.putAfter(CobblemonItems.PEWTER_CRUNCHIES, CobblemonItems.POTATO_MOCHI)
|
||||
injector.putAfter(CobblemonItems.RAGE_CANDY_BAR, CobblemonItems.PEWTER_CRUNCHIES)
|
||||
injector.putAfter(CobblemonItems.LAVA_COOKIE, CobblemonItems.RAGE_CANDY_BAR)
|
||||
injector.putAfter(CobblemonItems.JUBILIFE_MUFFIN, CobblemonItems.LAVA_COOKIE)
|
||||
injector.putAfter(CobblemonItems.OLD_GATEAU, CobblemonItems.JUBILIFE_MUFFIN)
|
||||
injector.putAfter(CobblemonItems.CASTELIACONE, CobblemonItems.OLD_GATEAU)
|
||||
injector.putAfter(CobblemonItems.LUMIOSE_GALETTE, CobblemonItems.CASTELIACONE)
|
||||
injector.putAfter(CobblemonItems.SHALOUR_SABLE, CobblemonItems.LUMIOSE_GALETTE)
|
||||
injector.putAfter(CobblemonItems.BIG_MALASADA, CobblemonItems.SHALOUR_SABLE)
|
||||
injector.putAfter(CobblemonItems.SMOKED_TAIL_CURRY, CobblemonItems.BIG_MALASADA)
|
||||
injector.putAfter(CobblemonItems.OPEN_FACED_SANDWICH, CobblemonItems.SMOKED_TAIL_CURRY)
|
||||
|
||||
injector.putAfter(CobblemonItems.LEEK_AND_POTATO_STEW, Items.RABBIT_STEW)
|
||||
injector.putAfter(CobblemonItems.VIVICHOKE_DIP, CobblemonItems.LEEK_AND_POTATO_STEW)
|
||||
|
||||
injector.putLast(CobblemonItems.POTATO_MOCHI)
|
||||
injector.putLast(CobblemonItems.FRIED_RICE)
|
||||
injector.putLast(CobblemonItems.CANDIED_APPLE)
|
||||
}
|
||||
|
||||
private fun toolsAndUtilitiesInjections(injector: Injector) {
|
||||
|
||||
@@ -38,8 +38,6 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
|
||||
}
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = !pokemon.isFullHealth() && pokemon.currentHealth > 0
|
||||
&& super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
if (user is ServerPlayer) {
|
||||
return use(user, user.getItemInHand(hand))
|
||||
@@ -52,10 +50,19 @@ class BerryJuiceItem : CobblemonItem(Properties()), PokemonSelectingItem, Healin
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack>? {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
if (pokemon.isFullHealth() || pokemon.isFull()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
pokemon.feedPokemon(1)
|
||||
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
|
||||
|
||||
pokemon.currentHealth = Integer.min(pokemon.currentHealth + 20, pokemon.hp)
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL,1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT,1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
var amount = Integer.min(pokemon.currentHealth + 20, pokemon.maxHealth)
|
||||
CobblemonEvents.POKEMON_HEALED.postThen(PokemonHealedEvent(pokemon, amount, this), { cancelledEvent -> return InteractionResultHolder.fail(stack)}) { event ->
|
||||
@@ -76,7 +83,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)
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F)
|
||||
if (!player.isCreative) {
|
||||
val woodenBowlItemStack = ItemStack(Items.BOWL)
|
||||
if (!player.inventory.add(woodenBowlItemStack)) {
|
||||
|
||||
@@ -27,9 +27,7 @@ abstract class EVIncreaseItem(
|
||||
val evIncreaseAmount: Int,
|
||||
) : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
override val bagItem = null
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.evs.getOrDefault(stat) < EVs.MAX_STAT_VALUE &&
|
||||
super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.evs.getOrDefault(stat) < EVs.MAX_STAT_VALUE
|
||||
abstract val sound: SoundEvent
|
||||
|
||||
override fun applyToPokemon(
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.block.EnergyRootBlock
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.genericRuntime
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
@@ -40,7 +42,7 @@ class EnergyRootItem(block: EnergyRootBlock, settings: Properties) : ItemNameBlo
|
||||
override val returnItem = Items.AIR
|
||||
override fun canUse(stack: ItemStack, battle: PokemonBattle, target: BattlePokemon) = target.health > 0 && target.health < target.maxHealth
|
||||
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?): String {
|
||||
battlePokemon.effectedPokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop("root", runtime))
|
||||
battlePokemon.effectedPokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(runtime))
|
||||
return "potion ${getHealAmount()}"
|
||||
}
|
||||
}
|
||||
@@ -56,7 +58,7 @@ class EnergyRootItem(block: EnergyRootBlock, settings: Properties) : ItemNameBlo
|
||||
amount = event.amount
|
||||
}
|
||||
pokemon.currentHealth += amount
|
||||
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop("root", runtime))
|
||||
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(runtime))
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_HERB_USE, 1F, 1F)
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
|
||||
+10
-3
@@ -21,20 +21,27 @@ import net.minecraft.world.level.Level
|
||||
|
||||
class FreshStartMochiItem : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
override val bagItem = null
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon) = pokemon.evs.any { it.value > 0 }
|
||||
&& super.canUseOnPokemon(stack, pokemon)
|
||||
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack> {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
if (pokemon.isFull()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
pokemon.evs.forEach {
|
||||
pokemon.evs[it.key] = 0
|
||||
}
|
||||
|
||||
@@ -8,14 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.item.interactive
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMechanics
|
||||
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.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
@@ -33,14 +30,9 @@ class HealPowderItem : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
override val itemName = "item.cobblemon.heal_powder"
|
||||
override val returnItem = Items.AIR
|
||||
override fun canUse(stack: ItemStack, battle: PokemonBattle, target: BattlePokemon) = canUseOnPokemon(stack, target.effectedPokemon)
|
||||
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?): String {
|
||||
battlePokemon.effectedPokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop("heal_powder", runtime))
|
||||
return "cure_status"
|
||||
}
|
||||
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "cure_status"
|
||||
}
|
||||
|
||||
private val runtime = MoLangRuntime().setup()
|
||||
|
||||
init {
|
||||
Cobblemon.implementation.registerCompostable(this, .75F)
|
||||
}
|
||||
@@ -55,7 +47,6 @@ class HealPowderItem : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
return if (currentStatus != null) {
|
||||
pokemon.status = null
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_HERB_USE, 1F, 1F)
|
||||
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop("heal_powder", runtime))
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
|
||||
@@ -1,73 +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.item.interactive
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.pokemon.IVs
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.util.Mth.clamp
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.level.Level
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
// An item that modifies a Pokémon's IVs according to a given modifier and valid range.
|
||||
class HyperTrainingItem(val ivIncreaseAmount: Int, val targetStats: Set<Stat>, val validRange: IntRange) : CobblemonItem(Properties()), PokemonSelectingItem {
|
||||
|
||||
override val bagItem = null
|
||||
|
||||
// Helper to ensure prospective IVs are within the valid range
|
||||
private fun canChangeIV(stat: Stat, pokemon: Pokemon): Boolean {
|
||||
val effectiveIV = pokemon.ivs.getEffectiveBattleIV(stat)
|
||||
return effectiveIV in validRange && effectiveIV + ivIncreaseAmount in 0..IVs.MAX_VALUE
|
||||
}
|
||||
|
||||
override fun canUseOnPokemon(stack: ItemStack, pokemon: Pokemon): Boolean {
|
||||
// Check if at least one stat's effective IV can be modified
|
||||
return targetStats.any { stat -> canChangeIV(stat, pokemon) }
|
||||
}
|
||||
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack> {
|
||||
if(!canUseOnPokemon(stack, pokemon)) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
// Modify the effective IVs for the target stats
|
||||
targetStats.forEach { stat ->
|
||||
if (canChangeIV(stat, pokemon)) {
|
||||
val effectiveIV = pokemon.ivs.getEffectiveBattleIV(stat)
|
||||
pokemon.hyperTrainIV(stat, effectiveIV + ivIncreaseAmount)
|
||||
}
|
||||
}
|
||||
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_PILLS_USE, 1F, 1F)
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
|
||||
override fun use(world: Level, user: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
if (user is ServerPlayer) {
|
||||
return use(user, user.getItemInHand(hand))
|
||||
}
|
||||
return InteractionResultHolder.success(user.getItemInHand(hand))
|
||||
}
|
||||
}
|
||||
@@ -21,12 +21,20 @@ class MochiItem(stat: Stats): EVIncreaseItem(stat, 10) {
|
||||
override val sound: SoundEvent = CobblemonSounds.MOCHI_USE
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack> {
|
||||
if (!canUseOnPokemon(stack, pokemon)) {
|
||||
if (pokemon.isFull()) {
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
pokemon.feedPokemon(1)
|
||||
|
||||
val fullnessPercent = ((pokemon.currentFullness).toFloat() / (pokemon.getMaxFullness()).toFloat()) * (.5).toFloat()
|
||||
if (pokemon.currentFullness >= pokemon.getMaxFullness()) {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT_FULL, 1F, 1F)
|
||||
}
|
||||
else {
|
||||
player.playSound(CobblemonSounds.BERRY_EAT, 1F, 1F + fullnessPercent)
|
||||
}
|
||||
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class RemedyItem(val remedyStrength: String) : CobblemonItem(Properties()), Poke
|
||||
override val returnItem = Items.AIR
|
||||
override fun canUse(stack: ItemStack, battle: PokemonBattle, target: BattlePokemon) = target.health > 0 && target.health < target.maxHealth
|
||||
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?): String {
|
||||
battlePokemon.effectedPokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(remedyStrength, runtime))
|
||||
battlePokemon.effectedPokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(runtime))
|
||||
return "potion ${CobblemonMechanics.remedies.getHealingAmount(remedyStrength, runtime, 20)}"
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,7 @@ class RemedyItem(val remedyStrength: String) : CobblemonItem(Properties()), Poke
|
||||
}
|
||||
pokemon.currentHealth += amount
|
||||
pokemon.entity?.playSound(CobblemonSounds.MEDICINE_HERB_USE, 1F, 1F)
|
||||
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(remedyStrength, runtime))
|
||||
pokemon.decrementFriendship(CobblemonMechanics.remedies.getFriendshipDrop(runtime))
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
}
|
||||
|
||||
@@ -10,13 +10,13 @@ package com.cobblemon.mod.common.mechanics
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
|
||||
class RemediesMechanic {
|
||||
val remedies = mutableMapOf<String, RemedyEntry>()
|
||||
val healingAmounts = mutableMapOf<String, ExpressionLike>()
|
||||
val friendshipDrop: ExpressionLike = "10".asExpressionLike()
|
||||
|
||||
fun getHealingAmount(type: String, runtime: MoLangRuntime, default: Int = 20) = remedies[type]?.let { runtime.resolveInt(it.healingAmount) } ?: default
|
||||
fun getFriendshipDrop(type: String, runtime: MoLangRuntime, default: Int = 0) = remedies[type]?.let { runtime.resolveInt(it.friendshipDrop) } ?: default
|
||||
}
|
||||
|
||||
data class RemedyEntry(val healingAmount: ExpressionLike, val friendshipDrop: ExpressionLike)
|
||||
fun getHealingAmount(type: String, runtime: MoLangRuntime, default: Int = 20) = healingAmounts[type]?.let { runtime.resolveInt(it) } ?: default
|
||||
fun getFriendshipDrop(runtime: MoLangRuntime) = runtime.resolveInt(friendshipDrop)
|
||||
}
|
||||
Loaded 100 of 618 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user