Compare commits

...
Author SHA1 Message Date
Plastered_Crab 3fa0544c28 - adjusted logic to prepare for detecting user switches and to allow for better use of pivot moves 2024-07-01 11:51:52 -07:00
Plastered_Crab e2445db9c4 - adjusted logic 2024-06-21 18:07:35 -07:00
Plastered_Crab 9610332de5 - adjusted team list 2024-06-19 22:38:15 -07:00
Plastered_Crab 0c08a3c271 - adjusted team list 2024-06-19 22:23:56 -07:00
Plastered_Crab 7aafc377db - added test sun team, rain team, and comp team to fight against for testing 2024-06-19 22:17:17 -07:00
Plastered_Crab 91fad06986 - start of incorporating skill levels into the battle ai 2024-06-19 16:33:07 -07:00
Lily 6865654f37 started on move tags 2024-01-26 17:57:03 -05:00
jeffw773 17b3345abe - Merged in MoreHoldItems branch and adjusted teams 2024-01-10 16:49:32 -08:00
jeffw773 9c037dbad2 Merge remote-tracking branch 'origin/main' into better_battle_ai_test 2024-01-10 16:12:58 -08:00
jeffw773 8afbe3a3a7 Merge branch 'MoreHoldItems' into better_battle_ai_test
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/api/pokemon/PokemonProperties.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/Pokemon.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/properties/PropertiesCompletionProvider.kt
2024-01-10 14:42:27 -08:00
jeffw773 916147ee0d - Battle AI should keep track of some volatiles more now 2024-01-08 14:30:12 -08:00
jeffw773 ad83d0e4a1 - Battle AI can now detect Type Changes
- Added hard "pivoter" NPC
2024-01-06 23:32:56 -08:00
jeffw773 5a993f3d88 - Fixed Battle AI to be able to use status moves on opponents 2024-01-05 13:59:36 -08:00
JazzMcNade 373c383097 Fixed matching the activepokemon on both parties in the tracker party. Fixed added newly revealed pokemon to the tracker party. 2024-01-04 00:47:13 -06:00
jeffw773 00c095ba8d - Almost done with rework of ActiveTracker 2024-01-03 21:24:32 -08:00
dhi_holo e8236b55a4 Recipe Fixes plus Information in Description
There are 6 items left unimplemented from the recipe document.
Soothe Bell, due to being an out of battle effect, I don't want to attempt, and Amulet Coin needs design work before implementation.
The four terrain seeds, due to future plans, I'm not sure if need to be set up differently. Beyond those six held items, this branch has all currently requested held items to my knowledge, all should now work as intended, although I have not confirmed all battle dialogue works, in part due to not wanting to find all the documentations of what the lines should be. I might come back to that another day, though.

Commits marked with "No Obtain Method" refer to items which have obtain methods of loot or whatever, which can be handled later by people familiar with those systems. If not, I'm down to learn, just not a thing for today.
2024-01-04 13:52:21 +10:00
dhi_holo 2ea07899ea -Added Sticky Barb
No Obtain Method
2024-01-04 13:01:30 +10:00
dhi_holo d0ce03cd5e -Added Shed Shell
No Obtain Method
2024-01-04 13:00:02 +10:00
dhi_holo 8ae0c409a3 -Added Light Ball
No Obtain Method
2024-01-04 12:58:15 +10:00
dhi_holo 2782cb5f34 -Added Lagging Tail
No Obtain Method
2024-01-04 12:56:09 +10:00
dhi_holo 2f10707211 -Added Grip Claw
No Obtain Method
2024-01-04 12:54:48 +10:00
dhi_holo f40a9d762a -Added Float Stone
No Obtain Method
2024-01-04 12:53:17 +10:00
dhi_holo 17587f97e5 -Added Absorb Bulb
No Obtain Method
2024-01-04 12:51:46 +10:00
dhi_holo 5230820657 -Added Punching Glove 2024-01-04 12:49:01 +10:00
dhi_holo 61c55e136f -Added Throat Spray
need to figure out how to add the potion brewing later, not a huge priority at this stage
2024-01-04 12:45:59 +10:00
dhi_holo 22cced74f5 -Added Luminous Moss 2024-01-04 12:43:40 +10:00
dhi_holo 3cd2dec8e0 -Added Loaded Dice 2024-01-04 12:40:34 +10:00
dhi_holo cea930893a -Added Iron Ball 2024-01-04 10:26:54 +10:00
dhi_holo 8662364ca8 -Added Wide Lens and Zoom Lens 2024-01-04 10:24:00 +10:00
dhi_holo 1fd079b1b4 -Added Weather Rocks
Damp Rock, Heat Rock, Smooth Rock, Icy Rock, terrible items
2024-01-04 10:19:53 +10:00
dhi_holo 244876a26c -Added Weakness Policy 2024-01-04 10:11:52 +10:00
dhi_holo e7790f530f -Added Utility Umbrella 2024-01-04 10:08:56 +10:00
dhi_holo 04a9ab0e67 -Adds Terrain Extender
If someone wants to work out how to make it so we can have a recipe that costs a water bucket, rather than water from a bucket, that'd be good, for now the recipe just costs an empty bucket
2024-01-04 10:06:39 +10:00
dhi_holo 3f338d27c3 -Added Scope Lens 2024-01-04 09:55:46 +10:00
dhi_holo 5da3dfb451 -Added Room Service 2024-01-04 09:54:00 +10:00
dhi_holo fd329e00cd -Added Ring Target 2024-01-04 09:52:00 +10:00
dhi_holo 6da47a8b2c -Added Red Card
Not gonna test this one for now, don't feel like setting up a second instance test. But, given Eject Button works, I'd say decent shot this one also works
2024-01-04 09:49:02 +10:00
dhi_holo 860c73fac9 -Added Protective Pads 2024-01-04 09:45:50 +10:00
dhi_holo e26fdd4bdd -Added Metronome
Deciding I'll ignore all held items with a * next to the name for now, not sure what they mean but hey, makes it easier to work through, and I can come back to them afterwards
2024-01-04 09:42:31 +10:00
dhi_holo 8e642f71b8 Merge branch 'main' into MoreHoldItems 2024-01-04 09:32:19 +10:00
dhi_holo f17884b4e1 Eject Button Lang, Read Description
All of the items added just now by me were tested besides Eviolite (don't feel like crunching those numbers today), Eject Pack is broken in my testing (see https://canary.discord.com/channels/725110639554592879/993671151870017656/1192009424282320957 for details), and ofc no item sprites yet, but that's dev life
2024-01-03 17:53:57 +10:00
dhi_holo c40b456948 -Added Eviolite and Expert Belt
test and finalise this little bit time (also corrected some jsons)
2024-01-03 17:19:31 +10:00
dhi_holo 7e74e85315 -Added Eject Button and Pack
I'm not testing these in game rn, I'll do that at the end of the session, which will probably be in a couple more items. But, these all hit the internet at the same time, so haha
2024-01-03 17:09:13 +10:00
dhi_holo 21fd4d7cbf -Added Covert Cloak 2024-01-03 17:00:58 +10:00
dhi_holo 908bff9892 -Added Cell Battery and Clear Amulet 2024-01-03 16:57:32 +10:00
dhi_holo fa14f70bbb -Added Shell Bell
Bell Go Heal
2024-01-03 15:59:01 +10:00
jeffw773 610ea0f30c - Added Sandstorm Team to battle that has stall, hazards, removal 2024-01-02 15:13:33 -08:00
jeffw773 a9c92d72d0 - NPC team for Red was buffed and given hazard removal
- AI can now do hazard removal properly (was broken)
2024-01-02 12:22:53 -08:00
jeffw773 25cc5f526b Merge remote-tracking branch 'origin/better_battle_ai_test' into better_battle_ai_test 2024-01-01 23:37:17 -08:00
jeffw773 3cb4f938f1 - AI can now use Hazards, Clear Hazards, and Status Moves
- Added trickroom NPC Team
2024-01-01 23:37:00 -08:00
dhi_holo 346559f292 Tags on top of Tags
Added a very large amount of tags.
The different tiers of Poké balls, also the Apricorn balls so it's easier for people to see what balls count for that advancement, different healing and battle item types, some evolution item sets which made sense to make tags (may add more later, these ones were just the obvious ones to make thing easier for future), the three colours for tumblestones, machine blocks, as well as adding the fence gate item tag, and adding the new tumblestone stuff to the pickaxe tag (although they can still be mined with an axe, probably something that needs fixing)

Mod loader tags were not tested on Forge, due to a crash involving CobblemonEntities, but Fabric works all nicely
2024-01-02 14:44:01 +10:00
dhi_holo 331b282fcf Decorated sherds tag, and fixed Focus Sash not being named
`focus_Sash` isn't valid, sadly
2024-01-02 12:41:28 +10:00
JazzMcNade a876666bc7 -Fixed an issue in which a pokemon with less than 4 moves would not allow its currently populated moveslots to be overwritten. 2024-01-01 20:31:24 -06:00
dhi_holo 7f97eeafed Update is_held_item.json
Reorganized alphabetically, for the most part, roughly matches the registry now.
2024-01-02 11:45:38 +10:00
dhi_holo 51f5a1f5a8 Merge branch 'main' into MoreHoldItems 2024-01-02 11:35:53 +10:00
dhi_holo 7c0535b8bd Merge branch 'main' into MoreHoldItems 2024-01-01 21:08:33 +10:00
dhi_holo 4f15ac0cbc Update CobblemonItems.kt
No More "why are the held items not in alphabetical order" for the time being (besides the three Powders and four Herbs, I left them together at the bottom because nobody cares about them)
2024-01-01 18:37:53 +10:00
JazzMcNade 35a0d8a80d -Added Blunder Policy 2024-01-01 01:31:08 -06:00
JazzMcNade c0270d3ef0 -Added Binding Band 2023-12-31 23:58:24 -06:00
JazzMcNade 82a1eb2a55 -Finished Air Balloon implementation. Fixed white space on recipes for for focus sash and Ability Shield 2023-12-31 21:44:26 -06:00
JazzMcNade a528ea952a -Added Ability Shield and Focus Sash. Begin work on Air Balloon. 2023-12-31 21:20:10 -06:00
JazzMcNade 592b40cd12 -Added temporary party store for cloned parties. Allows for proper faint behavior for clone team. 2023-12-31 18:49:45 -06:00
JazzMcNade 9e05cfa385 -Set simulation flag for clone battles 2023-12-31 14:22:47 -06:00
jeffw773 36f13f5b77 - Added Red, Blue, Volo, Evice to AI Battle pool
- AI can now use Trick Room
- Tweaked switchin considerations more to account for speed more
2023-12-30 02:05:45 -08:00
jeffw773 141a88ba13 - Cynthia Battle NPC tweaked + AI now doesn't constantly switch out
- Recovery moves consideration tweaked from .3 to .45
- Disabled moves now will not be considered
2023-12-29 19:50:16 -08:00
jeffw773 fc269e853c - Cynthia Battle AI is now stronger and hungers for battle
- Moves that must be used don't crash the battle for the Battle AI now
2023-12-29 00:21:28 -08:00
jeffw773 df44486eee - Added less chance of the strong AI being cheesed by a bad Ability 2023-12-28 22:29:13 -08:00
jeffw773 d7881a327a Merge remote-tracking branch 'origin/better_battle_ai_test' into better_battle_ai_test 2023-12-28 22:19:55 -08:00
jeffw773 6ff719d2ec - Made Battle AI able to know if it was given a bad abiltiy and will switch out 2023-12-28 22:19:26 -08:00
JazzMcNade 088fd65159 -Fixed cloning pokemon not capturing the current HP correctly 2023-12-29 00:06:38 -06:00
jeffw773 3a2d4028a5 - Cynthia battle NPC can be set to be any level (VERY HARD) 2023-12-28 12:37:12 -08:00
jeffw773 a6a9dce811 Merge remote-tracking branch 'origin/1.4.1' into better_battle_ai_test 2023-12-28 11:54:21 -08:00
jeffw773 55f0a392e9 - Added Cynthia (with team) from BDSP to NPC battle list
- Added ability to specify AI type before NPC battle
- Allow for different orders of commands for /randombattle
2023-12-28 11:53:49 -08:00
jeffw773 fb3b2a9452 Merge branch 'main' into better_battle_ai_test
# Conflicts:
#	common/src/main/kotlin/com/cobblemon/mod/common/CobblemonCommands.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/client/gui/battle/subscreen/BattleGeneralActionSelection.kt
#	common/src/main/kotlin/com/cobblemon/mod/common/pokemon/Pokemon.kt
2023-12-27 08:01:21 -08:00
jeffw773 dff934b308 - Added better considerations for meaningful switch-ins mid battle 2023-12-26 23:31:28 -08:00
jeffw773 0de555610a - Stronger Battle AI test will send in the best matchup after faint
- Also tweaked Tailwind considerations and healing considerations
2023-12-26 13:42:33 -08:00
jeffw773 2e213e0472 - Started fixing Battle AI's switch in/out logic 2023-12-24 00:04:54 -08:00
jeffw773 eeb4000b71 - fixed weather conditions causing null issue for battle AI 2023-12-23 14:40:31 -08:00
JazzMcNade 2fbf3100c5 -Added more status immunity and effect info to the AI 2023-12-23 16:33:52 -06:00
jeffw773 802bf10c6e - fixed switching out for the random NPC battle actor 2023-12-21 15:40:18 -08:00
jeffw773 42f442233a - Added Command to start random NPC battle with random party to use for testing AI 2023-12-21 14:30:35 -08:00
jeffw773 addd063406 - Adjusted how Strong Battle AI calculates what damaging moves to use (based on mainline game battle damage calculations) 2023-12-21 00:06:38 -08:00
jeffw773 bae01e7143 - Strong Battle AI is working! It hungers for the blood of the innocent. Still going to be worked on as time goes on though 2023-12-20 21:34:31 -08:00
jeffw773 fd0e2fa43f - Only 2 main errors left before testing can begin 2023-12-19 22:47:25 -08:00
jeffw773 76260fb998 - removed unused test code 2023-12-18 10:52:01 -08:00
jeffw773 3aa45d83b6 - Made additional changes to the test StrongBattleAI file. Fixed Obstruct spelling and begun converting over the functions to take in battle and request. Still more left to do. 2023-12-18 09:51:09 -08:00
jeffw773 2eb6062b9c - Beginning test of a smarter battle AI for Wild and NPC battles 2023-12-15 23:48:09 -08:00
151 changed files with 6550 additions and 208 deletions
@@ -46,6 +46,7 @@ object CobblemonCommands {
ClearPartyCommand.register(dispatcher)
ClearPCCommand.register(dispatcher)
PokemonRestartCommand.register(dispatcher)
RandomBattleCommand.register(dispatcher)
BedrockParticleCommand.register(dispatcher)
OpenDialogueCommand.register(dispatcher)
}
@@ -596,16 +596,28 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
// Held Items
@JvmField
val ABILITY_SHIELD = heldItem("ability_shield")
@JvmField
val ABSORB_BULB = heldItem("absorb_bulb")
@JvmField
val AIR_BALLOON = heldItem("air_balloon")
@JvmField
val ASSAULT_VEST = heldItem("assault_vest")
@JvmField
val BIG_ROOT = blockItem("big_root", CobblemonBlocks.BIG_ROOT)
@JvmField
val BINDING_BAND = heldItem("binding_band")
@JvmField
val BLACK_BELT = heldItem("black_belt")
@JvmField
val BLACK_GLASSES = heldItem("black_glasses")
@JvmField
val BLACK_SLUDGE = heldItem("black_sludge")
@JvmField
val BLUNDER_POLICY = heldItem("blunder_policy")
@JvmField
val CELL_BATTERY = heldItem("cell_battery")
@JvmField
val CHARCOAL = heldItem("charcoal_stick", remappedName = "charcoal")
@JvmField
val CHOICE_BAND = heldItem("choice_band")
@@ -616,26 +628,64 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val CLEANSE_TAG = heldItem("cleanse_tag")
@JvmField
val CLEAR_AMULET = heldItem("clear_amulet")
@JvmField
val COVERT_CLOAK = heldItem("covert_cloak")
@JvmField
val DESTINY_KNOT = heldItem("destiny_knot")
@JvmField
val DRAGON_FANG = heldItem("dragon_fang")
@JvmField
val EJECT_BUTTON = heldItem("eject_button")
@JvmField
val EJECT_PACK = heldItem("eject_pack")
@JvmField
val EVERSTONE = heldItem("everstone")
@JvmField
val EVIOLITE = heldItem("eviolite")
@JvmField
val EXP_SHARE = heldItem("exp_share")
@JvmField
val EXPERT_BELT = heldItem("expert_belt")
@JvmField
val FAIRY_FEATHER = heldItem("fairy_feather")
@JvmField
val FLAME_ORB = heldItem("flame_orb")
@JvmField
val FLOAT_STONE = heldItem("float_stone")
@JvmField
val FOCUS_BAND = heldItem("focus_band")
@JvmField
val FOCUS_SASH = heldItem("focus_sash")
@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 LEFTOVERS = heldItem("leftovers")
@JvmField
val LIFE_ORB = heldItem("life_orb")
@JvmField
val LIGHT_BALL = heldItem("light_ball")
@JvmField
val LIGHT_CLAY = heldItem("light_clay")
@JvmField
val LOADED_DICE = heldItem("loaded_dice")
@JvmField
val LUCKY_EGG = heldItem("lucky_egg")
@JvmField
val LUMINOUS_MOSS = heldItem("luminous_moss")
@JvmField
val MAGNET = heldItem("magnet")
@JvmField
val METRONOME = heldItem("metronome")
@JvmField
val MIRACLE_SEED = heldItem("miracle_seed")
@JvmField
val MUSCLE_BAND = heldItem("muscle_band")
@@ -646,14 +696,42 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val POISON_BARB = heldItem("poison_barb")
@JvmField
val POWER_ANKLET = heldItem("power_anklet")
@JvmField
val POWER_BAND = heldItem("power_band")
@JvmField
val POWER_BELT = heldItem("power_belt")
@JvmField
val POWER_BRACER = heldItem("power_bracer")
@JvmField
val POWER_LENS = heldItem("power_lens")
@JvmField
val POWER_WEIGHT = heldItem("power_weight")
@JvmField
val PROTECTIVE_PADS = heldItem("protective_pads")
@JvmField
val PUNCHING_GLOVE = heldItem("punching_glove")
@JvmField
val QUICK_CLAW = heldItem("quick_claw")
@JvmField
val RED_CARD = heldItem("red_card")
@JvmField
val RING_TARGET = heldItem("ring_target")
@JvmField
val ROCKY_HELMET = heldItem("rocky_helmet")
@JvmField
val ROOM_SERVICE = heldItem("room_service")
@JvmField
val SAFETY_GOGGLES = heldItem("safety_goggles")
@JvmField
val SCOPE_LENS = heldItem("scope_lens")
@JvmField
val SHARP_BEAK = heldItem("sharp_beak")
@JvmField
val SHED_SHELL = heldItem("shed_shell")
@JvmField
val SHELL_BELL = heldItem("shell_bell")
@JvmField
val SILK_SCARF = heldItem("silk_scarf")
@JvmField
val SILVER_POWDER = heldItem("silver_powder")
@@ -662,10 +740,28 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val SPELL_TAG = heldItem("spell_tag")
@JvmField
val SMOKE_BALL = heldItem("smoke_ball")
@JvmField
val STICKY_BARB = heldItem("sticky_barb")
@JvmField
val TERRAIN_EXTENDER = heldItem("terrain_extender")
@JvmField
val THROAT_SPRAY = heldItem("throat_spray")
@JvmField
val TOXIC_ORB = heldItem("toxic_orb")
@JvmField
val TWISTED_SPOON = heldItem("twisted_spoon")
@JvmField
val UTILITY_UMBRELLA = heldItem("utility_umbrella")
@JvmField
val WEAKNESS_POLICY = heldItem("weakness_policy")
@JvmField
val WIDE_LENS = heldItem("wide_lens")
@JvmField
val WISE_GLASSES = heldItem("wise_glasses")
@JvmField
val ZOOM_LENS = heldItem("zoom_lens")
@JvmField
val MENTAL_HERB = compostableHeldItem("mental_herb", null, 1F)
@JvmField
val MIRROR_HERB = compostableHeldItem("mirror_herb", null, 1F)
@@ -680,29 +776,13 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, RegistryKey<Registry<It
@JvmField
val QUICK_POWDER = heldItem("quick_powder")
@JvmField
val DESTINY_KNOT = heldItem("destiny_knot")
val DAMP_ROCK = heldItem("damp_rock")
@JvmField
val EVERSTONE = heldItem("everstone")
val HEAT_ROCK = heldItem("heat_rock")
@JvmField
val POWER_ANKLET = heldItem("power_anklet")
val SMOOTH_ROCK = heldItem("smooth_rock")
@JvmField
val POWER_BAND = heldItem("power_band")
@JvmField
val POWER_BELT = heldItem("power_belt")
@JvmField
val POWER_BRACER = heldItem("power_bracer")
@JvmField
val POWER_LENS = heldItem("power_lens")
@JvmField
val POWER_WEIGHT = heldItem("power_weight")
@JvmField
val FLAME_ORB = heldItem("flame_orb")
@JvmField
val LIFE_ORB = heldItem("life_orb")
@JvmField
val TOXIC_ORB = heldItem("toxic_orb")
@JvmField
val SMOKE_BALL = heldItem("smoke_ball")
val ICY_ROCK = heldItem("icy_rock")
// Mulch
@JvmField
@@ -96,6 +96,7 @@ open class PokemonBattle(
val chatLog = mutableListOf<Text>()
var started = false
var ended = false
var simulation = false
// TEMP battle showcase stuff
var announcingRules = false
var turn: Int = 1
@@ -205,7 +206,8 @@ open class PokemonBattle(
fun end() {
ended = true
this.actors.forEach { actor ->
// award XP if it is not a simulation battle
if (simulation == false) this.actors.forEach { actor ->
val faintedPokemons = actor.pokemonList.filter { it.health <= 0 }
actor.getSide().getOppositeSide().actors.forEach { opponent ->
val opponentNonFaintedPokemons = opponent.pokemonList.filter { it.health > 0 }
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.battles.PassActionResponse
import com.cobblemon.mod.common.battles.ai.StrongBattleAI
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
@@ -20,7 +21,7 @@ import java.util.UUID
abstract class AIBattleActor(
gameId: UUID,
pokemonList: List<BattlePokemon>,
val battleAI: BattleAI
val battleAI: BattleAI = StrongBattleAI(0)
) : BattleActor(gameId, pokemonList.toMutableList()) {
override fun sendUpdate(packet: NetworkPacket<*>) {
super.sendUpdate(packet)
@@ -13,7 +13,9 @@ import com.cobblemon.mod.common.api.moves.categories.DamageCategory
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.battles.MoveTarget
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.util.lang
import com.google.gson.JsonObject
import com.google.gson.annotations.SerializedName
import net.minecraft.text.MutableText
@@ -45,7 +47,8 @@ open class MoveTemplate(
val pp: Int,
val priority: Int,
val critRatio: Double,
val effectChances: Array<Double>
val effectChances: Array<Double>,
val flags: Set<String>
) {
val displayName: MutableText
@@ -65,7 +68,8 @@ open class MoveTemplate(
pp = 5,
priority = 0,
critRatio = 0.0,
effectChances = emptyArray()
effectChances = emptyArray(),
flags = emptySet()
)
companion object {
@@ -92,4 +96,9 @@ open class MoveTemplate(
template = this
)
}
/**
* Returns this move's showdown data as a [JsonObject]
*/
fun showdownJson() = ShowdownService.service.getMoves()[num].asJsonObject
}
@@ -72,7 +72,22 @@ object Moves : DataRegistry {
effectChances += secondaryMember.get("chance").asDouble
}
}
val move = MoveTemplate(id, num, elementalType, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray())
val flags = mutableSetOf<String>()
jsMove["flags"].asJsonObject.asMap().forEach { flags.add(it.key) }
val move = MoveTemplate(
id,
num,
elementalType,
damageCategory,
power,
target,
accuracy,
pp,
priority,
critRatio,
effectChances.toTypedArray(),
flags
)
this.register(move)
} catch (e: Exception) {
Cobblemon.LOGGER.error("Caught exception trying to resolve the move '{}'", id, e)
@@ -0,0 +1,15 @@
/*
* 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.tags
import com.cobblemon.mod.common.api.moves.MoveTemplate
class MoveTag(
val moves: List<MoveTemplate>
)
@@ -0,0 +1,55 @@
/*
* 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.tags
import com.cobblemon.mod.common.api.moves.Moves
object MoveTags {
private val moves = Moves.all()
val PRIORITY_ZERO = MoveTag(moves.filter { it.priority == 0 })
/* Showdown flags */
val PROTECT = MoveTag(moves.filter { it.flags.contains("protect") })
val CONTACT = MoveTag(moves.filter { it.flags.contains("contact") })
val DISTANCE = MoveTag(moves.filter { it.flags.contains("distance") })
val ALLY_ANIM = MoveTag(moves.filter { it.flags.contains("allyanim") })
val FAIL_ENCORE = MoveTag(moves.filter { it.flags.contains("failencore") })
val FAIL_COPYCAT = MoveTag(moves.filter { it.flags.contains("failcopycat") })
val REFLECTABLE = MoveTag(moves.filter { it.flags.contains("reflectable") })
val BITE = MoveTag(moves.filter { it.flags.contains("bite") })
val NON_SKY = MoveTag(moves.filter { it.flags.contains("nonsky") })
val GRAVITY = MoveTag(moves.filter { it.flags.contains("gravity") })
val POWDER = MoveTag(moves.filter { it.flags.contains("powder") })
val PLEDGE_COMBO = MoveTag(moves.filter { it.flags.contains("pledgecombo") })
val MIRROR = MoveTag(moves.filter { it.flags.contains("mirror") })
val SNATCH = MoveTag(moves.filter { it.flags.contains("snatch") })
val SLICING = MoveTag(moves.filter { it.flags.contains("slicing") })
val WIND = MoveTag(moves.filter { it.flags.contains("wind") })
val NO_SLEEP_TALK = MoveTag(moves.filter { it.flags.contains("nosleeptalk") })
val FAIL_INSTRUCT = MoveTag(moves.filter { it.flags.contains("failinstruct") })
val PULSE = MoveTag(moves.filter { it.flags.contains("pulse") })
val RECHARGE = MoveTag(moves.filter { it.flags.contains("recharge") })
val SOUND = MoveTag(moves.filter { it.flags.contains("sound") })
val PUNCH = MoveTag(moves.filter { it.flags.contains("punch") })
val FUTURE_MOVE = MoveTag(moves.filter { it.flags.contains("futuremove") })
val MUST_PRESSURE = MoveTag(moves.filter { it.flags.contains("mustpressure") })
val HEAL = MoveTag(moves.filter { it.flags.contains("heal") })
val BULLET = MoveTag(moves.filter { it.flags.contains("bullet") })
val BYPASS_SUB = MoveTag(moves.filter { it.flags.contains("bypasssub") })
val DANCE = MoveTag(moves.filter { it.flags.contains("dance") })
val NO_ASSIST = MoveTag(moves.filter { it.flags.contains("noassist") })
val FAIL_MIMIC = MoveTag(moves.filter { it.flags.contains("failmimic") })
val FAIL_ME_FIRST = MoveTag(moves.filter { it.flags.contains("failmefirst") })
val CANT_USE_TWICE = MoveTag(moves.filter { it.flags.contains("cantusetwice") })
val CHARGE = MoveTag(moves.filter { it.flags.contains("charge") })
val DEFROST = MoveTag(moves.filter { it.flags.contains("defrost") })
val NO_PARENTAL_BOND = MoveTag(moves.filter { it.flags.contains("noparentalbond") })
}
@@ -70,6 +70,9 @@ object CobblemonPermissions {
val CLEAR_PARTY = this.create("${COMMAND_PREFIX}clearparty", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
val CLEAR_PC = this.create("${COMMAND_PREFIX}clearpc", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
// Test for starting a random battle with AI Player
val RANDOM_BATTLE = this.create("${COMMAND_PREFIX}randombattle", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
fun all(): Iterable<Permission> = this.permissions
private fun create(node: String, level: PermissionLevel): Permission {
@@ -13,6 +13,7 @@ import com.bedrockk.molang.runtime.value.DoubleValue
import com.bedrockk.molang.runtime.value.StringValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.Abilities
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.aspect.AspectProvider
import com.cobblemon.mod.common.api.pokemon.stats.Stats
@@ -92,6 +93,10 @@ open class PokemonProperties {
props.dmaxLevel = parseIntProperty(keyPairs, listOf("dmax_level", "dmax"))?.coerceIn(0, Cobblemon.config.maxDynamaxLevel)
props.gmaxFactor = parseBooleanProperty(keyPairs, listOf("gmax_factor", "gmax"))
props.tradeable = parseBooleanProperty(keyPairs, listOf("tradeable", "tradable"))
props.move1 = parseStringOfRegistry(keyPairs, listOf("move1", "m1")) { Moves.getByName(it)?.name }
props.move2 = parseStringOfRegistry(keyPairs, listOf("move2", "m2")) { Moves.getByName(it)?.name }
props.move3 = parseStringOfRegistry(keyPairs, listOf("move3", "m3")) { Moves.getByName(it)?.name }
props.move4 = parseStringOfRegistry(keyPairs, listOf("move4", "m4")) { Moves.getByName(it)?.name }
props.originalTrainerType = OriginalTrainerType.values().toList().parsePropertyOfCollection(keyPairs, listOf("originaltrainertype", "ottype"), labelsOptional = true) { it.name.lowercase() }
props.originalTrainer = parsePlayerProperty(keyPairs, listOf("originaltrainer", "ot"))
@@ -274,9 +279,14 @@ open class PokemonProperties {
var dmaxLevel: Int? = null
var gmaxFactor: Boolean? = null
var tradeable: Boolean? = null
var move1: String? = null
var move2: String? = null
var move3: String? = null
var move4: String? = null
var originalTrainerType: OriginalTrainerType? = null
var originalTrainer: String? = null // Original Trainer by Username or UUID
var ivs: IVs? = null
var evs: EVs? = null
var customProperties = mutableListOf<CustomPokemonProperty>()
@@ -329,6 +339,10 @@ open class PokemonProperties {
dmaxLevel?.let { pokemon.dmaxLevel = it }
gmaxFactor?.let { pokemon.gmaxFactor = it }
tradeable?.let { pokemon.tradeable = it }
move1?.let { pokemon.setMove(it, 0) }
move2?.let { pokemon.setMove(it, 1) }
move3?.let { pokemon.setMove(it, 2) }
move4?.let { pokemon.setMove(it, 3) }
// If it has been explicitly set to NONE, clear the stored information, including the originalTrainer property
originalTrainerType?.let {
if (it == OriginalTrainerType.NONE) {
@@ -391,6 +405,10 @@ open class PokemonProperties {
dmaxLevel?.let { pokemonEntity.pokemon.dmaxLevel = it }
gmaxFactor?.let { pokemonEntity.pokemon.gmaxFactor = it }
tradeable?.let { pokemonEntity.pokemon.tradeable = it }
move1?.let { pokemonEntity.pokemon.setMove(it, 0) }
move2?.let { pokemonEntity.pokemon.setMove(it, 1) }
move3?.let { pokemonEntity.pokemon.setMove(it, 2) }
move4?.let { pokemonEntity.pokemon.setMove(it, 3) }
// If it has been explicitly set to NONE, clear the stored information, including the originalTrainer property
originalTrainerType?.let {
if (it == OriginalTrainerType.NONE) {
@@ -451,6 +469,10 @@ open class PokemonProperties {
dmaxLevel?.takeIf { it != pokemon.dmaxLevel }?.let { return false }
gmaxFactor?.takeIf { it != pokemon.gmaxFactor }?.let { return false }
tradeable?.takeIf { it != pokemon.tradeable }?.let { return false }
move1?.takeIf { move -> pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
move2?.takeIf { move -> pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
move3?.takeIf { move -> pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
move4?.takeIf { move -> pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
originalTrainer?.takeIf { it != pokemon.originalTrainer }?.let{ return false }
originalTrainerType?.takeIf { it != pokemon.originalTrainerType }?.let{ return false }
return customProperties.none { !it.matches(pokemon) }
@@ -489,6 +511,10 @@ open class PokemonProperties {
dmaxLevel?.takeIf { it != pokemonEntity.pokemon.dmaxLevel }?.let { return false }
gmaxFactor?.takeIf { it != pokemonEntity.pokemon.gmaxFactor }?.let { return false }
tradeable?.takeIf { it != pokemonEntity.pokemon.tradeable }?.let { return false }
move1?.takeIf { move -> pokemonEntity.pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
move2?.takeIf { move -> pokemonEntity.pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
move3?.takeIf { move -> pokemonEntity.pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
move4?.takeIf { move -> pokemonEntity.pokemon.moveSet.getMoves().none { it.name == move } }?.let { return false }
originalTrainer?.takeIf { it != pokemonEntity.pokemon.originalTrainer }?.let{ return false }
originalTrainerType?.takeIf { it != pokemonEntity.pokemon.originalTrainerType }?.let{ return false }
return customProperties.none { !it.matches(pokemonEntity) }
@@ -535,6 +561,10 @@ open class PokemonProperties {
dmaxLevel?.takeIf { it != properties.dmaxLevel }?.let { return false }
gmaxFactor?.takeIf { it != properties.gmaxFactor }?.let { return false }
tradeable?.takeIf { it != properties.tradeable }?.let { return false }
move1?.takeIf { it != properties.move1 }?.let { return false }
move2?.takeIf { it != properties.move2 }?.let { return false }
move3?.takeIf { it != properties.move3 }?.let { return false }
move4?.takeIf { it != properties.move4 }?.let { return false }
originalTrainer?.takeIf { it != properties.originalTrainer }?.let{ return false }
originalTrainerType?.takeIf { it != properties.originalTrainerType }?.let{ return false }
return true
@@ -543,7 +573,8 @@ open class PokemonProperties {
fun create(): Pokemon {
val pokemon = Pokemon()
apply(pokemon)
pokemon.initialize()
if (move1 == null) //if there is not a move1 or later specific moves stated then initialize
pokemon.initialize()
roll(pokemon)
return pokemon
}
@@ -33,6 +33,7 @@ import com.cobblemon.mod.common.api.pokemon.stats.Stats
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.api.spawning.TimeRange
import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.api.types.ElementalTypes
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
import com.cobblemon.mod.common.net.messages.client.data.SpeciesRegistrySyncPacket
import com.cobblemon.mod.common.pokemon.FormData
@@ -171,6 +172,9 @@ object PokemonSpecies : JsonDataRegistry<Species> {
*/
fun random(): Species = this.implemented.random()
// overloaded function to give random pokemon species of a certain type
fun random(type: ElementalType): Species = this.implemented.filter { it.primaryType == type || it.secondaryType == type }.random()
override fun reload(data: Map<Identifier, Species>) {
this.speciesByIdentifier.clear()
this.implemented.clear()
File diff suppressed because it is too large Load Diff
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.events.battles.BattleStartedPreEvent
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
import com.cobblemon.mod.common.api.storage.party.PartyStore
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.battles.runner.ShowdownService
import com.cobblemon.mod.common.net.messages.client.battle.BattleChallengeExpiredPacket
@@ -44,6 +45,7 @@ object BattleRegistry {
.registerTypeAdapter(ShowdownMoveset::class.java, ShowdownMovesetAdapter)
.create()
private val battleMap = ConcurrentHashMap<UUID, PokemonBattle>()
private val partyMap = ConcurrentHashMap<UUID, List<PartyStore>>()
// Challenger to challenge
val pvpChallenges = mutableMapOf<UUID, BattleChallenge>()
@@ -201,10 +203,11 @@ object BattleRegistry {
}
fun startBattle(
battleFormat: BattleFormat,
side1: BattleSide,
side2: BattleSide,
silent: Boolean = false
battleFormat: BattleFormat,
side1: BattleSide,
side2: BattleSide,
silent: Boolean = false,
clonePartyStores: List<PartyStore>? = null // used for cloned team battles
): BattleStartResult {
val battle = PokemonBattle(battleFormat, side1, side2)
if (silent) return SuccessfulBattleStart(battle)
@@ -212,6 +215,9 @@ object BattleRegistry {
val preBattleEvent = BattleStartedPreEvent(battle)
CobblemonEvents.BATTLE_STARTED_PRE.postThen(preBattleEvent) {
battleMap[battle.battleId] = battle
if(clonePartyStores != null) {
partyMap[battle.battleId] = clonePartyStores
}
startShowdown(battle)
CobblemonEvents.BATTLE_STARTED_POST.post(BattleStartedPostEvent(battle))
return SuccessfulBattleStart(battle)
@@ -221,6 +227,7 @@ object BattleRegistry {
fun closeBattle(battle: PokemonBattle) {
battleMap.remove(battle.battleId)
partyMap.remove(battle.battleId)
}
fun getBattle(id: UUID) : PokemonBattle? {
@@ -387,6 +387,8 @@ class ShowdownPokemon {
lateinit var baseAbility: String
lateinit var pokeball: String
lateinit var ability: String
var baseTypes = mutableListOf<String>()
var types = mutableListOf<String>()
var reviving: Boolean = false
val uuid: UUID by lazy { UUID.fromString(details.split(",")[1].trim()) }
@@ -401,6 +403,11 @@ class ShowdownPokemon {
buffer.writeString(baseAbility)
buffer.writeString(pokeball)
buffer.writeString(ability)
buffer.writeSizedInt(IntSize.U_BYTE, baseTypes.size)
baseTypes.forEach(buffer::writeString)
buffer.writeSizedInt(IntSize.U_BYTE, types.size)
types.forEach(buffer::writeString)
}
fun loadFromBuffer(buffer: PacketByteBuf): ShowdownPokemon {
@@ -415,6 +422,12 @@ class ShowdownPokemon {
baseAbility = buffer.readString()
pokeball = buffer.readString()
ability = buffer.readString()
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
baseTypes.add(buffer.readString())
}
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
types.add(buffer.readString())
}
return this
}
}
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.battles.ai.RandomBattleAI
import com.cobblemon.mod.common.battles.ai.StrongBattleAI
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
@@ -29,7 +30,8 @@ open class PokemonBattleActor(
uuid: UUID,
val pokemon: BattlePokemon,
override val fleeDistance: Float,
artificialDecider: BattleAI = RandomBattleAI()
//artificialDecider: BattleAI = RandomBattleAI()
artificialDecider: BattleAI = StrongBattleAI(0)
) : AIBattleActor(uuid, listOf(pokemon), artificialDecider), EntityBackedBattleActor<PokemonEntity>, FleeableBattleActor {
override fun getName() = pokemon.effectedPokemon.species.translatedName
override fun nameOwned(name: String): MutableText = Text.literal(name)
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.battles.actor
import com.cobblemon.mod.common.api.battles.model.actor.AIBattleActor
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.battles.model.ai.BattleAI
import com.cobblemon.mod.common.battles.ai.StrongBattleAI
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.asTranslated
import com.cobblemon.mod.common.util.battleLang
@@ -18,10 +19,11 @@ import java.util.UUID
import net.minecraft.text.MutableText
class TrainerBattleActor(
val trainerName: String,
uuid: UUID,
pokemonList: List<BattlePokemon>,
artificialDecider: BattleAI
val trainerName: String,
uuid: UUID,
pokemonList: List<BattlePokemon>,
skill: Int,
artificialDecider: BattleAI = StrongBattleAI(skill)
) : AIBattleActor(uuid, pokemonList, artificialDecider) {
override fun getName() = trainerName.asTranslated()
override fun nameOwned(name: String): MutableText = battleLang("owned_pokemon", this.getName(), name)
File diff suppressed because it is too large Load Diff
@@ -116,12 +116,12 @@ class BattleGUI : Screen(battleLang("gui.title")) {
val currentSelection = getCurrentActionSelection()
if (currentSelection == null || currentSelection is BattleGeneralActionSelection ) {
drawScaledText(
context = context,
text = battleLang("ui.hide_label", PartySendBinding.boundKey().localizedText),
x = MinecraftClient.getInstance().window.scaledWidth / 2,
y = (MinecraftClient.getInstance().window.scaledHeight / 5),
opacity = 0.75F * opacity,
centered = true
context = context,
text = battleLang("ui.hide_label", PartySendBinding.boundKey().localizedText),
x = MinecraftClient.getInstance().window.scaledWidth / 2,
y = (MinecraftClient.getInstance().window.scaledHeight / 5),
opacity = 0.75F * opacity,
centered = true
)
}
@@ -25,16 +25,16 @@ import net.minecraft.client.util.math.MatrixStack
import net.minecraft.text.MutableText
import net.minecraft.util.Identifier
class BattleGeneralActionSelection(
battleGUI: BattleGUI,
request: SingleActionRequest
battleGUI: BattleGUI,
request: SingleActionRequest
) : BattleActionSelection(
battleGUI,
request,
BattleGUI.OPTION_ROOT_X,
MinecraftClient.getInstance().window.scaledHeight - BattleGUI.OPTION_VERTICAL_OFFSET,
(BattleOptionTile.OPTION_WIDTH + 3 * BattleGUI.OPTION_HORIZONTAL_SPACING).toInt(),
(BattleOptionTile.OPTION_HEIGHT + 3 * BattleGUI.OPTION_VERTICAL_SPACING).toInt(),
battleLang("choose_action")
battleGUI,
request,
BattleGUI.OPTION_ROOT_X,
MinecraftClient.getInstance().window.scaledHeight - BattleGUI.OPTION_VERTICAL_OFFSET,
(BattleOptionTile.OPTION_WIDTH + 3 * BattleGUI.OPTION_HORIZONTAL_SPACING).toInt(),
(BattleOptionTile.OPTION_HEIGHT + 3 * BattleGUI.OPTION_VERTICAL_SPACING).toInt(),
battleLang("choose_action")
) {
val tiles = mutableListOf<BattleOptionTile>()
init {
@@ -74,14 +74,14 @@ class BattleGeneralActionSelection(
val x = if (rank % 2 == 0) BattleGUI.OPTION_ROOT_X else BattleGUI.OPTION_ROOT_X + BattleGUI.OPTION_HORIZONTAL_SPACING + BattleOptionTile.OPTION_WIDTH
val y = if (rank > 1) startY + BattleOptionTile.OPTION_HEIGHT + BattleGUI.OPTION_HORIZONTAL_SPACING else startY
tiles.add(
BattleOptionTile(
battleGUI = battleGUI,
x = x,
y = y,
resource = texture,
text = text,
onClick = onClick
)
BattleOptionTile(
battleGUI = battleGUI,
x = x,
y = y,
resource = texture,
text = text,
onClick = onClick
)
)
}
@@ -138,7 +138,8 @@ abstract class BattleGimmickButton(gimmick: ShowdownMoveset.Gimmick, val x: Floa
pp = gimmickTemplate?.pp ?: moveTemplate.pp,
priority = gimmickTemplate?.priority ?: moveTemplate.priority,
critRatio = gimmickTemplate?.critRatio ?: moveTemplate.critRatio,
effectChances = gimmickTemplate?.effectChances ?: moveTemplate.effectChances
effectChances = gimmickTemplate?.effectChances ?: moveTemplate.effectChances,
flags = gimmickTemplate!!.flags
)
}
}
@@ -35,16 +35,16 @@ import net.minecraft.text.Text
import net.minecraft.util.math.MathHelper.floor
class BattleMoveSelection(
battleGUI: BattleGUI,
request: SingleActionRequest,
battleGUI: BattleGUI,
request: SingleActionRequest,
) : BattleActionSelection(
battleGUI = battleGUI,
request = request,
x = 20,
y = MinecraftClient.getInstance().window.scaledHeight - 84,
width = 100,
height = 100,
battleLang("ui.select_move")
battleGUI = battleGUI,
request = request,
x = 20,
y = MinecraftClient.getInstance().window.scaledHeight - 84,
width = 100,
height = 100,
battleLang("ui.select_move")
) {
companion object {
const val MOVE_WIDTH = 92
@@ -77,10 +77,10 @@ class BattleMoveSelection(
}
open class MoveTile(
val moveSelection: BattleMoveSelection,
val move: InBattleMove,
val x: Float,
val y: Float,
val moveSelection: BattleMoveSelection,
val move: InBattleMove,
val x: Float,
val y: Float,
) {
var moveTemplate = Moves.getByNameOrDummy(move.id)
var rgb = moveTemplate.elementalType.hue.toRGB()
@@ -102,54 +102,54 @@ class BattleMoveSelection(
val selectConditionOpacity = moveSelection.opacity * if (!selectable) 0.5F else 1F
blitk(
matrixStack = context.matrices,
texture = moveTexture,
x = x,
y = y,
width = MOVE_WIDTH,
height = MOVE_HEIGHT,
vOffset = if (selectable && isHovered(mouseX.toDouble(), mouseY.toDouble())) MOVE_HEIGHT else 0,
textureHeight = MOVE_HEIGHT * 2,
red = rgb.first,
green = rgb.second,
blue = rgb.third,
alpha = selectConditionOpacity
matrixStack = context.matrices,
texture = moveTexture,
x = x,
y = y,
width = MOVE_WIDTH,
height = MOVE_HEIGHT,
vOffset = if (selectable && isHovered(mouseX.toDouble(), mouseY.toDouble())) MOVE_HEIGHT else 0,
textureHeight = MOVE_HEIGHT * 2,
red = rgb.first,
green = rgb.second,
blue = rgb.third,
alpha = selectConditionOpacity
)
blitk(
matrixStack = context.matrices,
texture = moveOverlayTexture,
x = x,
y = y,
width = MOVE_WIDTH,
height = MOVE_HEIGHT,
alpha = moveSelection.opacity
matrixStack = context.matrices,
texture = moveOverlayTexture,
x = x,
y = y,
width = MOVE_WIDTH,
height = MOVE_HEIGHT,
alpha = moveSelection.opacity
)
// Type Icon
TypeIcon(
x = x - 9,
y = y + 2,
type = moveTemplate.elementalType,
opacity = moveSelection.opacity
x = x - 9,
y = y + 2,
type = moveTemplate.elementalType,
opacity = moveSelection.opacity
).render(context)
// Move Category
MoveCategoryIcon(
x = x + 48,
y = y + 14.5,
category = moveTemplate.damageCategory,
opacity = moveSelection.opacity
x = x + 48,
y = y + 14.5,
category = moveTemplate.damageCategory,
opacity = moveSelection.opacity
).render(context)
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = moveTemplate.displayName.bold(),
x = x + 17,
y = y + 2,
opacity = selectConditionOpacity,
shadow = true
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = moveTemplate.displayName.bold(),
x = x + 17,
y = y + 2,
opacity = selectConditionOpacity,
shadow = true
)
var movePPText = Text.literal("${move.pp}/${move.maxpp}").bold()
@@ -163,13 +163,13 @@ class BattleMoveSelection(
}
drawScaledText(
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = movePPText,
x = x + 75,
y = y + 14,
opacity = moveSelection.opacity,
centered = true
context = context,
font = CobblemonResources.DEFAULT_LARGE,
text = movePPText,
x = x + 75,
y = y + 14,
opacity = moveSelection.opacity,
centered = true
)
}
@@ -26,16 +26,16 @@ import net.minecraft.client.util.math.MatrixStack
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.util.math.MathHelper.ceil
class BattleSwitchPokemonSelection(
battleGUI: BattleGUI,
request: SingleActionRequest
battleGUI: BattleGUI,
request: SingleActionRequest
) : BattleActionSelection(
battleGUI,
request,
x = 12,
y = ceil((MinecraftClient.getInstance().window.scaledHeight / 2) - (((SWITCH_TILE_HEIGHT * 3) + (SWITCH_TILE_VERTICAL_SPACING * 2)) / 2)),
width = 250,
height = 100,
battleLang("switch_pokemon")
battleGUI,
request,
x = 12,
y = ceil((MinecraftClient.getInstance().window.scaledHeight / 2) - (((SWITCH_TILE_HEIGHT * 3) + (SWITCH_TILE_VERTICAL_SPACING * 2)) / 2)),
width = 250,
height = 100,
battleLang("switch_pokemon")
) {
companion object {
const val SWITCH_TILE_WIDTH = BattleOverlay.TILE_WIDTH
@@ -48,11 +48,11 @@ class BattleSwitchPokemonSelection(
val backButton = BattleBackButton(x - 3F, MinecraftClient.getInstance().window.scaledHeight - 22F )
class SwitchTile(
val selection: BattleSwitchPokemonSelection,
val x: Float,
val y: Float,
val pokemon: Pokemon,
val showdownPokemon: ShowdownPokemon
val selection: BattleSwitchPokemonSelection,
val x: Float,
val y: Float,
val pokemon: Pokemon,
val showdownPokemon: ShowdownPokemon
) {
fun isHovered(mouseX: Double, mouseY: Double) = mouseX in x..(x + SWITCH_TILE_WIDTH) && mouseY in (y..(y + SWITCH_TILE_HEIGHT))
fun render(context: DrawContext, mouseX: Double, mouseY: Double, deltaTicks: Float) {
@@ -64,23 +64,23 @@ class BattleSwitchPokemonSelection(
healthRatioSplits[0].toInt() to pokemon.hp
}
CobblemonClient.battleOverlay.drawBattleTile(
context = context,
x = x,
y = y,
reversed = false,
species = pokemon.species,
level = pokemon.level,
aspects = pokemon.aspects,
displayName = pokemon.getDisplayName(),
gender = pokemon.gender,
status = pokemon.status?.status,
maxHealth = maxHp,
health = hp.toFloat(),
isFlatHealth = true,
state = null,
colour = null,
opacity = selection.opacity,
partialTicks = deltaTicks
context = context,
x = x,
y = y,
reversed = false,
species = pokemon.species,
level = pokemon.level,
aspects = pokemon.aspects,
displayName = pokemon.getDisplayName(),
gender = pokemon.gender,
status = pokemon.status?.status,
maxHealth = maxHp,
health = hp.toFloat(),
isFlatHealth = true,
state = null,
colour = null,
opacity = selection.opacity,
partialTicks = deltaTicks
)
} catch (exception: Exception) {
throw exception
@@ -92,20 +92,20 @@ class BattleSwitchPokemonSelection(
val pendingActionRequests = CobblemonClient.battle!!.pendingActionRequests
val switchingInPokemon = pendingActionRequests.mapNotNull { it.response }.filterIsInstance<SwitchActionResponse>().map { it.newPokemonId }
val showdownPokemonToPokemon = request.side!!.pokemon
.mapNotNull { showdownPokemon ->
battleGUI.actor!!.pokemon
.find { it.uuid == showdownPokemon.uuid }
?.let { showdownPokemon to it }
}
.filter {
if (request.side.pokemon[0].reviving) {
"fnt" in it.first.condition
} else {
"fnt" !in it.first.condition
.mapNotNull { showdownPokemon ->
battleGUI.actor!!.pokemon
.find { it.uuid == showdownPokemon.uuid }
?.let { showdownPokemon to it }
}
}
.filter { it.second.uuid !in battleGUI.actor!!.activePokemon.map { it.battlePokemon?.uuid } }
.filter { it.second.uuid !in switchingInPokemon }
.filter {
if (request.side.pokemon[0].reviving) {
"fnt" in it.first.condition
} else {
"fnt" !in it.first.condition
}
}
.filter { it.second.uuid !in battleGUI.actor!!.activePokemon.map { it.battlePokemon?.uuid } }
.filter { it.second.uuid !in switchingInPokemon }
showdownPokemonToPokemon.forEachIndexed { index, (showdownPokemon, pokemon) ->
val row = index / 2
@@ -89,17 +89,6 @@ class InfoWidget(
)
typeWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Original Trainer
val otName: MutableText = Text.literal(pokemon.originalTrainerName ?: "")
val otWidget = InfoOneLineWidget(
pX = x,
pY = y + 3 * ROW_HEIGHT,
width = width,
label = lang("ui.info.original_trainer"),
value = otName
)
otWidget.render(context, pMouseX, pMouseY, pPartialTicks)
// Nature
// Get the name of the MintItem used to mint the Pokémon's nature
@@ -0,0 +1,139 @@
/*
* 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.battles.BattleBuilder
import com.cobblemon.mod.common.util.permission
import com.mojang.brigadier.Command.SINGLE_SUCCESS
import com.mojang.brigadier.CommandDispatcher
import com.mojang.brigadier.arguments.IntegerArgumentType
import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.context.CommandContext
import net.minecraft.command.argument.EntityArgumentType
import net.minecraft.server.command.CommandManager.argument
import net.minecraft.server.command.CommandManager.literal
import net.minecraft.server.command.ServerCommandSource
object RandomBattleCommand {
// todo add param before number or type for AI subtypes
fun register(dispatcher: CommandDispatcher<ServerCommandSource>) {
dispatcher.register(
literal("randombattle")
.permission(CobblemonPermissions.RANDOM_BATTLE)
.then(
argument("player", EntityArgumentType.player())
.then(
argument("aiType", StringArgumentType.string())
.then(
argument("number", IntegerArgumentType.integer())
.executes { executeNumber(it, 50, "random") } // If only number is provided after aiType
.then(
argument("type", StringArgumentType.string())
.executes { executeWithNumberType(it) } // If number and type are provided after aiType
)
)
.then(
argument("type", StringArgumentType.string())
.executes { executeType(it, "random", 50) } // If only type is provided after aiType
.then(
argument("number", IntegerArgumentType.integer())
.executes { executeWithTypeNumber(it) } // If type and number are provided after aiType
)
)
.executes { executeAITypeDefault(it, 50, "random") } // Default if neither number nor type is provided after aiType
)
.executes { executeDefault(it, "random", 50, "random") } // Default if aiType is not provided
)
)
}
// NUMBER and TYPE
private fun executeWithNumberType(context: CommandContext<ServerCommandSource>): Int {
val player = EntityArgumentType.getPlayer(context, "player")
val aiType = StringArgumentType.getString(context,"aiType").lowercase()
val number = IntegerArgumentType.getInteger(context, "number")
val type = StringArgumentType.getString(context, "type")
// Your command logic here using 'player', 'number', and 'stringArg'
BattleBuilder.pvc(player, aiType, number, type, true)
return SINGLE_SUCCESS
}
// TYPE and NUMBER
private fun executeWithTypeNumber(context: CommandContext<ServerCommandSource>): Int {
val player = EntityArgumentType.getPlayer(context, "player")
val aiType = StringArgumentType.getString(context,"aiType").lowercase()
val number = IntegerArgumentType.getInteger(context, "number")
val type = StringArgumentType.getString(context, "type")
// Your command logic here using 'player', 'number', and 'stringArg'
BattleBuilder.pvc(player,aiType, number, type, true)
return SINGLE_SUCCESS
}
// if no type is given to the command after the integer for level NUMBER
private fun executeNumber(context: CommandContext<ServerCommandSource>, defaultNumber: Int, defaultString: String): Int {
val player = EntityArgumentType.getPlayer(context, "player")
val aiType = StringArgumentType.getString(context,"aiType").lowercase()
val number = IntegerArgumentType.getInteger(context, "number")
// Use default string
val type = defaultString
// Your command logic here using 'player', 'number', and 'stringArg'
BattleBuilder.pvc(player, aiType, number, type, true)
return SINGLE_SUCCESS
}
// if no type is given to the command after the integer for level NUMBER
private fun executeType(context: CommandContext<ServerCommandSource>, defaultString: String, defaultNumber: Int): Int {
val player = EntityArgumentType.getPlayer(context, "player")
val aiType = StringArgumentType.getString(context,"aiType").lowercase()
val type = StringArgumentType.getString(context, "type")
// Use default string
val number = defaultNumber
// Your command logic here using 'player', 'number', and 'stringArg'
BattleBuilder.pvc(player, aiType, number, type, true)
return SINGLE_SUCCESS
}
// if no additional arguments are provided after player DEFAULT
private fun executeDefault(context: CommandContext<ServerCommandSource>, defaultAIType: String, defaultNumber: Int, defaultString: String): Int {
val player = EntityArgumentType.getPlayer(context, "player")
val aiType = defaultAIType
val number = defaultNumber
val type = defaultString
// Your command logic here using 'player', 'number', and 'stringArg'
BattleBuilder.pvc(player, aiType, number, type, true)
return SINGLE_SUCCESS
}
// DEFAULT WITH AI Type
private fun executeAITypeDefault(context: CommandContext<ServerCommandSource>, defaultNumber: Int, defaultString: String): Int {
val player = EntityArgumentType.getPlayer(context, "player")
val aiType = StringArgumentType.getString(context,"aiType").lowercase()
val number = defaultNumber
val type = defaultString
// Your command logic here using 'player', 'number', and 'stringArg'
BattleBuilder.pvc(player, aiType, number, type, true)
return SINGLE_SUCCESS
}
}
@@ -359,37 +359,58 @@ object CobblemonItemGroups {
}
private fun heldItemEntries(displayContext: DisplayContext, entries: Entries) {
entries.add(CobblemonItems.ABILITY_SHIELD)
entries.add(CobblemonItems.ABSORB_BULB)
entries.add(CobblemonItems.AIR_BALLOON)
entries.add(CobblemonItems.ASSAULT_VEST)
entries.add(CobblemonItems.BIG_ROOT)
entries.add(CobblemonItems.BINDING_BAND)
entries.add(CobblemonItems.BLACK_BELT)
entries.add(CobblemonItems.BLACK_GLASSES)
entries.add(CobblemonItems.BLACK_SLUDGE)
entries.add(CobblemonItems.BLUNDER_POLICY)
entries.add(CobblemonItems.BRIGHT_POWDER)
entries.add(CobblemonItems.CELL_BATTERY)
entries.add(CobblemonItems.CHARCOAL)
entries.add(CobblemonItems.CHOICE_BAND)
entries.add(CobblemonItems.CHOICE_SCARF)
entries.add(CobblemonItems.CHOICE_SPECS)
entries.add(CobblemonItems.CLEANSE_TAG)
entries.add(CobblemonItems.CLEAR_AMULET)
entries.add(CobblemonItems.COVERT_CLOAK)
entries.add(CobblemonItems.DEEP_SEA_SCALE)
entries.add(CobblemonItems.DEEP_SEA_TOOTH)
entries.add(CobblemonItems.DESTINY_KNOT)
entries.add(CobblemonItems.DRAGON_FANG)
entries.add(CobblemonItems.EJECT_BUTTON)
entries.add(CobblemonItems.EJECT_PACK)
entries.add(CobblemonItems.EVERSTONE)
entries.add(CobblemonItems.EVIOLITE)
entries.add(CobblemonItems.EXP_SHARE)
entries.add(CobblemonItems.EXPERT_BELT)
entries.add(CobblemonItems.FAIRY_FEATHER)
entries.add(CobblemonItems.FLAME_ORB)
entries.add(CobblemonItems.FLOAT_STONE)
entries.add(CobblemonItems.FOCUS_BAND)
entries.add(CobblemonItems.FOCUS_SASH)
entries.add(CobblemonItems.GRIP_CLAW)
entries.add(CobblemonItems.HARD_STONE)
entries.add(CobblemonItems.HEAVY_DUTY_BOOTS)
entries.add(CobblemonItems.IRON_BALL)
entries.add(CobblemonItems.KINGS_ROCK)
entries.add(CobblemonItems.LAGGING_TAIL)
entries.add(CobblemonItems.LEFTOVERS)
entries.add(CobblemonItems.LIFE_ORB)
entries.add(CobblemonItems.LIGHT_BALL)
entries.add(CobblemonItems.LIGHT_CLAY)
entries.add(CobblemonItems.LOADED_DICE)
entries.add(CobblemonItems.LUCKY_EGG)
entries.add(CobblemonItems.LUMINOUS_MOSS)
entries.add(CobblemonItems.MAGNET)
entries.add(CobblemonItems.MENTAL_HERB)
entries.add(CobblemonItems.METAL_COAT)
entries.add(CobblemonItems.METAL_POWDER)
entries.add(CobblemonItems.METRONOME)
entries.add(CobblemonItems.MIRACLE_SEED)
entries.add(CobblemonItems.MIRROR_HERB)
entries.add(CobblemonItems.MUSCLE_BAND)
@@ -403,22 +424,41 @@ object CobblemonItemGroups {
entries.add(CobblemonItems.POWER_LENS)
entries.add(CobblemonItems.POWER_WEIGHT)
entries.add(CobblemonItems.POWER_HERB)
entries.add(CobblemonItems.PROTECTIVE_PADS)
entries.add(CobblemonItems.PUNCHING_GLOVE)
entries.add(CobblemonItems.QUICK_CLAW)
entries.add(CobblemonItems.QUICK_POWDER)
entries.add(CobblemonItems.RAZOR_CLAW)
entries.add(CobblemonItems.RAZOR_FANG)
entries.add(CobblemonItems.RED_CARD)
entries.add(CobblemonItems.RING_TARGET)
entries.add(CobblemonItems.ROCKY_HELMET)
entries.add(CobblemonItems.ROOM_SERVICE)
entries.add(CobblemonItems.SAFETY_GOGGLES)
entries.add(CobblemonItems.SCOPE_LENS)
entries.add(CobblemonItems.SHARP_BEAK)
entries.add(CobblemonItems.SHED_SHELL)
entries.add(CobblemonItems.SHELL_BELL)
entries.add(CobblemonItems.SILK_SCARF)
entries.add(CobblemonItems.SILVER_POWDER)
entries.add(CobblemonItems.SMOKE_BALL)
entries.add(CobblemonItems.SOFT_SAND)
entries.add(CobblemonItems.SPELL_TAG)
entries.add(CobblemonItems.STICKY_BARB)
entries.add(CobblemonItems.TERRAIN_EXTENDER)
entries.add(CobblemonItems.THROAT_SPRAY)
entries.add(CobblemonItems.TOXIC_ORB)
entries.add(CobblemonItems.TWISTED_SPOON)
entries.add(CobblemonItems.UTILITY_UMBRELLA)
entries.add(CobblemonItems.WEAKNESS_POLICY)
entries.add(CobblemonItems.WHITE_HERB)
entries.add(CobblemonItems.WIDE_LENS)
entries.add(CobblemonItems.WISE_GLASSES)
entries.add(CobblemonItems.ZOOM_LENS)
entries.add(CobblemonItems.DAMP_ROCK)
entries.add(CobblemonItems.HEAT_ROCK)
entries.add(CobblemonItems.SMOOTH_ROCK)
entries.add(CobblemonItems.ICY_ROCK)
}
private fun pokeballentries(displayContext: DisplayContext, entries: Entries) {
@@ -47,10 +47,11 @@ class MovesRegistrySyncPacket(moves: List<MoveTemplate>) : DataRegistrySyncPacke
val priority = buffer.readInt()
val critRatio = buffer.readDouble()
val effectChances = arrayListOf<Double>()
val flags = mutableSetOf<String>()
repeat(buffer.readVarInt()) {
effectChances += buffer.readDouble()
}
return MoveTemplate(name, num, type, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray())
return MoveTemplate(name, num, type, damageCategory, power, target, accuracy, pp, priority, critRatio, effectChances.toTypedArray(), flags)
}
override fun synchronizeDecoded(entries: Collection<MoveTemplate>) {
@@ -159,6 +159,20 @@ open class Pokemon : ShowdownIdentifiable {
_evs.emit(evs)
}
fun setMoveset(moveset: List<String>) {
moveset.forEachIndexed { index, it ->
this.benchedMoves.add(BenchedMove(Moves.getByName(it)!!, 0))
this.exchangeMove( this.moveSet[index]!!.template, Moves.getByName(it)!!)
}
}
fun setMove(move: String, moveSlot: Int) {
if (moveSlot < this.moveSet.getMoves().size) {
this.benchedMoves.add(BenchedMove(Moves.getByName(move)!!, 0))
this.exchangeMove(this.moveSet[moveSlot]!!.template, Moves.getByName(move)!!)
}
}
var nickname: MutableText? = null
set(value) {
field = value
@@ -751,9 +765,9 @@ open class Pokemon : ShowdownIdentifiable {
experience = nbt.getInt(DataKeys.POKEMON_EXPERIENCE).takeIf { experienceGroup.getLevel(it) == level } ?: experienceGroup.getExperience(level)
friendship = nbt.getShort(DataKeys.POKEMON_FRIENDSHIP).toInt().coerceIn(0, if (this.isClient) Int.MAX_VALUE else Cobblemon.config.maxPokemonFriendship)
gender = Gender.valueOf(nbt.getString(DataKeys.POKEMON_GENDER).takeIf { it.isNotBlank() } ?: Gender.MALE.name)
currentHealth = nbt.getShort(DataKeys.POKEMON_HEALTH).toInt()
ivs.loadFromNBT(nbt.getCompound(DataKeys.POKEMON_IVS))
evs.loadFromNBT(nbt.getCompound(DataKeys.POKEMON_EVS))
currentHealth = nbt.getShort(DataKeys.POKEMON_HEALTH).toInt()
moveSet.loadFromNBT(nbt)
scaleModifier = nbt.getFloat(DataKeys.POKEMON_SCALE_MODIFIER)
val abilityNBT = nbt.getCompound(DataKeys.POKEMON_ABILITY) ?: NbtCompound()
@@ -879,10 +893,10 @@ open class Pokemon : ShowdownIdentifiable {
level = json.get(DataKeys.POKEMON_LEVEL).asInt
experience = json.get(DataKeys.POKEMON_EXPERIENCE).asInt.takeIf { experienceGroup.getLevel(it) == level } ?: experienceGroup.getExperience(level)
friendship = json.get(DataKeys.POKEMON_FRIENDSHIP).asInt.coerceIn(0, if (this.isClient) Int.MAX_VALUE else Cobblemon.config.maxPokemonFriendship)
currentHealth = json.get(DataKeys.POKEMON_HEALTH).asInt
gender = Gender.valueOf(json.get(DataKeys.POKEMON_GENDER)?.asString ?: "male")
ivs.loadFromJSON(json.getAsJsonObject(DataKeys.POKEMON_IVS))
evs.loadFromJSON(json.getAsJsonObject(DataKeys.POKEMON_EVS))
currentHealth = json.get(DataKeys.POKEMON_HEALTH).asInt
moveSet.loadFromJSON(json.get(DataKeys.POKEMON_MOVESET).asJsonObject)
scaleModifier = json.get(DataKeys.POKEMON_SCALE_MODIFIER).asFloat
val abilityJSON = json.get(DataKeys.POKEMON_ABILITY)?.asJsonObject ?: JsonObject()
@@ -1145,6 +1159,50 @@ open class Pokemon : ShowdownIdentifiable {
return this
}
// overloaded version that has boolean for whether to initialize moves or not
fun initialize(initializeMoves: Boolean = true): Pokemon {
// Force the setter to initialize it
species = species
checkGender()
checkAbility()
// This should only be a thing once we have moveset control in properties until then a creation should require a moveset init.
/*
if (pokemon.moveSet.none { it != null }) {
pokemon.initializeMoveset()
}
*/
if (initializeMoves)
initializeMoveset()
return this
}
// overloaded version that initializes a pokemon with a certain typing
fun initialize(typing: ElementalType): Pokemon {
// Force the setter to initialize it
species = PokemonSpecies.random(typing)
// initialize the rest of the pokemon
if (PokemonSpecies.getByIdentifier(species.resourceIdentifier) == null) {
throw IllegalArgumentException("Cannot set a species that isn't registered")
}
val quotient = clamp(currentHealth / hp.toFloat(), 0F, 1F)
//field = species // todo do I need field? I don't think so
val newFeatures = SpeciesFeatures.getFeaturesFor(species).mapNotNull { it.invoke(this) }
features.clear()
features.addAll(newFeatures)
this.evolutionProxy.current().clear()
updateAspects()
updateForm()
checkGender()
checkAbility()
updateHP(quotient)
_species.emit(species)
initializeMoveset()
return this
}
// Last flower fed to a Mooshtank
var lastFlowerFed: ItemStack = ItemStack.EMPTY
@@ -1382,6 +1440,14 @@ open class Pokemon : ShowdownIdentifiable {
move.raisedPpStages = benchedNewMove.ppRaisedStages
move.currentPp = move.maxPp
moveSet.add(move)
// Inserts the new move in the old move's position and pushes the other move's down a postion
val srcIdx = moveSet.indexOf(moveSet.find { it.template == oldMove })
val dstIdx = moveSet.indexOf(moveSet.find { it.template == newMove })
var currIdx = srcIdx + 1
while(currIdx <= dstIdx) {
moveSet.swapMove(srcIdx, currIdx)
currIdx++
}
return true
}
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.pokemon.properties
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.abilities.Abilities
import com.cobblemon.mod.common.api.data.DataRegistry
import com.cobblemon.mod.common.api.moves.Moves
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.Natures
import com.cobblemon.mod.common.api.pokemon.stats.Stats
@@ -141,8 +142,10 @@ internal object PropertiesCompletionProvider : DataRegistry {
this.inject(setOf("gmax"), setOf("yes", "no"))
this.inject(setOf("tera"), ElementalTypes.all().map { it.name })
this.inject(setOf("tradeable"), setOf("yes", "no"))
this.inject(setOf("originaltrainer", "ot"), setOf(""))
this.inject(setOf("originaltrainertype", "ottype"), setOf("None", "Player", "NPC"))
this.inject(setOf("move1"), Moves.all().map { if (it.name.asIdentifierDefaultingNamespace().namespace == Cobblemon.MODID) it.name.asIdentifierDefaultingNamespace().path else it.name })
this.inject(setOf("move2"), Moves.all().map { if (it.name.asIdentifierDefaultingNamespace().namespace == Cobblemon.MODID) it.name.asIdentifierDefaultingNamespace().path else it.name })
this.inject(setOf("move3"), Moves.all().map { if (it.name.asIdentifierDefaultingNamespace().namespace == Cobblemon.MODID) it.name.asIdentifierDefaultingNamespace().path else it.name })
this.inject(setOf("move4"), Moves.all().map { if (it.name.asIdentifierDefaultingNamespace().namespace == Cobblemon.MODID) it.name.asIdentifierDefaultingNamespace().path else it.name })
Stats.PERMANENT.forEach{ stat ->
val statName = stat.toString().lowercase()
@@ -161,44 +161,81 @@
"item.cobblemon.jolly_mint": "Jolly Mint",
"item.cobblemon.naive_mint": "Naive Mint",
"item.cobblemon.serious_mint": "Serious Mint",
"item.cobblemon.ability_shield": "Ability Shield",
"item.cobblemon.absorb_bulb": "Absorb Bulb",
"item.cobblemon.air_balloon": "Air Balloon",
"item.cobblemon.assault_vest": "Assault Vest",
"item.cobblemon.auspicious_armor": "Auspicious Armor",
"item.cobblemon.malicious_armor": "Malicious Armor",
"item.cobblemon.binding_band": "Binding Band",
"item.cobblemon.black_belt": "Black Belt",
"item.cobblemon.black_glasses": "Black Glasses",
"item.cobblemon.black_sludge": "Black Sludge",
"item.cobblemon.blunder_policy": "Blunder Policy",
"item.cobblemon.cell_battery": "Cell Battery",
"item.cobblemon.charcoal_stick": "Charcoal Stick",
"item.cobblemon.choice_band": "Choice Band",
"item.cobblemon.choice_scarf": "Choice Scarf",
"item.cobblemon.choice_specs": "Choice Specs",
"item.cobblemon.cleanse_tag": "Cleanse Tag",
"item.cobblemon.clear_amulet": "Clear Amulet",
"item.cobblemon.covert_cloak": "Covert Cloak",
"item.cobblemon.dragon_fang": "Dragon Fang",
"item.cobblemon.eject_button": "Eject Button",
"item.cobblemon.eject_pack": "Eject Pack",
"item.cobblemon.everstone": "Everstone",
"item.cobblemon.eviolite": "Eviolite",
"item.cobblemon.exp_share": "Exp. Share",
"item.cobblemon.expert_belt": "Expert Belt",
"item.cobblemon.fairy_feather": "Fairy Feather",
"item.cobblemon.float_stone": "Float Stone",
"item.cobblemon.focus_band": "Focus Band",
"item.cobblemon.focus_sash": "Focus Sash",
"item.cobblemon.grip_claw": "Grip Claw",
"item.cobblemon.hard_stone": "Hard Stone",
"item.cobblemon.heavy_duty_boots": "Heavy-Duty Boots",
"item.cobblemon.iron_ball": "Iron Ball",
"item.cobblemon.lagging_tail": "Lagging Tail",
"item.cobblemon.leftovers": "Leftovers",
"item.cobblemon.light_ball": "Light Ball",
"item.cobblemon.light_clay": "Light Clay",
"item.cobblemon.loaded_dice": "Loaded Dice",
"item.cobblemon.lucky_egg": "Lucky Egg",
"item.cobblemon.luminous_moss": "Luminous Moss",
"item.cobblemon.magnet": "Magnet",
"item.cobblemon.metronome": "Metronome",
"item.cobblemon.miracle_seed": "Miracle Seed",
"item.cobblemon.muscle_band": "Muscle Band",
"item.cobblemon.mystic_water": "Mystic Water",
"item.cobblemon.never_melt_ice": "Never-Melt Ice",
"item.cobblemon.poison_barb": "Poison Barb",
"item.cobblemon.protective_pads": "Protective Pads",
"item.cobblemon.punching_glove": "Punching Glove",
"item.cobblemon.quick_claw": "Quick Claw",
"item.cobblemon.razor_claw": "Razor Claw",
"item.cobblemon.razor_fang": "Razor Fang",
"item.cobblemon.red_card": "Red Card",
"item.cobblemon.ring_target": "Ring Target",
"item.cobblemon.rocky_helmet": "Rocky Helmet",
"item.cobblemon.room_service": "Room Service",
"item.cobblemon.safety_goggles": "Safety Goggles",
"item.cobblemon.scope_lens": "Scope Lens",
"item.cobblemon.sharp_beak": "Sharp Beak",
"item.cobblemon.shed_shell": "Shed Shell",
"item.cobblemon.shell_bell": "Shell Bell",
"item.cobblemon.silk_scarf": "Silk Scarf",
"item.cobblemon.silver_powder": "Silver Powder",
"item.cobblemon.soft_sand": "Soft Sand",
"item.cobblemon.spell_tag": "Spell Tag",
"item.cobblemon.sticky_barb": "Sticky Barb",
"item.cobblemon.terrain_extender": "Terrain Extender",
"item.cobblemon.throat_spray": "Throat Spray",
"item.cobblemon.twisted_spoon": "Twisted Spoon",
"item.cobblemon.utility_umbrella": "Utility Umbrella",
"item.cobblemon.weakness_policy": "Weakness Policy",
"item.cobblemon.wide_lens": "Wide Lens",
"item.cobblemon.wise_glasses": "Wise Glasses",
"item.cobblemon.zoom_lens": "Zoom Lens",
"item.cobblemon.mental_herb": "Mental Herb",
"item.cobblemon.mirror_herb": "Mirror Herb",
"item.cobblemon.power_herb": "Power Herb",
@@ -207,7 +244,6 @@
"item.cobblemon.metal_powder": "Metal Powder",
"item.cobblemon.quick_powder": "Quick Powder",
"item.cobblemon.destiny_knot": "Destiny Knot",
"item.cobblemon.everstone": "Everstone",
"item.cobblemon.power_anklet": "Power Anklet",
"item.cobblemon.power_band": "Power Band",
"item.cobblemon.power_belt": "Power Belt",
@@ -219,6 +255,10 @@
"item.cobblemon.smoke_ball": "Smoke Ball",
"item.cobblemon.toxic_orb": "Toxic Orb",
"item.cobblemon.life_orb": "Life Orb",
"item.cobblemon.damp_rock": "Damp Rock",
"item.cobblemon.heat_rock": "Heat Rock",
"item.cobblemon.smooth_rock": "Smooth Rock",
"item.cobblemon.icy_rock": "Icy Rock",
"item.cobblemon.poke_ball.tooltip": "1× catch rate",
"item.cobblemon.slate_ball.tooltip": "1× catch rate",
@@ -1251,6 +1291,8 @@
"cobblemon.battle.enditem.whiteherb": "%1$s returned its status to normal using its White Herb!",
"cobblemon.battle.enditem.corrosivegas": "%3$s corroded %1$s's %2$s!",
"cobblemon.battle.enditem.stealeat": "%3$s stole and ate its target's %2$s!",
"cobblemon.battle.enditem.cellbattery": "%1$s used its Cell Battery!",
"cobblemon.battle.enditem.ejectbutton": "%1$s is switched out with the Eject Button!",
"cobblemon.battle.heal.zeffect": "%1$s's HP was restored by the Z-Power!",
"cobblemon.battle.heal.wish": "%1$s's wish came true!",
@@ -1459,6 +1501,34 @@
"tag.item.cobblemon.sun_stone_ores": "Sun Stone Ores",
"tag.item.cobblemon.thunder_stone_ores": "Thunder Stone Ores",
"tag.item.cobblemon.water_stone_ores": "Water Stone Ores",
"tag.item.cobblemon.apples": "Apples",
"tag.item.cobblemon.apricorn_poke_balls": "Apricorn Poké Balls",
"tag.item.cobblemon.ancient_poke_balls": "Ancient Poké Balls",
"tag.item.cobblemon.black_tumblestones": "Black Tumblestones",
"tag.item.cobblemon.copper_poke_balls": "Copper Tier Poké Balls",
"tag.item.cobblemon.diamond_poke_balls": "Diamond Tier Poké Balls",
"tag.item.cobblemon.deep_seas": "Deep Sea Items",
"tag.item.cobblemon.ethers": "Ethers and Elixirs",
"tag.item.cobblemon.fossil_machine_parts": "Fossil Machine Parts",
"tag.item.cobblemon.gold_poke_balls": "Gold Tier Poké Balls",
"tag.item.cobblemon.iron_poke_balls": "Iron Tier Poké Balls",
"tag.item.cobblemon.machines": "Machines",
"tag.item.cobblemon.nether_star_poke_balls": "Nether Star Tier Poké Balls",
"tag.item.cobblemon.potions": "Potions",
"tag.item.cobblemon.red_tumblestones": "Tumblestones",
"tag.item.cobblemon.remedies": "Remedies",
"tag.item.cobblemon.restores": "Restores",
"tag.item.cobblemon.revives": "Revives",
"tag.item.cobblemon.sky_tumblestones": "Sky Tumblestones",
"tag.item.cobblemon.sweets": "Sweets",
"tag.item.cobblemon.teapots": "Teapots",
"tag.item.cobblemon.vitamins": "Vitamins",
"tag.item.cobblemon.x_items": "X Battle Items",
"tag.item.cobblemon.raw_meat": "Raw Meat",
"tag.item.cobblemon.cooked_meat": "Cooked Meat",
"tag.item.cobblemon.fossils": "Fossils",
"tag.item.cobblemon.mint_seeds": "Mint Seeds",
"tag.item.cobblemon.tumblestones": "Tumblestones",
"cobblemon.move.10000000voltthunderbolt": "10,000,000 Volt Thunderbolt",
"cobblemon.move.10000000voltthunderbolt.desc": "The user, Pikachu wearing a cap, powers up a jolt of electricity using its Z-Power and unleashes it. Critical hits land more easily.",
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/ability_shield"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/absorb_bulb"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/air_balloon"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/binding_band"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/blunder_policy"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/cell_battery"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/clear_amulet"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/covert_cloak"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/damp_rock"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/eject_button"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/eject_pack"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/eviolite"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/expert_belt"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/float_stone"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/focus_sash"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/grip_claw"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/heat_rock"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/icy_rock"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/iron_ball"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/lagging_tail"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/light_ball"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/loaded_dice"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/luminous_moss"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/metronome"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/protective_pads"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/punching_glove"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/red_card"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/ring_target"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/room_service"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/scope_lens"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/shed_shell"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/shell_bell"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/smooth_rock"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/sticky_barb"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/terrain_extender"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/throat_spray"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/utility_umbrella"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/weakness_policy"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/wide_lens"
}
}
@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "cobblemon:item/held_items/zoom_lens"
}
}
@@ -1,3 +1,3 @@
{
"showdownVersion": "11"
"showdownVersion": "12"
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_copper": {
"conditions": {
"items": [
{
"items": [
"minecraft:copper_ingot"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:cell_battery"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_copper",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:cell_battery"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_stone": {
"conditions": {
"items": [
{
"items": [
"cobblemon:water_stone"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:damp_rock"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_stone",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:damp_rock"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_button": {
"conditions": {
"items": [
{
"items": [
"cobblemon:eject_button"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:eject_pack"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_button",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:eject_pack"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_everstone": {
"conditions": {
"items": [
{
"items": [
"cobblemon:everstone"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:eviolite"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_everstone",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:eviolite"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_stone": {
"conditions": {
"items": [
{
"items": [
"cobblemon:water_stone"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:heat_rock"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_stone",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:heat_rock"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_stone": {
"conditions": {
"items": [
{
"items": [
"cobblemon:ice_stone"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:icy_rock"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_stone",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:icy_rock"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_iron": {
"conditions": {
"items": [
{
"items": [
"minecraft:iron_block"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:iron_ball"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_iron",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:iron_ball"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_ball": {
"conditions": {
"items": [
{
"items": [
"cobblemon:iron_ball"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:loaded_dice"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_ball",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:loaded_dice"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_note": {
"conditions": {
"items": [
{
"items": [
"minecraft:note_block"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:metronome"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_note",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:metronome"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_target": {
"conditions": {
"items": [
{
"items": [
"minecraft:target"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:ring_target"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_target",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:ring_target"
]
}
}
@@ -0,0 +1,34 @@
{
"parent": "cobblemon:recipes/root",
"criteria": {
"has_bucket": {
"conditions": {
"items": [
{
"items": [
"minecraft:bucket"
]
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "cobblemon:terrain_extender"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_bucket",
"has_the_recipe"
]
],
"rewards": {
"recipes": [
"cobblemon:terrain_extender"
]
}
}
@@ -0,0 +1,25 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"IDI",
"DSD",
" A "
],
"key": {
"I": {
"item": "minecraft:iron_ingot"
},
"D": {
"item": "minecraft:diamond"
},
"S": {
"item": "minecraft:shield"
},
"A": {
"item": "minecraft:amethyst_shard"
}
},
"result": {
"item": "cobblemon:ability_shield"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" WW",
" PW",
"S "
],
"key": {
"W": {
"item": "minecraft:red_wool"
},
"P": {
"item": "minecraft:phantom_membrane"
},
"S": {
"item": "minecraft:string"
}
},
"result": {
"item": "cobblemon:air_balloon"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" SW",
"SsS",
"WS "
],
"key": {
"S": {
"item": "minecraft:string"
},
"s": {
"item": "minecraft:slime_ball"
},
"W": {
"item": "minecraft:brown_wool"
}
},
"result": {
"item": "cobblemon:binding_band"
}
}
@@ -0,0 +1,28 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" R ",
"DIF",
" P "
],
"key": {
"R": {
"item": "minecraft:rabbit_foot"
},
"D": {
"item": "minecraft:yellow_dye"
},
"I": {
"item": "minecraft:ink_sac"
},
"F": {
"item": "minecraft:feather"
},
"P": {
"item": "minecraft:paper"
}
},
"result": {
"item": "cobblemon:blunder_policy"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"I",
"R",
"C"
],
"key": {
"C": {
"item": "minecraft:copper_ingot"
},
"R": {
"item": "minecraft:redstone"
},
"I": {
"item": "minecraft:iron_ingot"
}
},
"result": {
"item": "cobblemon:cell_battery"
}
}
@@ -0,0 +1,25 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"SDS",
"GAG",
" D "
],
"key": {
"D": {
"item": "minecraft:diamond"
},
"S": {
"item": "minecraft:string"
},
"G": {
"item": "minecraft:gold_ingot"
},
"A": {
"item": "minecraft:amethyst_shard"
}
},
"result": {
"item": "cobblemon:clear_amulet"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" W ",
"WPW",
"WGW"
],
"key": {
"G": {
"item": "minecraft:golden_carrot"
},
"W": {
"item": "minecraft:gray_wool"
},
"P": {
"item": "minecraft:phantom_membrane"
}
},
"result": {
"item": "cobblemon:covert_cloak"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"DS",
"HD"
],
"key": {
"D": {
"item": "minecraft:dripstone_block"
},
"S": {
"item": "cobblemon:water_stone"
},
"H": {
"item": "cobblemon:hard_stone"
}
},
"result":
{
"item": "cobblemon:damp_rock"
}
}
@@ -0,0 +1,28 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"IBI",
"YPY",
"IRI"
],
"key": {
"Y": {
"item": "minecraft:yellow_dye"
},
"I": {
"item": "minecraft:iron_ingot"
},
"B": {
"tag": "minecraft:buttons"
},
"R": {
"item": "minecraft:redstone"
},
"P": {
"item": "minecraft:piston"
}
},
"result": {
"item": "cobblemon:eject_button"
}
}
@@ -0,0 +1,25 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"WWW",
"WEW",
"LRL"
],
"key": {
"W": {
"item": "minecraft:white_wool"
},
"E": {
"item": "cobblemon:eject_button"
},
"R": {
"item": "minecraft:redstone"
},
"L": {
"item": "minecraft:leather"
}
},
"result": {
"item": "cobblemon:eject_pack"
}
}
@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" A ",
"AEA",
" A "
],
"key": {
"A": {
"item": "minecraft:amethyst_shard"
},
"E": {
"item": "cobblemon:everstone"
}
},
"result": {
"item": "cobblemon:eviolite"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"P ",
"WBW",
" P"
],
"key": {
"P": {
"item": "minecraft:blaze_powder"
},
"W": {
"item": "minecraft:black_wool"
},
"B": {
"item": "cobblemon:black_belt"
}
},
"result": {
"item": "cobblemon:expert_belt"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"D ",
"WIW",
" D"
],
"key": {
"W": {
"item": "minecraft:red_wool"
},
"D": {
"item": "minecraft:blaze_powder"
},
"I": {
"item": "minecraft:copper_ingot"
}
},
"result": {
"item": "cobblemon:focus_sash"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"DS",
"HD"
],
"key": {
"D": {
"item": "minecraft:dripstone_block"
},
"S": {
"item": "cobblemon:fire_stone"
},
"H": {
"item": "cobblemon:hard_stone"
}
},
"result":
{
"item": "cobblemon:heat_rock"
}
}
@@ -0,0 +1,22 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"DS",
"HD"
],
"key": {
"D": {
"item": "minecraft:dripstone_block"
},
"S": {
"item": "cobblemon:ice_stone"
},
"H": {
"item": "cobblemon:hard_stone"
}
},
"result":
{
"item": "cobblemon:icy_rock"
}
}
@@ -0,0 +1,8 @@
{
"type": "minecraft:stonecutting",
"count": 1,
"ingredient": {
"item": "minecraft:iron_block"
},
"result": "cobblemon:iron_ball"
}
@@ -0,0 +1,25 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"SOS",
"OCO",
"IOI"
],
"key": {
"S": {
"item": "minecraft:slime_ball"
},
"O": {
"item": "minecraft:obsidian"
},
"C": {
"item": "cobblemon:clover_sweet"
},
"I": {
"item": "cobblemon:iron_ball"
}
},
"result": {
"item": "cobblemon:loaded_dice"
}
}
@@ -0,0 +1,21 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"MG",
"BM"
],
"key": {
"M": {
"item": "minecraft:moss_block"
},
"G": {
"item": "minecraft:glow_berries"
},
"B": {
"item": "minecraft:bowl"
}
},
"result": {
"item": "cobblemon:luminous_moss"
}
}

Some files were not shown because too many files have changed in this diff Show More