Compare commits

..
Author SHA1 Message Date
Instrafe 376a420474 Updated Changelog 2026-01-11 10:30:53 -05:00
Instrafe a8e2db25f8 Fixed Scraggy and Scrafty's spawns not having the natural preset 2026-01-11 10:27:47 -05:00
Hiroku 2bb85718d7 Merge branch 'main' into 'main'
Fix Adorn compatibility

See merge request cable-mc/cobblemon!2112
2026-01-11 12:21:25 +00:00
Tate Frost ee187d7b89 Delete file + update Adorn resource pack metadata
- Delete config file that was committed in error
- Update Adorn resource pack metadata to reflect new wood type
2026-01-10 22:30:27 -06:00
Tate Frost 3532cac278 Update CHANGELOG.md 2026-01-10 22:18:01 -06:00
Hiroku 1447ab25b4 Merge branch 'CombeeWorldGenFix' into 'main'
CombeeWorldGenFix

See merge request cable-mc/cobblemon!2071
2026-01-11 02:55:56 +00:00
Hiroku 9a06ca78c6 Merge branch 'fix-mongo-driver' into 'main'
Fix MongoDB ClassNotFoundException by including drivers at runtime

See merge request cable-mc/cobblemon!2098
2026-01-11 02:47:10 +00:00
Hiroku f6ba70634b Merge branch 'double-battle-gimmicks' into 'main'
Fix double battle gimmicks not being processed

See merge request cable-mc/cobblemon!2094
2026-01-11 02:46:36 +00:00
Hiroku 148fd04a93 Merge branch 'molang-evaluate_expression' into 'main'
molang addition: exception handling for run_molang

See merge request cable-mc/cobblemon!2102
2026-01-11 02:12:07 +00:00
Hiroku 17f60623ee Merge branch 'effect-id-regex-update' into 'main'
Custom messages for datapack moves and abilities

See merge request cable-mc/cobblemon!2106
2026-01-11 02:08:42 +00:00
Hiroku c5ece27c11 Merge branch '1861-galarien_mrmime_mount' into 'main'
Fix Galarian Mr. Mime incorrectly being rideable.

Closes #1861

See merge request cable-mc/cobblemon!2107
2026-01-11 02:02:14 +00:00
Hiroku 296ccd1a76 Merge branch 'main' into 'main'
Fix pasture block incorrect hit-box when facing north and south.

See merge request cable-mc/cobblemon!2109
2026-01-11 02:01:44 +00:00
Tate Frost 08b58e2f78 Fix Adorn compatibility
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn
- Added Saccharine wood + Adorn compatibility
2026-01-07 02:04:52 -06:00
Merv 62d2b8db2d Edit CHANGELOG.md 2026-01-06 18:47:45 +00:00
Merv 3869f7ed93 Merge branch cobblemon:main into main 2026-01-05 23:09:08 +00:00
Dragonwhisper92 c9c44872d6 Updated Changelog. 2026-01-05 19:35:05 +00:00
Dragonwhisper92 cae53efedc Updated ActivateInstruction.kt to have an optional message parameter. 2026-01-05 19:14:40 +00:00
Polymeta 5fac24cee8 Merge branch 'Molang-SimpleDateFormat-Fix' into 'main'
Fixed Molang functions:

See merge request cable-mc/cobblemon!2105
2026-01-05 11:22:45 +00:00
Polymeta 1954dfec80 Merge branch '1784-riding_stats_order' into 'main'
Fix riding stat boosts to always render in the same order

Closes #1784

See merge request cable-mc/cobblemon!2108
2026-01-05 11:20:29 +00:00
Landon 2eea2b64c2 Merge branch 'bag-clause' into 'main'
Bag Clause (Preventing Item use in Battles)

See merge request cable-mc/cobblemon!1849
2026-01-05 08:12:36 +00:00
GDWR a127a93be8 Sort boosts when rendering to remove the jumping of stats between items
The sort uses the key. As `RidingStat` it sorts them by the enum value.
2026-01-04 20:27:42 +00:00
GDWR 9b32f85817 Set an empty riding definition for Galarian Mr. Mime to avoid inheriting the default definition 2026-01-04 17:28:02 +00:00
Dragonwhisper92 ec139d2677 Updated Effect.kt to use a custom REGEX entry 2026-01-04 16:46:44 +00:00
Landon Wills 4327be0cf9 Omit bag clause from getting sent to showdown 2026-01-04 02:22:32 -05:00
Landon Wills c25c832b31 Remove import 2026-01-04 01:21:20 -05:00
Landon Wills eabaabc535 Move bag clause check to bag items instead of pokemon entity 2026-01-04 01:19:26 -05:00
Dragonwhisper92 9acf97f5a0 Updated CHANGELOG.md 2026-01-04 00:18:24 +00:00
Dragonwhisper92 24fc212c76 Updated CHANGELOG.md 2026-01-04 00:15:32 +00:00
Hiroku 04f88bdd63 Merge branch 'form-change-move-sanitization-fix' into 'main'
Fix the improper sanitization of moves on mons with compounding properties

Closes #1853 and #1846

See merge request cable-mc/cobblemon!2085
2026-01-04 00:05:26 +00:00
Dragonwhisper92 a4eb58aa57 Fixed molang functions:
- date_local_time
- date_of
- date_is_after
too use the correct SimpleDateFormat of "dd/MM/yyyy"
2026-01-03 23:40:12 +00:00
Merv 6704d4e5ee Maybe fix pasture block incorrect hitbox 2026-01-03 02:05:03 +00:00
Hiroku c88087de29 Merge branch 'main' into 'main'
Small improvements to the Battle AI

See merge request cable-mc/cobblemon!2101
2026-01-02 00:38:26 +00:00
Konoha 86bb802140 adjustment: exception handling to run_molang 2026-01-01 11:44:29 -05:00
GGavino1 6b644b384d Updated CHANGELOG.md to include AI changes 2026-01-01 15:00:15 +00:00
Konoha c370af8914 feature: molang function for safe evaluation of booleans 2025-12-31 22:23:50 -05:00
GGavino1 1cd6d2bfc7 Edit StrongBattleAI.kt 2025-12-31 23:15:52 +00:00
Konoha 1edeae2a60 fix: let's actually fix 2025-12-27 09:48:49 -05:00
mkh 409f1056b9 fix: Add MongoDB driver dependency to Fabric/NeoForge build configuration and shade it into the mod jar to resolve ClassNotFoundException. 2025-12-26 17:31:46 +08:00
Landon Wills d8c470db3d Oops, forgot a file 2025-12-23 01:28:50 -05:00
Landon Wills c642c4b84b Update changelog 2025-12-23 01:22:01 -05:00
Landon Wills 0b80f7e547 Make the gimmick buttons work with the back button 2025-12-23 01:18:35 -05:00
Landon Wills d543f45607 Fix double battle gimmicks not being processed, prevent people from trying to use the same gimmick multiple times on the same turn 2025-12-23 00:43:31 -05:00
Konoha 2b4fdfd219 changelog: sanitization fix 2025-12-21 15:40:17 -05:00
Hiroku 1a3b655d3f Merge branch 'the-tiniest-of-tiny-changes' into 'main'
Edit pokemon_model.json

See merge request cable-mc/cobblemon!2091
2025-12-20 12:41:36 +00:00
dhi_holo 1f5f278970 Edit pokemon_model.json 2025-12-20 21:25:12 +10:00
Hiroku 0b4eb5239a Merge branch 'in-flight-dismounting-config' into 'main'
Add enable in-flight dismounting config

See merge request cable-mc/cobblemon!2079
2025-12-20 06:01:12 +00:00
lion 118e8f6205 Add enable in-flight dismounting config 2025-12-20 06:01:12 +00:00
Hiroku cf126c5906 Merge branch 'molang-is-love-molang-is-life' into 'main'
Fixed the `run_script` Molang function to not fail if the environment's context is null.

See merge request cable-mc/cobblemon!2090
2025-12-20 01:59:22 +00:00
Spicy 645cf61911 Fixed the run_script Molang function to not fail if the environment's context is null. 2025-12-19 19:48:27 -06:00
Hiroku 87d5ede3dd Merge branch 'RestoreCombeeLeavesPathing' into 'main'
RestoreCombeeLeavesPathing

See merge request cable-mc/cobblemon!2046
2025-12-19 07:36:50 +00:00
Hiroku 203e5d89cd Merge branch 'label-consistency' into 'main'
Who are we if not consistent?

See merge request cable-mc/cobblemon!1985
2025-12-19 07:36:21 +00:00
Konoha ce611cc61c cleanup: fix redundancies in form change sanitization 2025-12-18 21:17:48 -05:00
JazzMcNade f6ad7ff865 Fix changelog 2025-12-17 21:08:46 -06:00
JazzMcNade d69627a9c8 Merge branch 'main' into CombeeWorldGenFix 2025-12-17 20:05:09 -06:00
JazzMcNade 54e8763470 Fixed a bug in which Combees could become stuck inside of leaves 2025-12-13 21:17:59 -06:00
JazzMcNade db34687df0 Merge branch 'main' into RestoreCombeeLeavesPathing 2025-12-13 21:11:57 -06:00
Konoha 7f008d85ff fix: form_change move updates no longer sanitize the sets of compounding property mons 2025-12-13 18:37:37 -05:00
Polymeta 06ebf51078 Merge branch 'Wii-Break-It-Wii-Fix-It' into 'main'
Boat Tags and Mint Leaves

Closes #1855

See merge request cable-mc/cobblemon!2082
2025-12-13 22:14:32 +00:00
Polymeta 39c5bcd73c Merge branch 'even-more-seasonings' into 'main'
Adding Missing Effects for Seasonings

See merge request cable-mc/cobblemon!1991
2025-12-13 22:13:24 +00:00
Ceejay 8f5f158b60 Adding Missing Effects for Seasonings 2025-12-13 22:13:24 +00:00
dhi_holo 3bc1e35125 Update CHANGELOG.md 2025-12-13 18:42:50 +10:00
dhi_holo 460bedddae Boat Tags
Resolves #1855
2025-12-13 18:12:24 +10:00
dhi_holo 8b64c315f3 Merge branch 'main' into Wii-Break-It-Wii-Fix-It 2025-12-13 17:51:15 +10:00
dhi_holo 7c824a2b72 OVERSIGHTS 2025-12-13 17:50:57 +10:00
Paul f197ac5077 Removed a bunch of duplicates from is_held_item because it looks whack. 2025-12-12 16:24:30 +10:00
Hiroku e0be669482 Merge branch 'patch-1' into 'main'
Fix Soothe Bell not tagged as `cobblemon:held/is_held_item`

See merge request cable-mc/cobblemon!2081
2025-12-12 06:17:17 +00:00
Micky 08ea21fff4 Fix Soothe Bell not tagged as cobblemon:held/is_held_item 2025-12-10 13:27:23 +00:00
JazzMcNade 9dac604a93 Merge branch 'main' into RestoreCombeeLeavesPathing 2025-12-10 00:20:49 -06:00
Polymeta 28c0f8ab7d Merge branch 'item-interactions-sync' into 'main'
Item interactions sync

See merge request cable-mc/cobblemon!2068
2025-12-08 16:08:48 +00:00
lion fcbe0db568 Item interactions sync 2025-12-08 16:08:48 +00:00
Polymeta 83cefe476e Merge branch 'partner-mark' into 'main'
Add Partner Mark

See merge request cable-mc/cobblemon!2034
2025-12-08 15:57:21 +00:00
Guilherme Pereira 690ccbd260 refactor check riding statistics method for server player mixin 2025-12-08 12:06:20 -03:00
Polymeta 63846d53fb Merge branch 'main' into 'main'
Fixed shiny Pokémon not respecting the silent flag on spawn.

See merge request cable-mc/cobblemon!2064
2025-12-08 13:07:25 +00:00
Polymeta 86cb865742 fixed mochi items being consumed twice
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-12-08 13:01:14 +00:00
Polymeta 1a0c9b6a82 Merge branch 'malformed-jsons-no-more' into 'main'
Fixes a crash caused by malformed riding prespectives json file when trying to ride a pokemon

See merge request cable-mc/cobblemon!2077
2025-12-08 12:59:22 +00:00
Polymeta 985eb103fe Merge branch 'sterr/ride-sound-changes' into 'main'
New ride sound stuff

See merge request cable-mc/cobblemon!2065
2025-12-08 11:44:22 +00:00
Polymeta aec76a78da Merge branch 'restore_adorn_texturing' into 'main'
Restore adorn texturing

Closes #1833

See merge request cable-mc/cobblemon!2078
2025-12-08 11:36:41 +00:00
Jacob Hartmann 17f3edf2be Changelog 2025-12-07 20:35:11 -07:00
Jacob Hartmann 9c5bfda20f Updating texture paths 2025-12-07 20:34:09 -07:00
Gertimoshka 6d545fc1ca Fixes a crash caused by malformed riding prespectives json file when trying to ride a pokemon 2025-12-07 11:47:04 +02:00
Polymeta 9a8ad27122 Merge branch 'fix-spectator-crash' into 'main'
fix spectator crash

Closes #1847

See merge request cable-mc/cobblemon!2076
2025-12-07 08:39:18 +00:00
500-internal-server-error 9f1dbc9ff0 add notes to changelog 2025-12-07 07:58:55 +07:00
Polymeta 99942748b0 Merge branch 'entropydragon--spawn-bait-regional-forms' into 'main'
fix: use regional form data for spawn bait influence

See merge request cable-mc/cobblemon!2074
2025-12-07 00:49:48 +00:00
jasoncramer 64c34230bf chore: add to changelog 2025-12-06 19:28:41 -05:00
500-internal-server-error 36881b70be fix spectator crash 2025-12-06 20:51:48 +07:00
jasoncramer 9b052478f6 fix: use regional form data for spawn bait influence 2025-12-05 14:23:05 -05:00
Hiroku 339f8339f0 Merge branch 'RestorePokemonItemPickup' into 'main'
Restore Pokemon item pickup

See merge request cable-mc/cobblemon!2073
2025-12-05 08:19:41 +00:00
Hiroku db9a802c3f Merge branch 'fix-spawner-crash' into 'main'
Prevents outside spawn influences from crashing the logical server.

See merge request cable-mc/cobblemon!2072
2025-12-05 07:45:29 +00:00
JazzMcNade e5666e7a82 Restore Pokemon item pickup. Remove unnecessary check in shouldBeSaved() 2025-12-05 01:30:20 -06:00
Neovitalism a588213323 Update CHANGELOG.md 2025-12-04 03:05:03 -06:00
Neovitalism 56b2ba08ad Prevents outside influences from crashing the logical server.
Before when it was completed exceptionally w/ the pokesnack spawner, it would crash the server.
2025-12-04 03:03:57 -06:00
JazzMcNade 8540a73885 Fix for error occurring while populating bee nests with pokemon on world gen 2025-12-04 01:38:56 -06:00
Khvrram 7e6ca7be5e Merge branch cobblemon:main into main 2025-12-04 01:59:17 +00:00
Neovitalism 25ce784a60 Hopefully fixes changelog
Idk why gitlab didn't detect that when merging main
2025-12-03 10:17:48 -06:00
Neovitalism 5358cccb62 Merge branch 'main' into label-consistency 2025-12-03 10:09:41 -06:00
Polymeta c43b3bbb4d Merge branch 'fix-can-drop-held-item' into 'main'
Fix can drop held item function

See merge request cable-mc/cobblemon!2069
2025-12-03 08:17:38 +00:00
lion d826aeeb07 Fix can drop held item function 2025-12-03 08:17:35 +00:00
Polymeta f90c6967ce Merge branch 'FixHoneyedLeavesInteraction' into 'main'
FixHoneyedLeavesInteraction

Closes #1832

See merge request cable-mc/cobblemon!2067
2025-12-03 08:15:26 +00:00
JazzMcNade b9cf18adbd Changelog 2025-12-02 20:16:56 -06:00
JazzMcNade 30650e1f9f Code simplication 2025-12-02 20:12:37 -06:00
JazzMcNade eaa558a7c8 Check for creative on using empty bottle 2025-12-02 00:36:53 -06:00
JazzMcNade 0dc725e513 Can only receive honey at max age. Adds result to hand if possible. Checks for creative and server/client 2025-12-02 00:28:23 -06:00
Sterrezo a575c6bc3d Update CHANGELOG.md 2025-12-01 15:47:34 +01:00
Sterrezo 9c102a7850 Merge branch 'main' into sterr/ride-sound-changes 2025-12-01 15:45:40 +01:00
Sterrezo 22a1eaab19 Volume balancing 2025-12-01 15:35:22 +01:00
Sterrezo 0118ace5fc Implemented stereo flight loops 2025-12-01 15:09:37 +01:00
Sterrezo d4a93abbf7 Added support for submerged ride sounds 2025-12-01 14:27:55 +01:00
Sterrezo d0ee3f3e9d Added an option for ride sounds to not play for the passengers 2025-12-01 13:56:56 +01:00
JazzMcNade 698fa9dff9 Merge branch 'main' into RestoreCombeeLeavesPathing 2025-12-01 00:46:50 -06:00
Khvrram 46ae53f565 Merge branch cobblemon:main into main 2025-12-01 04:25:52 +00:00
Hiroku 7d4e5892ba Merge branch 'main' into 'main'
Orientation after crash fix

See merge request cable-mc/cobblemon!2061
2025-12-01 00:23:40 +00:00
Khvrram f9de415020 Orientation after crash fix 2025-12-01 00:23:39 +00:00
Khurram Valiyev 4d123b6e4b Fixed shiny Pokémon not respecting the silent flag on spawn. 2025-11-29 22:50:52 -05:00
Polymeta 54dc2e7f6f tidy up changelog [skip-ci] 2025-11-29 12:57:24 +00:00
Polymeta 1d60ba093f Merge branch 'convention-tags-not-being-consistent-grrrrrrrr' into 'main'
Why

See merge request cable-mc/cobblemon!2060
2025-11-29 11:53:50 +00:00
Hiroku 0fef74dce7 Edit OneToOneFileStoreAdapter.kt 2025-11-29 09:46:27 +00:00
Hiroku b08647bb32 Revert "Merge branch 'main' into 'main'"
This reverts merge request !2062
2025-11-29 04:26:57 +00:00
Hiroku de9e89f040 Merge branch 'main' into 'main'
Editar en_us.json

See merge request cable-mc/cobblemon!2062
2025-11-29 04:25:10 +00:00
Ezequiel Neri Ferreira 84a29ebc2a Editar en_us.json 2025-11-29 04:22:49 +00:00
Paul 37b13ae959 Unsnaps your shot 2025-11-29 12:44:40 +10:00
dhi_holo 1cacbe8306 Why
It's called Shears, that's the item name, why does NeoForge use a Shear tag instead
Atleast Fabric has that tag as well so it's not a hard fix
2025-11-29 12:30:45 +10:00
Paul 12d224d15a Reinforce switchForm for crashes 2025-11-29 11:25:58 +10:00
Paul a57eee3afc Changelog updates [skip-ci] 2025-11-29 10:46:19 +10:00
Hiroku 57595c999c Merge branch 'remove-snapshot' into 'main'
Remove snapshot for release

See merge request cable-mc/cobblemon!2059
2025-11-28 23:24:59 +00:00
Landon Wills 83615b7eb3 Prepare release 2025-11-28 17:54:24 -05:00
Polymeta c53c544a8b Merge branch 'implement_pokemon' into 'main'
Last minute changes

See merge request cable-mc/cobblemon!2058
2025-11-28 22:23:03 +00:00
Kenji_64 c7c272c79c Had to fix Dragapult (again) 2025-11-28 21:04:50 +01:00
Kenji_64 c759161367 Added cries to Eelektrik and Eelektross 2025-11-28 21:01:27 +01:00
Landon 19b7b4804f Merge branch 'add-defend-owner-task' into 'main'
Make Pokémon only attack mobs targeting the player

See merge request cable-mc/cobblemon!2051
2025-11-28 18:30:05 +00:00
Landon 3a005cc813 Merge branch '1.7.1-spawns' into 'main'
Updated Dratini line spawns.

See merge request cable-mc/cobblemon!2055
2025-11-28 18:28:24 +00:00
Landon a8e16efa48 Merge branch 'jet-handling' into 'main'
Increase pitch rotation of Jet

See merge request cable-mc/cobblemon!2054
2025-11-28 18:08:20 +00:00
Veraxiel c3ddfce0a7 Updated Dratini spawn. 2025-11-28 12:38:53 -05:00
Landon Wills 9500f7a1f3 adjust wording 2025-11-28 12:21:44 -05:00
Landon Wills 83a8d92e3f Add changelog 2025-11-28 12:21:08 -05:00
Landon Wills e105c5d4d7 Remove multipliers, adjust expression 2025-11-28 12:17:42 -05:00
Landon Wills 3d816f57e2 Increase pitch rotation of Jet 2025-11-28 12:13:55 -05:00
Landon 1e6dcfba9b Merge branch 'change-freelook-default' into 'main'
Change free look binding default to Left Alt

See merge request cable-mc/cobblemon!2053
2025-11-28 16:30:35 +00:00
Polymeta e59d755d32 Merge branch 'implement_pokemon' into 'main'
Various implementation fixes

See merge request cable-mc/cobblemon!2050
2025-11-28 15:38:40 +00:00
Guilherme Pereira c155b5575d change free look binding default to left alt 2025-11-28 09:35:13 -03:00
Jerzykv 9c6b8b231a oops 2 2025-11-28 13:30:16 +01:00
Jerzykv 92b404dac4 oops 2025-11-28 13:27:19 +01:00
Jerzykv 8a1c536d68 Fixed Furfrou's pink and magenta trims being swapped 2025-11-28 12:56:07 +01:00
Jerzykv 04719d22a5 Fixed a tiny issue with Ceruledge's poser 2025-11-28 12:55:54 +01:00
Jerzykv dacc312756 Implemented Tinkatink line remodels 2025-11-28 12:55:26 +01:00
Polymeta ee4a3d46ba Merge branch '1.7.1-spawns' into 'main'
Updated some spawns.

See merge request cable-mc/cobblemon!2052
2025-11-28 09:31:16 +00:00
violet 80b11f1c3d Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-28 01:20:00 -05:00
Carmendar ddcf4eea7b Heracross and Mudsdale jump fix. 2025-11-28 00:16:50 -06:00
violet 6a0681e4c6 fixed cyclizar's textures 2025-11-27 23:37:39 -05:00
Veraxiel 8ebb378da7 Updated some spawns. 2025-11-27 23:31:32 -05:00
violet e92a878074 fixed boltund's model 2025-11-27 23:30:22 -05:00
Paul 0b97b41c08 Merge remote-tracking branch 'origin/main' 2025-11-28 12:27:10 +10:00
Paul 20fe732cfc Potentially minor perf improvement on following walk targets that are unreachable 2025-11-28 12:26:26 +10:00
Carmendar 0575aa29d9 Doubled high end land mount stamina. 2025-11-27 18:43:20 -06:00
Guilherme Pereira 29b560d244 Merge branch 'main' of gitlab.com:cable-mc/cobblemon into partner-mark 2025-11-27 18:21:19 -03:00
Guilherme Pereira dcc98b4a54 rename mob to living entity 2025-11-27 18:19:49 -03:00
Guilherme Pereira d3ce455391 prevents defend owner task from targeting players 2025-11-27 18:10:59 -03:00
Kenji_64 85c6b633d8 Fixed Dragapult's eyes clippings 2025-11-27 22:03:48 +01:00
Guilherme Pereira 956b599060 update CHANGELOG.md 2025-11-27 17:51:11 -03:00
Jerzykv f88552f99b Gholdengo no longer dances in air. what a shame (fixed flying battle pose issue) 2025-11-27 21:46:35 +01:00
Carmendar e2b559f3eb Merge branch 'main' into implement_pokemon 2025-11-27 14:42:31 -06:00
Carmendar 39816d33b6 Rufflet eepy cry and battle pose fix 2025-11-27 14:38:39 -06:00
Landon 0cf2a23fd4 Merge branch 'cobble-land-fixes' into 'main'
Land adjustments for a smoother riding experience. And bug fixes to land rides

See merge request cable-mc/cobblemon!2039
2025-11-27 19:31:24 +00:00
Guilherme Pereira c4d8eae47e add defend owner task once again 2025-11-27 12:16:54 -03:00
Polymeta 2a5a292386 fix saccharine hanging signs sometimes dropping oak wood signs
Signed-off-by: Polymeta <40173118+Polymeta@users.noreply.github.com>
2025-11-27 11:27:58 +00:00
Polymeta e8a09f5c48 Merge branch 'json-fixing' into 'main'
JSON Fixes

Closes #1819

See merge request cable-mc/cobblemon!2048
2025-11-27 10:42:07 +00:00
dhi_holo e82193cdfd Update interact_with_pokemon.json
Removed accidental flag
2025-11-27 19:56:33 +10:00
dhi_holo 87e7cdebf6 Fabric Tags that aren't true c tags are the bane of my existence
Fixed the concrete tags to behave properly, changelog
2025-11-27 15:25:53 +10:00
dhi_holo 9ca84d852f Update interact_with_pokemon.json
Should close #1819
2025-11-27 14:22:06 +10:00
Carmendar 8194f93d13 Merge branch 'main' into implement_pokemon 2025-11-26 20:54:41 -06:00
Carmendar c158ec33fa Braviary sleep cry fix 2025-11-26 20:53:46 -06:00
Carmendar 1e27c7494e Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2025-11-26 20:52:27 -06:00
Carmendar 54a1f8d932 Braviary battle pose fix 2025-11-26 20:51:45 -06:00
Kenji_64 d2af0c9332 Fixed Swampert line's missing recoils crashing the game 2025-11-26 15:40:40 +01:00
Kenji_64 379a566d71 Fixed Ditto being silent 2025-11-26 11:52:43 +01:00
Kenji_64 f30ff739ed Fixed Metagross' ground_idle not looping properly (again) >:( 2025-11-26 11:36:23 +01:00
JazzMcNade a8949cf1f9 changelog 2025-11-25 21:49:38 -06:00
JazzMcNade 61db6334f9 Restores Combee pathing through leaves 2025-11-25 21:37:57 -06:00
RedGenesectNinja c45e34648c Fixed Toedscool and Toedscruel's hitboxes being too small 2025-11-25 18:53:12 -06:00
jackowes d56586ecac - Fix walking animation issues 2025-11-24 21:39:36 -06:00
jackowes 9df8be33e9 - revert a bad change 2025-11-24 14:51:33 -06:00
jackowes ff2afd546e changelog 2025-11-23 21:50:30 -06:00
jackowes b8b7756a45 - Add double tap to sprint on land mounts
- Adjust step up in air and on ground to reflect vanilla behaviour
- Fix inAir check so pose does not change back to walking or running while in air
2025-11-23 21:29:30 -06:00
jackowes 3d6146f551 - Add double tap to sprint on land mounts.
- Adjust step up in air and on ground to reflect vanilla behaviour
2025-11-23 21:15:41 -06:00
jackowes 31d81db243 Merge branch 'main' into cobble-land-fixes 2025-11-23 18:19:51 -06:00
jackowes 4c36db8685 - Fix ridden pokemon land collision and weird step up issues. Horse is smoother overall now.
- Change the turnrate debuff to be squareroot instead of linear.
- Accel stat does not affect land ridden mounts walks.
- Add vanilla sprinting fov to pokemon land mounts
2025-11-23 18:19:13 -06:00
Guilherme Pereira 7cedfb9047 update CHANGELOG.md 2025-11-22 22:02:14 -03:00
Guilherme Pereira a7ab2e37c2 Merge branch 'main' of gitlab.com:cable-mc/cobblemon into partner-mark 2025-11-22 21:57:49 -03:00
Guilherme Pereira 4723f91500 add riding stats 2025-11-22 21:57:25 -03:00
Guilherme Pereira e23aa6b066 add partner mark molang callback 2025-11-22 19:39:21 -03:00
Neovitalism 46d278ca55 key \:) 2025-11-17 03:18:02 -06:00
Neovitalism 339038956d Support for deserialization from any key
...I think.
2025-11-17 03:09:21 -06:00
Neovitalism 116a93d8cc Update CHANGELOG.md 2025-11-16 04:19:32 -06:00
Neovitalism acebc35d3f Who are we if not consistent?
Before, this property was called `PokemonFlagProperty`, had the key `tag`, and checked pokémon's labels. It was also in a package by itself.

Now, it's moved down into the properties package, renamed to LabelProperty, and the key "label" was added, keeping "tag" as a secondary for those that are using it currently.
2025-11-16 04:10:45 -06:00
Konoha aee89f1c92 Preliminary Bag Clause implementation 2025-09-09 18:15:37 -04:00
371 changed files with 13894 additions and 5928 deletions

No files matched your search

+53 -36
View File
@@ -1,54 +1,71 @@
# Changelog
## [1.7.1 (MONTH xth, 2025)](#1-7-1)
## [1.7.2 (MONTH Xth, YEAR)](#1-7-2)
### Additions
- Added riding statistics: `Distance by Pokémon on Land`, `Distance by Pokémon in Air` and `Distance by Pokémon in Liquid`.
- Added the Partner Mark, which party Pokémon have a very small chance to earn as the player walks, provided they have enough friendship.
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
- Added brewing recipe for Throat Spray.
- Added new effects
- Mental Restoration: Reduces "Time Since Last Rest" statistic, which controls Insomnia, by half a minute per second per effect level
- Negative Effect Cleanse: Removes all negative effects
- Effect Cleanse: Removes all effects
- Added more seasonings for sinister tea
- Mental Herb - Mental Restoration I for 10 seconds
- White Herb - Negative Effect Cleanse
- Milk - Effect Cleanse
- Moomoo Milk - Effect Cleanse
- Added `label` as an alternate key to the `tag` property.
- Added Saccharine wood furniture for Adorn.
### Changes
- Converted the riding freelook button to a configurable keybinding.
- Reduced the cost of the Vivichoke Seed trade with the Wandering Trader.
- Ride sounds have been separated into stereo for passengers and mono for other players. Riding will now sound more spacious.
- Added a new config option, `Enable In-Flight Dismounting` (default: off), which lets you dismount while riding a Pokémon in the air.
- Battle AI now uses a smarter threshold for switching, reducing unnecessary switches.
- AI will always use the most damaging move when at low HP and when it is not switching, improving endgame decision-making.
- Added support for optional message variants in battle activate instructions for more context-specific battle text.
- Example: `this.add('-activate', pokemon, 'ability: example', '[msg]message1');` will parse to lang key `cobblemon.battle.activate.example.message1`
### Fixes
- Prevent displaying ride controls overlay to passengers.
- Fixed player suffocation on vanilla mounts experienced on some worlds.
- Fixed Poké Snack spawning sounds not coming from the block.
- Fix player suffocation on vanilla mounts experienced on some worlds.
- Stop passengers from hearing the shiny noise of a ridden shiny Pokémon.
- Fixed incorrect camera pivot on Bird, Jet, and Dolphin mounts.
- Fixed Poké Snack spawning sound positioning.
- Ponigiri can no longer be eaten at full hunger.
- Medicinal Brew's Campfire Pot recipe now correctly displays that it can be made using an empty glass bottle or a filled bottle.
- Fixed a crash when you place a block in the way of hearty grains 2nd block
- Fixed a graphics crash that could occur on some machines when campfires were nearby.
- Fixed glass bottle not being returned when honey-ing a saccharine leaf block
- Fixed Combees not depositing honey upon leaving a hive if they entered with nectar.
- Fixed pastured Combees not moving in night or rain.
- Fixed a case in which a Combee might try to path to a flower that no longer exists.
- Fixed Combees attempting to enter a full hive.
- Fixed a crash involving Combees and hives.
- Fixed crashing and rendering issues when opening a PC box with certain wallpapers.
- Fixed a crash when opening a PC box with certain wallpapers while using *VulkanMod*.
- Fixed a glitch where friendship would reset to the default value when evolving a Pokémon.
- Fixed a crashed related to NPC navigation.
- Fix player suffocation on vanilla mounts experienced on some worlds.
- Stop passengers from hearing the shiny noise of a ridden shiny Pokémon.
- Fixed friendship resetting to the default value when evolving a Pokémon.
- Fixed a bunch of incompatibilities with NeoForge mods
- Fixed a bug where wind charges hitting pasture blocks would recall all pokémon in it.
- Fixed an issue in the OmniPathNodeMaker/Navigation that prevented Combees from pathing into and out of Saccharine leaves.
- Fixed orientation not getting reset after crashing while flying and getting back on the Pokémon.
- Fixed Furfrou not being trimmable on NeoForge.
- Fixed shiny Pokémon not respecting the silent flag on spawn.
- Fixed honey from Saccharine Leaves being harvestable at less than the max age.
- Items given from interacting with Saccharine Leaves are placed in the active hotbar slot if possible.
- Fix all Pokémon being saved to chunks and never despawning.
- Fixed possible error on world generation when Combees are placed in naturally generated bee nests.
- Fixed PokeSnacks crashing if there was no available spawn.
- Fixed Pokémon spawn influences not being specific to regional forms
- Fixed crashing when viewing another player in spectator mode
- Fixed missing apricorn textures for Adorn blocks
- Fixed crashing when riding due to malformed json file, instead resetting it
- Fixed mochi items consuming two items at a time
- Fix item interaction sometimes not working properly when playing on servers.
- Fixed Soothe Bell not being properly tagged as a held item.
- Fixed Mint Leaves not being usable for filling the Resurrection Machine.
- Added Saccharine Boats and Saccharine Boat with Chests to relevant boat tags.
- Fixed the `run_script` Molang function to not fail if the environment's context is null.
- Fixed the movesets of certain Pokémon being incorrectly sanitized upon reload.
- Fixed the ordering of Aprijuice's riding stat boosts to always have the same order.
- Fixed the Molang functions `date_local_time`, `date_of`, `date_is_after` to use the correct date format.
- Fixed the bottom half of pasture blocks having an incorrect hit-box when facing north or south.
- Fixed Galarian Mr. Mime incorrectly being rideable.
- Fixed gimmicks not being usable in double / triple battles
- Fixed gimmick buttons showing when already used in the same turn in double / triple battles
- Fixed Apricorn block model rotation for counters/sinks/cupboards/drawers to match that of most recent version of Adorn.
- Fixed Scraggy & Scrafty being able to spawn on non-natural blocks in badlands
### Developer
- Changed the `owner` parameter in the `OwnerQueryRequirement` interface from `ServerPlayer` to `Player`. This method is now also called on the client to verify whether a Pokémon interaction succeeded, so make sure to update your implementations to handle both server and client contexts.
### Molang & Datapacks
- Removed automatic generation of PC wallpaper screen glow if no asset is provided; it is now optional.
- Ride sounds can now be set as exclusive to passengers
- Ride sounds no longer play when submerged unless specified with a new setting
- Exception handling has been added to `run_molang`, resolving some crashes caused by malformed MoLang expressions.
### Particles
### Localization
- Updated translations for:
- French
- Japanese
- Korean
- Brazilian Portuguese
- Simplified Chinese
- Traditional Chinese
+61
View File
@@ -0,0 +1,61 @@
# Changelog
## [1.7.1 (November 29th, 2025)](#1-7-1)
### Additions
- Added trades for Saccharine Saplings, Hearty Grains, Chipped Pot, and Masterpiece Teacup to the Wandering Trader.
- Added brewing recipe for Throat Spray.
- Added vanilla sprinting's field of view change to Pokémon land mounts.
- Added a customizable keybind for the riding freelook button.
- Added double tap to sprint on land mounts.
### Changes
- Made Jet pitch turning 1.5x faster across all Pokémon.
- Party Pokémon now attack only mobs that are attacking their owner, instead of randomly targeting unrelated mobs and getting themselves hurt.
- Reduced the cost of the Vivichoke Seed trade with the Wandering Trader.
### Fixes
- Fixed incorrect camera pivot on Bird, Jet, and Dolphin mounts, leading to some disorienting riding.
- Fixed players suffocating while on vanilla mounts.
- Fixed a graphics crash that could occur on some machines when campfire pots were nearby.
- Fixed ride controls overlay being displayed to passengers. The passengers probably don't need to know about those.
- Fixed mount jumping so that it doesn't switch back to ground animations.
- Fixed ridden Pokémon land collision and some issues around stepping up blocks. Land mounts are smoother overall now.
- Fixed Furfrou's pink and magenta trims being swapped. Only a man could make that mistake.
- Fixed friendship being reset to the default value when evolving a Pokémon.
- Fixed Combees not depositing honey upon leaving a hive if they entered it with nectar.
- Fixed pastured Combees not moving during the night or in rain.
- Fixed a case in which a Combee might try to path to a flower that no longer exists.
- Fixed Combees attempting to enter a full hive.
- Fixed a crash involving Combees and hives. 500 bee bugs. Bugged bees? We can be bees. Mark, this is good news.
- Fixed a crash related to NPC navigation.
- Fixed a crash when opening a PC box with certain wallpapers while using *VulkanMod*.
- Fixed a crash when you place a block in the way of hearty grains 2nd block.
- Fixed passengers hearing the shiny noise of a ridden shiny Pokémon.
- Ponigiri can no longer be eaten at full hunger.
- Fixed Poké Snack spawning sounds not coming from the block.
- Medicinal Brew's Campfire Pot recipe now correctly displays that it can be made using an empty glass bottle or a filled bottle.
- Fixed glass bottle not being returned when slathering honey on a saccharine leaf block.
- Fixed saccharine hanging signs sometimes dropping their oak wood counterpart when being broken.
- Fixed a bunch of incompatibilities with NeoForge mods.
- Fixed a bug where wind charges hitting pasture blocks would recall all Pokémon in it.
- Fixed the Home on the Range advancement triggering when opening the Pokémon interaction wheel.
- Fixed recipes that use concrete not working on NeoForge.
- Fixed Boltund's model.
- Fixed Cyclizar's textures.
### Developer
### Molang & Datapacks
- Removed automatic generation of PC wallpaper screen glow if no asset is provided; it is now optional.
- This is because there's no practical way to do this without blowing up things like *VulkanMod*.
### Particles
### Localization
- Updated translations for:
- French
- Japanese
- Korean
- Brazilian Portuguese
- Simplified Chinese
- Traditional Chinese
@@ -11,7 +11,9 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.CobblemonMemories;
import com.cobblemon.mod.common.api.ai.config.task.PathToBeeHiveTaskConfig;
import com.cobblemon.mod.common.api.pokemon.PokemonProperties;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.world.feature.SaccharineTreeFeature;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.tags.BlockTags;
@@ -42,7 +44,21 @@ public abstract class BeeOccupantMixin {
if (cir.getReturnValue() == null) {
final BeehiveBlockEntity.Occupant occupant = (BeehiveBlockEntity.Occupant) (Object) this;
CompoundTag compoundTag = occupant.entityData().copyTag();
Entity entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
String id = compoundTag.getString("id");
Entity entity = null;
if (id.equals(SaccharineTreeFeature.Companion.getPOKEMON_PLACEHOLD_ID())) {
// Special case for Pokemon stuffed into a beenest upon world gen.
// For technical reasons we cannot create them as full entities during world gen.
// So we look for this special id tag and complete the entity when it attempts to exit a hive.
if (compoundTag.contains("pokemonProperties")) {
String properties = compoundTag.getString("pokemonProperties");
PokemonProperties pokemon = PokemonProperties.Companion.parse(properties);
entity = pokemon.createEntity(level);
}
} else {
entity = EntityType.loadEntityRecursive(compoundTag, level, (entityx) -> entityx);
}
if (entity instanceof PokemonEntity pokemonEntity) {
var state = level.getBlockState(pos);
var newPos = Vec3.ZERO;
@@ -37,16 +37,16 @@ public class ClientPacketListenerMixin {
passengers.add(this.level.getEntity(passenger));
}
Arrays
.stream(pokemon.getOccupiedSeats())
.filter(x -> !passengers.contains(x))
.filter(Objects::nonNull)
.forEach(Entity::stopRiding);
.stream(pokemon.getOccupiedSeats())
.filter(x -> !passengers.contains(x))
.filter(Objects::nonNull)
.forEach(Entity::stopRiding);
var occupiedSeats = Arrays.asList(pokemon.getOccupiedSeats());
passengers.stream()
.filter(x -> !occupiedSeats.contains(x))
.filter(Objects::nonNull)
.forEach(x -> x.startRiding(pokemon, true));
.filter(x -> !occupiedSeats.contains(x))
.filter(Objects::nonNull)
.forEach(x -> x.startRiding(pokemon, true));
ci.cancel();
}
}
@@ -11,11 +11,15 @@ package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.Cobblemon;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.PlayerSpawnerAccessor;
import com.cobblemon.mod.common.api.riding.RidingStyle;
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner;
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawnerFactory;
import com.cobblemon.mod.common.api.stats.CobblemonStats;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
@@ -89,4 +93,32 @@ public abstract class ServerPlayerMixin implements PlayerSpawnerAccessor {
private boolean cobblemon$cancelSavingPokemonMounts(boolean original, @Local(ordinal=0) Entity entity) {
return original && !(entity instanceof PokemonEntity);
}
@WrapOperation(method = "checkRidingStatistics", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getVehicle()Lnet/minecraft/world/entity/Entity;"))
public Entity cobblemon$checkRidingStatistics(ServerPlayer player, Operation<Entity> original, @Local int distance) {
var entity = original.call(player);
if (!(entity instanceof PokemonEntity pokemonEntity)) {
return entity;
}
var ridingController = pokemonEntity.getRidingController();
if (ridingController == null) return entity;
var activeContext = ridingController.getContext();
if (activeContext == null) return entity;
var ridingStyle = activeContext.getStyle();
CobblemonStats.CobblemonStat stat = switch (ridingStyle) {
case RidingStyle.LAND -> CobblemonStats.RIDING_LAND;
case RidingStyle.AIR -> CobblemonStats.RIDING_AIR;
case RidingStyle.LIQUID -> CobblemonStats.RIDING_LIQUID;
default -> null;
};
if (stat != null) {
player.awardStat(CobblemonStats.getStat(stat), distance);
}
return entity;
}
}
@@ -33,7 +33,7 @@ public class AbstractClientPlayerMixin {
cir.setReturnValue(usageContext.getFovMultiplier());
} else {
// Only modify fov through riding if the pokedex is not open
LocalPlayer player = (LocalPlayer) (Object) this;
AbstractClientPlayer player = (AbstractClientPlayer) (Object) this;
// Only modify fov for the driver and not the passengers
if (player != null && player.isPassenger() && player.getVehicle() instanceof PokemonEntity && player.getVehicle().getControllingPassenger() == player) {
PokemonEntity ride = (PokemonEntity) player.getVehicle();
@@ -50,16 +50,8 @@ public abstract class EntityMixin {
)
)
public boolean cobblemon$forceOnGroundForStepUp(Entity entity, Operation<Boolean> original) {
if (entity instanceof PokemonEntity && entity.hasControllingPassenger()) {
BlockPos below = entity.blockPosition().below();
Level level = entity.level();
var blockStateBelow = level.getBlockState(below);
boolean isAirOrLiquid = blockStateBelow.isAir() || !blockStateBelow.getFluidState().isEmpty();
boolean canSupportEntity = blockStateBelow.isFaceSturdy(level, below, Direction.UP);
boolean standingOnSolid = canSupportEntity && !isAirOrLiquid;
if (standingOnSolid) {
return true;
}
if (entity instanceof PokemonEntity vehicle && entity.hasControllingPassenger()) {
return true;
}
return original.call(entity);
}
@@ -42,8 +42,8 @@ import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
import com.cobblemon.mod.common.api.scheduling.ServerTaskTracker
import com.cobblemon.mod.common.api.spawning.BestSpawner
import com.cobblemon.mod.common.api.spawning.CobblemonSpawningZoneGenerator
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
import com.cobblemon.mod.common.api.spawning.SpawningZoneGenerator
import com.cobblemon.mod.common.api.spawning.position.AreaSpawnablePositionResolver
import com.cobblemon.mod.common.api.starter.StarterHandler
import com.cobblemon.mod.common.api.stats.CobblemonStats
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
@@ -76,12 +76,7 @@ import com.cobblemon.mod.common.config.LastChangedVersion
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.EntityCallbackHandler
import com.cobblemon.mod.common.events.CallbackHandler
import com.cobblemon.mod.common.events.PokedexHandler
import com.cobblemon.mod.common.events.ServerTickHandler
import com.cobblemon.mod.common.events.StatHandler
import com.cobblemon.mod.common.events.*
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
import com.cobblemon.mod.common.permission.LaxPermissionValidator
import com.cobblemon.mod.common.platform.events.PlatformEvents
@@ -96,7 +91,7 @@ import com.cobblemon.mod.common.pokemon.feature.SlowpokeTailRegrowthSpeciesFeatu
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
import com.cobblemon.mod.common.pokemon.properties.*
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
import com.cobblemon.mod.common.pokemon.properties.LabelProperty
import com.cobblemon.mod.common.pokemon.stat.CobblemonStatProvider
import com.cobblemon.mod.common.starter.CobblemonStarterHandler
import com.cobblemon.mod.common.util.*
@@ -206,6 +201,7 @@ object Cobblemon {
implementation.registerEntityDataSerializers()
implementation.registerCriteria()
implementation.registerEntitySubPredicates()
implementation.registerMobEffects()
DispenserBehaviorRegistry.registerDispenserBehaviors()
DropEntry.register("command", CommandDropEntry::class.java)
@@ -319,7 +315,7 @@ object Cobblemon {
CustomPokemonProperty.register(UncatchableProperty)
CustomPokemonProperty.register(BattleCloneProperty)
CustomPokemonProperty.register(PokemonFlagProperty)
CustomPokemonProperty.register(LabelProperty)
CustomPokemonProperty.register(HiddenAbilityPropertyType)
CustomPokemonProperty.register(AspectPropertyType)
CustomPokemonProperty.register(UnaspectPropertyType)
@@ -215,7 +215,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
@JvmField
val SACCHARINE_WALL_SIGN = this.create("saccharine_wall_sign", CobblemonWallSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
val SACCHARINE_WALL_HANGING_SIGN = this.create("saccharine_wall_hanging_sign", CobblemonWallHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
@JvmField
@@ -117,6 +117,11 @@ interface CobblemonImplementation {
fun registerEntitySubPredicates()
/**
* TODO
*/
fun registerMobEffects()
/**
* Add a feature to the current platform implementation.
@@ -0,0 +1,33 @@
/*
* 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
import com.cobblemon.mod.common.api.cooking.effects.CleanseAllEffect
import com.cobblemon.mod.common.api.cooking.effects.CleanseNegativeEffect
import com.cobblemon.mod.common.api.cooking.effects.MentalRestorationEffect
import com.cobblemon.mod.common.platform.PlatformRegistry
import net.minecraft.core.Registry
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.core.registries.Registries
import net.minecraft.resources.ResourceKey
import net.minecraft.world.effect.MobEffect
object CobblemonMobEffects : PlatformRegistry<Registry<MobEffect>, ResourceKey<Registry<MobEffect>>, MobEffect>() {
override val registry: Registry<MobEffect> = BuiltInRegistries.MOB_EFFECT
override val resourceKey: ResourceKey<Registry<MobEffect>> = Registries.MOB_EFFECT
@JvmField
val CLEANSE_NEGATIVE = create("cleanse_negative", CleanseNegativeEffect())
@JvmField
val MENTAL_RESTORATION = create("mental_restoration", MentalRestorationEffect())
@JvmField
val CLEANSE_ALL = create("cleanse_all", CleanseAllEffect())
}
@@ -21,15 +21,12 @@ import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallb
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
import com.cobblemon.mod.common.client.net.data.CobblemonMechanicsSyncHandler
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
import com.cobblemon.mod.common.client.net.data.PokemonInteractionsSyncHandler
import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
import com.cobblemon.mod.common.client.net.debug.OpenRidingStatsDebugGUIHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
import com.cobblemon.mod.common.client.net.effect.PokeSnackBlockParticlesHandler
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
import com.cobblemon.mod.common.client.net.effect.SaccharineLogBlockParticlesHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
import com.cobblemon.mod.common.client.net.effect.*
import com.cobblemon.mod.common.client.net.gui.ExpGainedDataPacketHandler
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
@@ -37,11 +34,7 @@ import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
import com.cobblemon.mod.common.client.net.orientation.ClientboundUpdateOrientationHandler
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureConflictFlagHandler
import com.cobblemon.mod.common.client.net.pasture.*
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
@@ -59,14 +52,7 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
import com.cobblemon.mod.common.client.net.storage.pc.*
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
import com.cobblemon.mod.common.client.net.trade.*
import com.cobblemon.mod.common.net.PacketRegisterInfo
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
@@ -83,20 +69,12 @@ import com.cobblemon.mod.common.net.messages.client.data.*
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
import com.cobblemon.mod.common.net.messages.client.effect.SaccharineLogBlockParticlesPacket
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.effect.*
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateDriverInputPacket
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
import com.cobblemon.mod.common.net.messages.client.pasture.*
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
@@ -116,43 +94,19 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.UnlockPCBoxWallpaperPacket
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
import com.cobblemon.mod.common.net.messages.client.trade.*
import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
import com.cobblemon.mod.common.net.messages.server.*
import com.cobblemon.mod.common.net.messages.server.battle.*
import com.cobblemon.mod.common.net.messages.server.behaviour.DamageOnCollisionPacket
import com.cobblemon.mod.common.net.messages.server.behaviour.SetEntityBehaviourPacket
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
@@ -177,11 +131,7 @@ import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPack
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMarkPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
import com.cobblemon.mod.common.net.messages.server.pokemon.update.*
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket
@@ -192,21 +142,11 @@ import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokem
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
import com.cobblemon.mod.common.net.messages.server.trade.*
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
import com.cobblemon.mod.common.net.serverhandling.battle.*
import com.cobblemon.mod.common.net.serverhandling.behaviour.DamageOnCollisionPacketHandler
import com.cobblemon.mod.common.net.serverhandling.behaviour.SetEntityBehaviourHandler
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
@@ -232,11 +172,7 @@ import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandl
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.*
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
import com.cobblemon.mod.common.net.serverhandling.riding.DriverInputPacketHandler
import com.cobblemon.mod.common.net.serverhandling.riding.ServerboundUpdateRiderRotationHandler
@@ -250,12 +186,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemo
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
import com.cobblemon.mod.common.net.serverhandling.trade.*
import com.cobblemon.mod.common.util.server
import net.minecraft.server.level.ServerPlayer
@@ -401,6 +332,7 @@ object CobblemonNetwork {
// Data registries
list.add(PacketRegisterInfo(AbilityRegistrySyncPacket.ID, AbilityRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(CobblemonMechanicsSyncPacket.ID, CobblemonMechanicsSyncPacket::decode, CobblemonMechanicsSyncHandler))
list.add(PacketRegisterInfo(PokemonInteractionsSyncPacket.ID, PokemonInteractionsSyncPacket::decode, PokemonInteractionsSyncHandler))
list.add(PacketRegisterInfo(MovesRegistrySyncPacket.ID, MovesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
@@ -0,0 +1,44 @@
/*
* 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.ai.config.task
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.api.ai.BehaviourConfigurationContext
import com.cobblemon.mod.common.api.ai.WrapperLivingEntityTask
import com.cobblemon.mod.common.api.npc.configuration.MoLangConfigVariable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.entity.pokemon.ai.tasks.DefendOwnerTask
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.behavior.BehaviorControl
import net.minecraft.world.entity.ai.memory.MemoryModuleType
class DefendOwnerTaskConfig : SingleTaskConfig {
override fun getVariables(
entity: LivingEntity,
behaviourConfigurationContext: BehaviourConfigurationContext
): List<MoLangConfigVariable> {
return emptyList()
}
override fun createTask(
entity: LivingEntity,
behaviourConfigurationContext: BehaviourConfigurationContext
): BehaviorControl<in LivingEntity>? {
behaviourConfigurationContext.addMemories(
MemoryModuleType.ATTACK_TARGET,
CobblemonMemories.NEAREST_VISIBLE_ATTACKER,
)
return WrapperLivingEntityTask(
DefendOwnerTask.create(),
PokemonEntity::class.java
)
}
}
@@ -105,6 +105,7 @@ interface TaskConfig {
cobblemonResource("go_to_land") to GoToLandTaskConfig::class.java,
cobblemonResource("manage_flight_in_battle") to ManageFlightInBattleTaskConfig::class.java,
cobblemonResource("attack_hostile_mobs") to AttackHostileMobsTaskConfig::class.java,
cobblemonResource("defend_owner") to DefendOwnerTaskConfig::class.java,
cobblemonResource("move_to_sweet_berry_bush") to MoveToSweetBerryBushTaskConfig::class.java,
cobblemonResource("stop_moving_to_sweet_berry_bush") to StopTryingToReachSweetBerryBushTaskConfig::class.java,
cobblemonResource("harvest_sweet_berry_bush") to HarvestSweetBerryBushTaskConfig::class.java,
@@ -0,0 +1,22 @@
/*
* 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.cooking.effects
import net.minecraft.world.effect.MobEffect
import net.minecraft.world.effect.MobEffectCategory
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.LivingEntity
class CleanseAllEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
override fun isInstantenous() = true
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
target.removeAllEffects()
}
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
}
@@ -0,0 +1,27 @@
/*
* 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.cooking.effects
import net.minecraft.world.effect.MobEffect
import net.minecraft.world.effect.MobEffectCategory
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.LivingEntity
class CleanseNegativeEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xFFFFFF) {
override fun isInstantenous() = true
override fun applyInstantenousEffect(source: Entity?, indirect: Entity?, target: LivingEntity, amplifier: Int, proximity: Double) {
val snapshot = target.activeEffects.toList()
for (ei in snapshot) {
if (ei.effect.value().category == MobEffectCategory.HARMFUL) {
target.removeEffect(ei.effect)
}
}
}
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int) = false
}
@@ -0,0 +1,33 @@
/*
* 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.cooking.effects
import net.minecraft.server.level.ServerPlayer
import net.minecraft.stats.Stats
import net.minecraft.world.effect.MobEffect
import net.minecraft.world.effect.MobEffectCategory
import net.minecraft.world.entity.LivingEntity
class MentalRestorationEffect : MobEffect(MobEffectCategory.BENEFICIAL, 0xAA66FF) {
override fun applyEffectTick(entity: LivingEntity, amplifier: Int): Boolean {
if (entity is ServerPlayer) {
val stats = entity.stats
val statType = Stats.CUSTOM.get(Stats.TIME_SINCE_REST)
val current = stats.getValue(statType)
val reduction = 31 * (amplifier + 1)// reduce by half a minute every second per level (30 ticks removed per tick + 1 to account for the tick passing)
val newValue = Math.max(current - reduction, 0)
stats.setValue(entity, statType, newValue)
}
return true
}
override fun shouldApplyEffectTickThisTick(duration: Int, amplifier: Int): Boolean {
return true
}
}
@@ -12,10 +12,10 @@ import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.requirements.PokemonPropertiesRequirement
@@ -51,7 +51,12 @@ object PokemonInteractions : JsonDataRegistry<PokemonInteractionSet> {
val speciesInteractions = mutableListOf<PokemonInteractionSet>()
val generalInteractions = mutableListOf<PokemonInteractionSet>()
override fun sync(player: ServerPlayer) {}
override fun sync(player: ServerPlayer) {
PokemonInteractionsSyncPacket(
speciesInteractions,
generalInteractions,
).sendToPlayer(player)
}
override fun reload(data: Map<ResourceLocation, PokemonInteractionSet>) {
speciesInteractions.clear()
@@ -15,11 +15,10 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
import com.cobblemon.mod.common.util.asExpressionLike
import com.cobblemon.mod.common.util.giveOrDropItemStack
import com.cobblemon.mod.common.util.withPlayerValue
import com.cobblemon.mod.common.util.withQueryValue
import com.cobblemon.mod.common.pokemon.adapters.CobblemonRequirementAdapter
import com.cobblemon.mod.common.util.*
import net.minecraft.core.registries.Registries
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.sounds.SoundSource
@@ -28,30 +27,83 @@ import net.minecraft.world.entity.EquipmentSlot
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.ItemStack
/**
* A
*/
data class PokemonInteractionSet(
val requirements: List<Requirement> = listOf(),
val interactions: List<PokemonInteraction> = listOf()
)
val interactions: List<PokemonInteraction> = listOf(),
) {
fun encode(buffer: FriendlyByteBuf) {
buffer.writeCollection(requirements) { it, requirement ->
CobblemonRequirementAdapter.encode(requirement, it)
}
buffer.writeCollection(interactions) { it, interaction ->
interaction.encode(it)
}
}
companion object {
fun decode(buffer: FriendlyByteBuf): PokemonInteractionSet {
val requirements = buffer.readList { it ->
CobblemonRequirementAdapter.decode(it)
}
val interactions = buffer.readList { it ->
PokemonInteraction.decode(it)
}
return PokemonInteractionSet(
requirements,
interactions,
)
}
}
}
data class PokemonInteraction(
val grouping: ResourceLocation,
val requirements: List<Requirement> = listOf(),
val effects: List<InteractionEffect> = listOf(),
val cooldown: ExpressionLike = "0".asExpressionLike()
)
) {
fun encode(buffer: FriendlyByteBuf) {
buffer.writeResourceLocation(grouping)
buffer.writeCollection(requirements) { it, requirement ->
CobblemonRequirementAdapter.encode(requirement, it)
}
buffer.writeExpressionLike(cooldown)
}
companion object {
fun decode(buffer: FriendlyByteBuf): PokemonInteraction {
val grouping = buffer.readResourceLocation()
val requirements = buffer.readList { it ->
CobblemonRequirementAdapter.decode(it)
}
// No need to sync these for now
val effects = emptyList<InteractionEffect>()
val cooldown = buffer.readExpressionLike()
return PokemonInteraction(
grouping,
requirements,
effects,
cooldown,
)
}
}
}
interface InteractionEffect {
fun applyEffect(pokemon: PokemonEntity, player: ServerPlayer)
}
class DropItemEffect(val item: ResourceLocation, val amount: IntRange?): InteractionEffect {
class DropItemEffect(val item: ResourceLocation, val amount: IntRange?) : InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
) {
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException("Cannot load item with id: $item")
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException(
"Cannot load item with id: $item"
)
val stack = ItemStack(item)
stack.count = amount?.randomOrNull() ?: 1
if (stack.isEmpty)
@@ -68,12 +120,14 @@ class DropItemEffect(val item: ResourceLocation, val amount: IntRange?): Interac
}
}
class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?): InteractionEffect {
class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?) : InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
) {
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException("Cannot load item with id: $item")
val item = player.registryAccess().registryOrThrow(Registries.ITEM).get(item) ?: throw IllegalArgumentException(
"Cannot load item with id: $item"
)
val stack = ItemStack(item)
stack.count = amount?.randomOrNull() ?: 1
if (stack.isEmpty)
@@ -86,14 +140,29 @@ class GiveItemEffect(val item: ResourceLocation, val amount: IntRange?): Interac
}
}
class PlaySoundEffect(val sound: ResourceLocation, val soundSource: SoundSource?, val playAround: Boolean = true, val distance: Double = 64.0, val volume: Float = 1.0F, val pitch: Float = 1.0F): InteractionEffect {
class PlaySoundEffect(
val sound: ResourceLocation,
val soundSource: SoundSource?,
val playAround: Boolean = true,
val distance: Double = 64.0,
val volume: Float = 1.0F,
val pitch: Float = 1.0F
) : InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
) {
val packet = UnvalidatedPlaySoundS2CPacket(sound, soundSource ?: SoundSource.NEUTRAL, pokemon.x, pokemon.y, pokemon.z, volume, pitch)
val packet = UnvalidatedPlaySoundS2CPacket(
sound,
soundSource ?: SoundSource.NEUTRAL,
pokemon.x,
pokemon.y,
pokemon.z,
volume,
pitch
)
if (playAround) {
packet.sendToPlayersAround( pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
packet.sendToPlayersAround(pokemon.x, pokemon.y, pokemon.z, distance, pokemon.level().dimension())
} else {
packet.sendToPlayer(player)
}
@@ -104,7 +173,7 @@ class PlaySoundEffect(val sound: ResourceLocation, val soundSource: SoundSource?
}
}
class ShrinkItemEffect(val amount: Int = 1): InteractionEffect {
class ShrinkItemEffect(val amount: Int = 1) : InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
@@ -120,7 +189,7 @@ class ShrinkItemEffect(val amount: Int = 1): InteractionEffect {
}
}
class ScriptEffect(val script: ExpressionLike): InteractionEffect {
class ScriptEffect(val script: ExpressionLike) : InteractionEffect {
override fun applyEffect(
pokemon: PokemonEntity,
player: ServerPlayer
@@ -311,7 +311,7 @@ object MoLangFunctions {
runtime.environment.variable = params.environment.variable
val args = params.params.subList(1, params.params.size)
runtime.environment.context = ContextStruct(
params.environment.context.map + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
(params.environment.context?.map ?: emptyMap()) + args.mapIndexed { index, value -> "arg_${index + 1}" to value }.toMap()
)
val script = params.getString(0).asIdentifierDefaultingNamespace()
// store the args in the
@@ -324,13 +324,24 @@ object MoLangFunctions {
runtime.environment.context = params.environment.context
val expression = params.getString(0).asExpressionLike()
val delayInSeconds = params.getDoubleOrNull(1)?.toFloat() ?: 0.0f
fun evaluate(): MoValue {
return try {
runtime.resolve(expression)
} catch (ex: Exception) {
Cobblemon.LOGGER.warn("Failed to evaluate MoLang expression${if (delayInSeconds > 0.0f) " (delayed)" else ""}: $expression", ex)
DoubleValue.ZERO
}
}
if (delayInSeconds > 0.0f) {
val tracker = if (Cobblemon.implementation.environment() == Environment.SERVER) ServerTaskTracker else ClientTaskTracker
tracker.after(delayInSeconds) {
runtime.resolve(expression)
evaluate()
}
DoubleValue.ONE
} else {
runtime.resolve(expression)
evaluate()
}
},
"system_time_millis" to java.util.function.Function { _ ->
@@ -340,19 +351,19 @@ object MoLangFunctions {
"date_local_time" to java.util.function.Function { _ ->
val time = System.currentTimeMillis()
val date = java.util.Date(time)
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
StringValue(formatted)
},
"date_of" to java.util.function.Function { params ->
val time = params.getDouble(0).toLong()
val date = java.util.Date(time)
val formatted = java.text.SimpleDateFormat("DD/MM/YYYY").format(date)
val formatted = java.text.SimpleDateFormat("dd/MM/yyyy").format(date)
StringValue(formatted)
},
"date_is_after" to java.util.function.Function { params ->
val dateA = params.getString(0)
val dateB = params.getString(1)
val format = java.text.SimpleDateFormat("DD/MM/YYYY")
val format = java.text.SimpleDateFormat("dd/MM/yyyy")
val a = format.parse(dateA)
val b = format.parse(dateB)
DoubleValue(a.after(b))
@@ -779,6 +790,20 @@ object MoLangFunctions {
battleStartResult.ifSuccessful { returnValue = it.struct }
return@put returnValue
}
map.put("get_custom_stat") { params ->
val statName = params.getString(0)
val resourceLocation = ResourceLocation.tryParse(statName) ?: return@put DoubleValue.ZERO
val statResourceLocation = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation) ?: return@put DoubleValue.ZERO
val exists = net.minecraft.stats.Stats.CUSTOM.contains(statResourceLocation)
if (!exists) return@put DoubleValue.ZERO
val stat = net.minecraft.stats.Stats.CUSTOM.get(statResourceLocation)
val value = player.stats.getValue(stat)
DoubleValue(value)
}
}
map
}
@@ -1739,22 +1764,35 @@ object MoLangFunctions {
pokemon.removeCosmeticItem()
}
map.put("add_marks") { params ->
var appliedMark = false
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
if (mark != null) pokemon.exchangeMark(mark, true)
if (mark != null) {
pokemon.exchangeMark(mark, true)
appliedMark = true
}
}
DoubleValue(appliedMark)
}
map.put("add_marks_with_chance") { params ->
var appliedMark = false
for (param in params.params) {
val identifier = param.asString().asIdentifierDefaultingNamespace()
val mark = Marks.getByIdentifier(identifier)
mark?.let {
val probability = it.chance.coerceIn(0F, 1F) * 100
val randomValue = Random.nextDouble(0.0, 100.0)
if (randomValue < probability) pokemon.exchangeMark(it, true)
if (randomValue < probability) {
pokemon.exchangeMark(it, true)
appliedMark = true
}
}
}
DoubleValue(appliedMark)
}
map.put("add_potential_marks") { params ->
for (param in params.params) {
@@ -80,7 +80,9 @@ open class ChoiceSpeciesFeatureProvider(
internal constructor(): this(emptyList())
override fun get(pokemon: Pokemon) = pokemon.getFeature<StringSpeciesFeature>(keys.first())
override fun get(pokemon: Pokemon): StringSpeciesFeature? {
return pokemon.features.filterIsInstance<StringSpeciesFeature>().find { it.name in keys }
}
override fun invoke(pokemon: Pokemon): StringSpeciesFeature? {
val existing = get(pokemon)
@@ -101,15 +103,15 @@ open class ChoiceSpeciesFeatureProvider(
}
override fun invoke(nbt: CompoundTag): StringSpeciesFeature? {
return if (nbt.contains(keys.first())) {
StringSpeciesFeature(keys.first(), "").also { it.loadFromNBT(nbt) }
} else null
val key = keys.find { nbt.contains(it) }
if (key == null) return null
return StringSpeciesFeature(key, "").also { it.loadFromNBT(nbt) }
}
override fun invoke(json: JsonObject): StringSpeciesFeature? {
return if (json.has(keys.first())) {
StringSpeciesFeature(keys.first(), "").also { it.loadFromJSON(json) }
} else null
val key = keys.find { json.has(it) }
if (key == null) return null
return StringSpeciesFeature(key, "").also { it.loadFromJSON(json) }
}
override fun fromString(value: String?): StringSpeciesFeature? {
@@ -131,7 +133,7 @@ open class ChoiceSpeciesFeatureProvider(
override fun provide(properties: PokemonProperties): Set<String> {
return if (isAspect) {
val feature = properties.customProperties.filterIsInstance<StringSpeciesFeature>().find { it.name == keys.first() }
val feature = properties.customProperties.filterIsInstance<StringSpeciesFeature>().find { it.name in keys }
if (feature != null) {
setOf(getAspect(feature))
} else {
@@ -132,7 +132,9 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
constructor(vararg keys: String) : this(keys.toList())
override fun get(pokemon: Pokemon) = pokemon.getFeature<FlagSpeciesFeature>(keys.first())
override fun get(pokemon: Pokemon): FlagSpeciesFeature? {
return pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
}
override fun invoke(pokemon: Pokemon): FlagSpeciesFeature? {
return get(pokemon)
@@ -144,15 +146,15 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
}
override fun invoke(nbt: CompoundTag): FlagSpeciesFeature? {
return if (nbt.contains(keys.first())) {
FlagSpeciesFeature(keys.first(), false).also { it.loadFromNBT(nbt) }
} else null
val key = keys.find { nbt.contains(it) }
if (key == null) return null
return FlagSpeciesFeature(key, false).also { it.loadFromNBT(nbt) }
}
override fun invoke(json: JsonObject): FlagSpeciesFeature? {
return if (json.has(keys.first())) {
FlagSpeciesFeature(keys.first(), false).also { it.loadFromJSON(json) }
} else null
val key = keys.find { json.has(it) }
if (key == null) return null
return FlagSpeciesFeature(key, false).also { it.loadFromJSON(json) }
}
override fun fromString(value: String?): FlagSpeciesFeature? {
@@ -170,16 +172,26 @@ class FlagSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<FlagSpecie
}
override fun provide(pokemon: Pokemon): Set<String> {
return if (isAspect && pokemon.getFeature<FlagSpeciesFeature>(keys.first())?.enabled == true) {
setOf(keys.first())
return if (isAspect) {
val feature = pokemon.features.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
if (feature != null && feature.enabled) {
setOf(keys.first())
} else {
emptySet()
}
} else {
emptySet()
}
}
override fun provide(properties: PokemonProperties): Set<String> {
return if (isAspect && properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name == keys.first() }?.enabled == true) {
setOf(keys.first())
return if (isAspect) {
val feature = properties.customProperties.filterIsInstance<FlagSpeciesFeature>().find { it.name in keys }
if (feature != null && feature.enabled) {
setOf(keys.first())
} else {
emptySet()
}
} else {
emptySet()
}
@@ -142,19 +142,15 @@ class IntSpeciesFeatureProvider : SynchronizedSpeciesFeatureProvider<IntSpeciesF
}
override fun invoke(nbt: CompoundTag): IntSpeciesFeature? {
return if (nbt.contains(keys.first())) {
IntSpeciesFeature(keys.first(), nbt.getInt(keys.first()))
} else {
null
}
val key = keys.find { nbt.contains(it) }
if (key == null) return null
return IntSpeciesFeature(keys.first(), nbt.getInt(key));
}
override fun invoke(json: JsonObject): IntSpeciesFeature? {
return if (json.has(keys.first())) {
IntSpeciesFeature(keys.first(), json.get(keys.first()).asInt)
} else {
null
}
val key = keys.find { json.has(it) }
if (key == null) return null
return IntSpeciesFeature(keys.first(), json.get(key).asInt)
}
override fun get(pokemon: Pokemon) = pokemon.features.filterIsInstance<IntSpeciesFeature>().find { it.name in keys }
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
/**
* A [Requirement] that expects a [LivingEntity] to be attached to the [Pokemon].
@@ -26,7 +27,7 @@ interface OwnerQueryRequirement : Requirement {
override fun check(pokemon: Pokemon): Boolean {
val owner = pokemon.getOwnerEntity() ?: return false
return when (owner) {
is ServerPlayer -> {
is Player -> {
this.checkPlayer(pokemon, owner)
}
is NPCEntity -> {
@@ -37,13 +38,13 @@ interface OwnerQueryRequirement : Requirement {
}
/**
* Checks if the given [Pokemon] & [ServerPlayer] satisfies the requirement.
* Checks if the given [Pokemon] & [Player] satisfies the requirement.
*
* @param pokemon The [Pokemon] being queried.
* @param owner The [ServerPlayer] that owns this [Pokemon].
* @param owner The [Player] that owns this [Pokemon].
* @return If the requirement was satisfied.
*/
fun checkPlayer(pokemon: Pokemon, owner: ServerPlayer): Boolean
fun checkPlayer(pokemon: Pokemon, owner: Player): Boolean
/**
* Checks if the given [Pokemon] & [NPCEntity] satisfies the requirement.
@@ -322,7 +322,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
val pitchRot = handling * state.currMouseYForce.get()
// Roll
val rollRot = handling * 1.5 * state.currMouseXForce.get()
val rollRot = handling * state.currMouseXForce.get()
val mouseRotation = Vec3(0.0, pitchRot, rollRot)
@@ -34,7 +34,6 @@ import com.cobblemon.mod.common.util.resolveFloat
import com.cobblemon.mod.common.util.writeNullableExpression
import com.cobblemon.mod.common.util.writeRidingStats
import net.minecraft.client.Minecraft
import net.minecraft.client.player.LocalPlayer
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
@@ -115,10 +114,10 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
input: Vec3
) {
if (vehicle.level().isClientSide) {
handleSprinting(state)
handleSprinting(state, driver)
inAirCheck(state, vehicle)
tickStamina(settings, state, vehicle)
state.walking.set(state.rideVelocity.get().horizontalDistance() > 0.01)
state.walking.set(state.rideVelocity.get().horizontalDistance() > 0.01 || driver.zza != 0.0f)
}
}
@@ -140,9 +139,24 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
}
fun handleSprinting(
state: HorseState
state: HorseState,
driver: Player
) {
val tryingToSprint = Minecraft.getInstance().options.keySprint.isDown() && Minecraft.getInstance().options.keyUp.isDown()
val sprintTimerTickLength = 7 // Emulate vanillas tick timer length
var hasDoubleTapped = false
// If you are not sprinting and you just pressed down and theres no
if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && !state.sprinting.get() && state.sprintTickTimer.get() == 0) {
state.sprintTickTimer.set(sprintTimerTickLength)
} else if (!state.forwardHeldLastTick.get() && Minecraft.getInstance().options.keyUp.isDown() && state.sprintTickTimer.get() != 0) { // If has double tapped
hasDoubleTapped = true
}else if(!state.sprinting.get() && state.sprintTickTimer.get() > 0) {
state.sprintTickTimer.set(state.sprintTickTimer.get() - 1)
} else {
state.sprintTickTimer.set(0)
}
val tryingToSprint = (Minecraft.getInstance().options.keySprint.isDown() && Minecraft.getInstance().options.keyUp.isDown()) || hasDoubleTapped
if (state.stamina.get() <= 0.0f || !Minecraft.getInstance().options.keyUp.isDown()) {
// If stamina runs out or the player is not holding forward then stop sprinting
@@ -157,6 +171,9 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
// If you are trying to sprint and the toggle allows it then start sprinting and disable toggle
state.sprinting.set(true)
}
// Take not of whether forward was held last tick
state.forwardHeldLastTick.set(Minecraft.getInstance().options.keyUp.isDown())
}
fun tickStamina(
@@ -228,7 +245,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
// Normalize the current rotation diff
val rotDiff = Mth.wrapDegrees(driver.yRot - vehicle.yRot).coerceIn(-maxYawDiff,maxYawDiff)
val rotDiffNorm = rotDiff / maxYawDiff
val rotDiffNorm = rotDiff / maxYawDiff//(rotDiff / maxYawDiff).coerceIn(-0.2f, 0.2f)
// Take the square root so that the ride levels out quicker when at lower differences between entity
// y and driver y
@@ -241,7 +258,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
val walkSpeed = getWalkSpeed(vehicle)
val w = max(walkSpeed, vehicle.deltaMovement.horizontalDistance())
val invRelSpeed = (RidingBehaviour.scaleToRange(w, walkSpeed, topSpeed ) - 1.0f) * -1.0f
val turnRate = ((handling.toFloat() / 20.0f) * max(walkHandlingBoost * invRelSpeed, 1.0)).toFloat()
val turnRate = ((handling.toFloat() / 20.0f) * max(walkHandlingBoost * sqrt(abs(invRelSpeed)), 1.0)).toFloat()
// Ensure you only ever rotate as much difference as there is between the angles.
val turnSpeed = turnRate * rotDiffMod
@@ -274,30 +291,24 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalHorse.speedExpr!!)
val walkSpeed = getWalkSpeed(vehicle)
val topSpeed = if(canSprint && state.sprinting.get()) rideTopSpeed else walkSpeed
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalHorse.accelerationExpr!!) * 20.0)
val accelTime = if(state.sprinting.get()) (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalHorse.accelerationExpr!!) * 20.0) else 0.5 * 20.0
val accel = topSpeed / accelTime
var activeInput = false
/******************************************************
* Gather the previous velocity and check for horizontal
* collisions
*****************************************************/
val dmSpeed = vehicle.deltaMovement.length()
val rvSpeed = state.rideVelocity.get().length()
var newVelocity = state.rideVelocity.get() //.normalize().scale(vehicle.deltaMovement.horizontalDistance())
/******************************************************
* Gather the previous velocity and check for horizontal
* collisions
*****************************************************/
// if (dmSpeed > rvSpeed) {
// // align the velocity vector to be in local vehicle space
// newVelocity = vehicle.deltaMovement
// val yawAligned = Matrix3f().rotateY(-vehicle.yRot.toRadians())
// newVelocity = (newVelocity.toVector3f().mul(yawAligned)).toVec3d()
// }
if (vehicle.horizontalCollision) {
newVelocity = newVelocity.normalize().scale(vehicle.deltaMovement.length())
var horizontalVec = Vec3(newVelocity.x, 0.0, newVelocity.z)
horizontalVec = horizontalVec.normalize().scale(min(horizontalVec.length(), 0.3))
newVelocity = Vec3(horizontalVec.x, newVelocity.y, horizontalVec.z)
}
/******************************************************
@@ -373,7 +384,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
state.jumpTicks.set(state.jumpTicks.get() + 1)
}
//Zero out lateral velocity possibly picked up from a controller transition
// Zero out lateral velocity possibly picked up from a controller transition
newVelocity = Vec3(0.0, newVelocity.y, newVelocity.z)
@@ -462,7 +473,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
vehicle: PokemonEntity,
driver: Player
): Float {
return 1.0f
return if (state.sprinting.get()) 1.15f else 1.0f
}
override fun useAngVelSmoothing(
@@ -521,6 +532,14 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
return true
}
override fun maxUpStep(
settings: HorseSettings,
state: HorseState,
vehicle: PokemonEntity
): Float? {
return if (state.inAir.get()) 0.0f else 1.2f
}
override fun getRideSounds(
settings: HorseSettings,
state: HorseState,
@@ -619,6 +638,8 @@ class HorseState : RidingBehaviourState() {
var sprintToggleable = ridingState(false, Side.CLIENT)
var inAir = ridingState(false, Side.CLIENT)
var jumpTicks = ridingState(0, Side.CLIENT)
var sprintTickTimer = ridingState(0, Side.CLIENT)
var forwardHeldLastTick = ridingState(false, Side.CLIENT)
override fun encode(buffer: FriendlyByteBuf) {
super.encode(buffer)
@@ -627,6 +648,8 @@ class HorseState : RidingBehaviourState() {
buffer.writeBoolean(sprintToggleable.get())
buffer.writeBoolean(inAir.get())
buffer.writeInt(jumpTicks.get())
buffer.writeInt(sprintTickTimer.get())
buffer.writeBoolean(forwardHeldLastTick.get())
}
override fun decode(buffer: FriendlyByteBuf) {
@@ -636,6 +659,8 @@ class HorseState : RidingBehaviourState() {
sprintToggleable.set(buffer.readBoolean(), forced = true)
inAir.set(buffer.readBoolean(), forced = true)
jumpTicks.set(buffer.readInt(), forced = true)
sprintTickTimer.set(buffer.readInt(), forced = true)
forwardHeldLastTick.set(buffer.readBoolean(), forced = true)
}
override fun reset() {
@@ -645,6 +670,8 @@ class HorseState : RidingBehaviourState() {
sprintToggleable.set(false, forced = true)
inAir.set(false, forced = true)
jumpTicks.set(0, forced = true)
sprintTickTimer.set(0, forced = true)
forwardHeldLastTick.set(false, forced = true)
}
override fun copy() = HorseState().also {
@@ -655,6 +682,8 @@ class HorseState : RidingBehaviourState() {
it.sprintToggleable.set(this.sprintToggleable.get(), forced = true)
it.inAir.set(this.inAir.get(), forced = true)
it.jumpTicks.set(this.jumpTicks.get(), forced = true)
it.sprintTickTimer.set(this.sprintTickTimer.get(), forced = true)
it.forwardHeldLastTick.set(this.forwardHeldLastTick.get(), forced = true)
}
override fun shouldSync(previous: RidingBehaviourState): Boolean {
@@ -12,6 +12,7 @@ package com.cobblemon.mod.common.api.riding.sound
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeBehaviour
import com.cobblemon.mod.common.api.riding.behaviour.types.composite.CompositeState
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getIsSubmerged
import com.cobblemon.mod.common.util.resolveDouble
import net.minecraft.client.Minecraft
import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance
@@ -65,6 +66,21 @@ class RideLoopSound(val ride: PokemonEntity, val soundSettings: RideSoundSetting
return
}
// Mute the sound if it's not meant to play for the passenger
if (this.isPassenger && !this.soundSettings.playForPassengers) {
this.volume = 0.0f
return
}
// Mute sounds when submerged unless they support underwater sounds, underwater sounds don't play above water
if (this.ride.getIsSubmerged() && !this.soundSettings.submerged) {
this.volume = 0.0f
return
} else if (!this.ride.getIsSubmerged() && this.soundSettings.submerged) {
this.volume = 0.0f
return
}
// Perform data driven pitch and volume calculation
this.volume = ((soundSettings.volumeExpr.let { ride.runtime.resolveDouble(it) })).toFloat()
this.volume *= this.fade
@@ -27,7 +27,9 @@ data class RideSoundSettings(
val soundLocation: ResourceLocation,
@SerializedName("volumeExpr") private val _volumeExpr: Expression? = "1.0".asExpression(),
@SerializedName("pitchExpr") private val _pitchExpr: Expression? = "1.0".asExpression(),
val playForPassengers: Boolean = true,
val playForNonPassengers: Boolean = false,
val submerged: Boolean = false,
val muffleEnabled: Boolean = false,
@SerializedName("attenuationModel") private val _attenuationModel: RideAttenuationModel? = RideAttenuationModel.NONE
): Encodable {
@@ -46,7 +48,9 @@ data class RideSoundSettings(
buffer.writeResourceLocation(soundLocation)
buffer.writeExpression(volumeExpr)
buffer.writeExpression(pitchExpr)
buffer.writeBoolean(playForPassengers)
buffer.writeBoolean(playForNonPassengers)
buffer.writeBoolean(submerged)
buffer.writeBoolean(muffleEnabled)
buffer.writeEnum(attenuationModel)
}
@@ -57,7 +61,9 @@ data class RideSoundSettings(
val soundLocation = buffer.readResourceLocation()
val volumeExpr = buffer.readExpression()
val pitchExpr = buffer.readExpression()
val playForPassengers = buffer.readBoolean()
val playForNonPassengers = buffer.readBoolean()
val submerged = buffer.readBoolean()
val muffleEnabled = buffer.readBoolean()
val attenuationModel = buffer.readEnum(RideAttenuationModel::class.java)
@@ -65,7 +71,9 @@ data class RideSoundSettings(
soundLocation,
volumeExpr,
pitchExpr,
playForPassengers,
playForNonPassengers,
submerged,
muffleEnabled,
attenuationModel
)
@@ -44,11 +44,7 @@ abstract class SpawnAction<R>(
spawnablePosition.applyInfluences { it.affectAction(this) }
val result = run()
if (result != null) {
future.complete(result)
} else {
future.completeExceptionally(Exception("Nothing was spawned."))
}
future.complete(result)
return result
}
@@ -61,7 +61,9 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val baitEVStat = effects.firstOrNull { it.type == Effects.EV }?.subcategory?.path?.let { Stats.getStat(it) }
if (detailSpecies != null && baitEVStat != null) {
val evYieldValue = detailSpecies.evYield[baitEVStat]?.toFloat() ?: 0f
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
val evYieldValue = formData.evYield[baitEVStat]?.toFloat() ?: 0f
return when {
evYieldValue > 0 -> {
markUsed()
@@ -83,7 +85,9 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val baitTypingEffect = baitEffect?.subcategory?.path?.let { ElementalTypes.get(it) }
if (detailSpecies != null && baitTypingEffect != null) {
val isMatchingType = detailSpecies.types.contains(baitTypingEffect)
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
val isMatchingType = formData.types.contains(baitTypingEffect)
return when {
isMatchingType -> {
markUsed()
@@ -100,6 +104,9 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
val detailSpecies = detail.pokemon.species?.let { PokemonSpecies.getByName(it) }
if (detailSpecies != null) {
val detailAspects = detail.pokemon.aspects
val formData = detailSpecies.getForm(detailAspects)
// Collect all the egg group effects
val eggGroupEffects = effects.filter { it.type == Effects.EGG_GROUP }
@@ -111,7 +118,7 @@ open class SpawnBaitInfluence(val effects: List<SpawnBait.Effect>, val onUsed: (
LOGGER.warn("Unknown egg group identifier: $effectEggGroupKey")
return@firstOrNull false
}
detailSpecies.eggGroups.contains(eggGroup)
formData.eggGroups.contains(eggGroup)
}
if (matchingEffect != null) {
@@ -8,30 +8,58 @@
package com.cobblemon.mod.common.api.stats
import com.cobblemon.mod.common.Cobblemon
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.resources.ResourceLocation
import net.minecraft.stats.StatFormatter
object CobblemonStats {
val stats = mutableMapOf<String, ResourceLocation>()
val stats = mutableMapOf<String, CobblemonStat>()
var CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "captured") //makeCustomStat("captured", StatFormatter.DEFAULT)
val SHINIES_CAPTURED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "shinies_captured") //makeCustomStat("shinies_captured", StatFormatter.DEFAULT)
val RELEASED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "released") //makeCustomStat("released", StatFormatter.DEFAULT)
val EVOLVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "evolved") //makeCustomStat("evolved", StatFormatter.DEFAULT)
val LEVEL_UP: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "level_up") //makeCustomStat("level_up", StatFormatter.DEFAULT)
val BATTLES_WON: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_won") //makeCustomStat("battles_won", StatFormatter.DEFAULT)
val BATTLES_LOST: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_lost") //makeCustomStat("battles_lost", StatFormatter.DEFAULT)
val BATTLES_FLED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_fled") //makeCustomStat("battles_fled", StatFormatter.DEFAULT)
val BATTLES_TOTAL: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "battles_total") //makeCustomStat("battles_total", StatFormatter.DEFAULT)
val DEX_ENTRIES: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "dex_entries") //makeCustomStat("dex_entries", StatFormatter.DEFAULT)
val EGGS_COLLECTED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_collected") //makeCustomStat("eggs_collected", StatFormatter.DEFAULT)
val EGGS_HATCHED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "eggs_hatched") //makeCustomStat("eggs_hatched", StatFormatter.DEFAULT)
val TRADED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "traded") //makeCustomStat("traded", StatFormatter.DEFAULT)
val FOSSILS_REVIVED: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "fossils_revived") //makeCustomStat("fossils_revived", StatFormatter.DEFAULT)
val TIMES_RIDDEN: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "times_ridden")
val ROD_CASTS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "rod_casts")
val REEL_INS: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "reel_ins")
val POKEMON_INTERACTED_WITH: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", "pokemon_interacted_with") //makeCustomStat("pokemon_interacted_with", StatFormatter.DEFAULT)
//TODO block, stats (interact, gimmi), riding (styles?)
@JvmField
var CAPTURED: CobblemonStat = CobblemonStat("captured")
@JvmField
val SHINIES_CAPTURED: CobblemonStat = CobblemonStat("shinies_captured")
@JvmField
val RELEASED: CobblemonStat = CobblemonStat("released")
@JvmField
val EVOLVED: CobblemonStat = CobblemonStat("evolved")
@JvmField
val LEVEL_UP: CobblemonStat = CobblemonStat("level_up")
@JvmField
val BATTLES_WON: CobblemonStat = CobblemonStat("battles_won")
@JvmField
val BATTLES_LOST: CobblemonStat = CobblemonStat("battles_lost")
@JvmField
val BATTLES_FLED: CobblemonStat = CobblemonStat("battles_fled")
@JvmField
val BATTLES_TOTAL: CobblemonStat = CobblemonStat("battles_total")
@JvmField
val DEX_ENTRIES: CobblemonStat = CobblemonStat("dex_entries")
@JvmField
val EGGS_COLLECTED: CobblemonStat = CobblemonStat("eggs_collected")
@JvmField
val EGGS_HATCHED: CobblemonStat = CobblemonStat("eggs_hatched")
@JvmField
val TRADED: CobblemonStat = CobblemonStat("traded")
@JvmField
val FOSSILS_REVIVED: CobblemonStat = CobblemonStat("fossils_revived")
@JvmField
val TIMES_RIDDEN: CobblemonStat = CobblemonStat("times_ridden")
@JvmField
val ROD_CASTS: CobblemonStat = CobblemonStat("rod_casts")
@JvmField
val REEL_INS: CobblemonStat = CobblemonStat("reel_ins")
@JvmField
val POKEMON_INTERACTED_WITH: CobblemonStat = CobblemonStat("pokemon_interacted_with")
@JvmField
val RIDING_LAND: CobblemonStat = CobblemonStat("riding_land", StatFormatter.DISTANCE)
@JvmField
val RIDING_AIR: CobblemonStat = CobblemonStat("riding_air", StatFormatter.DISTANCE)
@JvmField
val RIDING_LIQUID: CobblemonStat = CobblemonStat("riding_liquid", StatFormatter.DISTANCE)
//TODO block, stats (interact, gimmi)
fun registerStats() {
stats["captured"] = CAPTURED
@@ -52,5 +80,22 @@ object CobblemonStats {
stats["rod_casts"] = ROD_CASTS
stats["reel_ins"] = REEL_INS
stats["pokemon_interacted_with"] = POKEMON_INTERACTED_WITH
stats["riding_land"] = RIDING_LAND
stats["riding_air"] = RIDING_AIR
stats["riding_liquid"] = RIDING_LIQUID
}
@JvmStatic
fun getStat(cobblemonStat: CobblemonStat) : ResourceLocation {
val resourceLocation = cobblemonStat.resourceLocation
val stat = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation)
if (stat == null) {
Cobblemon.LOGGER.error("Could not find stat with id {}", resourceLocation)
}
return stat ?: throw NullPointerException("Could not find stat with id $resourceLocation")
}
data class CobblemonStat(val path: String, val formatter: StatFormatter = StatFormatter.DEFAULT) {
val resourceLocation: ResourceLocation = ResourceLocation.fromNamespaceAndPath("cobblemon", path);
}
}
@@ -88,7 +88,6 @@ abstract class OneToOneFileStoreAdapter<S>(
result
}
else {
storeClass.getConstructor(UUID::class.java).newInstance(uuid)
var result = storeClass.getConstructor(UUID::class.java).newInstance(uuid)
save(storeClass, uuid, serialize(result, registryAccess))
oldFile.delete()
@@ -105,12 +105,18 @@ data class BattleFormat(
}
fun toFormatJSON(): String {
/*
Bag clause does not exist in showdown as a rule because showdown simply has no concept of a 'bag'.
If we try sending it, the battle will error. So this simply omits that from ever getting sent.
If we ever find a case where we are doing this for more than just bag clause, we should make a proper abstraction.
*/
val rulesToSendToShowdown = ruleSet.filter { it != BattleRules.BAG_CLAUSE }
return """
{
"mod": "$mod",
"gameType": "${battleType.name}",
"gen": $gen,
"ruleset": [${ruleSet.joinToString { "\"$it\"" }}],
"ruleset": [${rulesToSendToShowdown.joinToString { "\"$it\"" }}],
"effectType": "Format"
}
""".trimIndent().replace("\n", "")
@@ -12,6 +12,7 @@ object BattleRules {
const val OBTAINABLE = "Obtainable"
const val PAST = "+Past"
const val UNOBTAINABLE = "+Unobtainable"
const val BAG_CLAUSE = "Bag Clause"
const val TEAM_PREVIEW = "Team Preview"
const val ENDLESS_BATTLE_CLAUSE = "Endless Battle Clause"
const val CANCEL_MOD = "Cancel Mod"
@@ -289,6 +289,8 @@ class ShowdownMoveset {
var canDynamax = false
var maxMoves: List<InBattleGimmickMove?>? = null
var canTerastallize: String? = null
/** This stores a list of gimmicks that have already been used this turn by a previous Pokemon, but the full turn has not been processed (ie. double battles). */
val pendingGimmickUsedThisTurn = mutableListOf<Gimmick>()
fun saveToBuffer(buffer: RegistryFriendlyByteBuf) {
buffer.writeSizedInt(IntSize.U_BYTE, moves.size)
@@ -31,6 +31,7 @@ import kotlin.collections.associateWith
import kotlin.collections.partition
import kotlin.math.absoluteValue
/**
* AI that tries to choose the best move for the given situations. Based off of the Pokemon Trainer Tournament Simulator Github
* https://github.com/cRz-Shadows/Pokemon_Trainer_Tournament_Simulator/blob/main/pokemon-showdown/sim/examples/Simulation-test-1.ts#L330
@@ -271,6 +272,11 @@ class StrongBattleAI(skill: Int) : BattleAI {
}
activeTrackerPokemon.firstTurn = false
// If HP is below 30% and not switching out, always use the most damaging move
if (activeTrackerPokemon.currentHpPercent < 0.3 && !shouldSwitchOut(aiSide, battle, activeBattlePokemon, moveset)) {
findAndUseMostDamagingMove(activeBattlePokemon, activeTrackerPokemon, opponents, availableMoves, moveset, battle, aiSide)?.let { return it }
}
// Decision-making based on move availability and switch-out condition
if (!shouldSwitchOut(aiSide, battle, activeBattlePokemon, moveset)) {
val nRemainingMons = activeTracker.alliedSide.actors.sumOf { actor -> actor.party.filter { it.currentHpPercent > 0 }.size }
@@ -521,6 +527,19 @@ class StrongBattleAI(skill: Int) : BattleAI {
val opponentActiveTracker = activeTracker.opponentSide.activePokemon
val opponentSpeedEstimations = opponentActiveTracker.map { statEstimationActive(it, Stats.SPEED) }
// Only switch if a switch-in is significantly better than the current Pokémon
val currentScore = estimateMatchup(activeBattlePokemon, side, battle)
val bestSwitchScore = availableSwitches.maxOfOrNull { estimateMatchup(activeBattlePokemon, side, battle, it) } ?: currentScore
val improvementThreshold = currentScore.absoluteValue * 0.25 + 2
if (bestSwitchScore <= currentScore + improvementThreshold) {
return false
}
if(bestSwitchScore < 1) {
return false
}
// todo add some way to keep track of the player's boosting to see if it needs to switch out to something that can stop it
// if slower speed stat than the opposing pokemon and HP is less than 20% don't switch out
@@ -548,6 +567,8 @@ class StrongBattleAI(skill: Int) : BattleAI {
if (availableSwitches.isEmpty() || availableSwitches.none { estimateMatchup(activeBattlePokemon, side, battle, it) > 0 })
return false
// ...and a 'good' reason to switch out
if (opponentActiveTracker.any { it.boosts.getOrDefault(Stats.ACCURACY, 0) <= accuracySwitchThreshold } ||
opponentActiveTracker.any { it.boosts.getOrDefault(Stats.DEFENCE, 0) <= -3 } ||
@@ -114,7 +114,14 @@ class ActivateInstruction(val instructionSet: InstructionSet, val message: Battl
}
"maxguard", "protect" -> battleLang("activate.protect", pokemonName)
"shadowforce", "hyperspacefury", "hyperspacehole" -> battleLang("activate.phantomforce", pokemonName)
else -> battleLang("activate.${effect.id}", pokemonName, sourceName, extraEffect)
else -> {
val msgVariant = message.optionalArgument("msg")
if (msgVariant != null) {
battleLang("activate.${effect.id}.$msgVariant", pokemonName, sourceName, extraEffect)
} else {
battleLang("activate.${effect.id}", pokemonName, sourceName, extraEffect)
}
}
}
battle.broadcastChatMessage(lang)
//We check holds here so the chat msg + particle effect happen more concurrently, instead of sequentially
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.util.isInBattle
import com.cobblemon.mod.common.util.playSoundServer
import com.cobblemon.mod.common.util.toVec3d
import com.cobblemon.mod.common.util.voxelShape
import com.cobblemon.mod.common.util.rotateShape
import com.mojang.serialization.MapCodec
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
@@ -71,10 +72,10 @@ class PastureBlock(settings: Properties): BaseEntityBlock(settings), SimpleWater
private val WEST_AABB_TOP = buildCollider(top = true, Direction.WEST)
private val EAST_AABB_TOP = buildCollider(top = true, Direction.EAST)
private val SOUTH_AABB_BOTTOM = buildCollider(top = false, Direction.SOUTH)
private val NORTH_AABB_BOTTOM = buildCollider(top = false, Direction.NORTH)
private val WEST_AABB_BOTTOM = buildCollider(top = false, Direction.WEST)
private val EAST_AABB_BOTTOM = buildCollider(top = false, Direction.EAST)
private val SOUTH_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.SOUTH, EAST_AABB_BOTTOM)
private val NORTH_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.NORTH, EAST_AABB_BOTTOM)
private val WEST_AABB_BOTTOM = rotateShape(Direction.EAST, Direction.WEST, EAST_AABB_BOTTOM)
private fun buildCollider(top: Boolean, direction: Direction): VoxelShape {
if (top) {
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.block
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.entity.MoLangScriptingEntity
import com.cobblemon.mod.common.util.isServerSide
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.dispenser.DispenseItemBehavior
@@ -263,21 +264,36 @@ class SaccharineLeafBlock(settings: Properties) : LeavesBlock(settings) {
val isGlassBottle = itemStack.`is`(Items.GLASS_BOTTLE)
val isHoneyBottle = itemStack.`is`(Items.HONEY_BOTTLE)
if (isGlassBottle && !isAtMinAge(state)) {
if (isGlassBottle && isAtMaxAge(state)) {
if (level.isClientSide) return ItemInteractionResult.SUCCESS
// Decrement stack if not in creative mode
itemStack.consume(1, player)
// Give player honey bottle for now
player.addItem(Items.HONEY_BOTTLE.defaultInstance)
// Give player a honey bottle
if (stack.isEmpty) {
// Replace the consumed empty bottle with a honey bottle
player.setItemInHand(hand, ItemStack(Items.HONEY_BOTTLE));
} else {
player.addItem(Items.HONEY_BOTTLE.defaultInstance)
}
level.playSound(null, pos, SoundEvents.BOTTLE_FILL, SoundSource.BLOCKS)
level.setBlock(pos, state.setValue(AGE, 0), UPDATE_CLIENTS)
level.gameEvent(null, GameEvent.BLOCK_CHANGE, pos)
return ItemInteractionResult.SUCCESS
} else if (isHoneyBottle && !isAtMaxAge(state)) {
if (level.isClientSide) return ItemInteractionResult.SUCCESS
// Decrement stack if not in creative mode
itemStack.consume(1, player)
player.addItem(Items.GLASS_BOTTLE.defaultInstance)
if (!player.isCreative) {
itemStack.consume(1, player)
if (stack.isEmpty) {
// Replace the consumed honey bottle with an empty bottle
player.setItemInHand(hand, ItemStack(Items.GLASS_BOTTLE));
} else {
player.addItem(Items.GLASS_BOTTLE.defaultInstance)
}
}
level.playSound(null, pos, SoundEvents.HONEY_BLOCK_PLACE, SoundSource.BLOCKS)
level.setBlock(pos, state.setValue(AGE, 2), UPDATE_CLIENTS)
@@ -11,10 +11,11 @@ package com.cobblemon.mod.common.client.battle
import com.cobblemon.mod.common.CobblemonNetwork
import com.cobblemon.mod.common.api.battles.model.actor.ActorType
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.battles.BattleFormat
import com.cobblemon.mod.common.battles.ForcePassActionResponse
import com.cobblemon.mod.common.battles.MoveActionResponse
import com.cobblemon.mod.common.battles.PassActionResponse
import com.cobblemon.mod.common.battles.ShowdownMoveset
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
@@ -61,8 +62,15 @@ class ClientBattle(
if (index != -1) {
while(index < pendingActionRequests.size) {
val request = pendingActionRequests[index]
if (request.response != PassActionResponse && request.response !is ForcePassActionResponse)
if (request.response != PassActionResponse && request.response !is ForcePassActionResponse) {
val response = request.response
// If we're cancelling a turn that used a gimmick, we re-enable the ability for that gimmick to be used.
if (response is MoveActionResponse && response.gimmickID != null) {
val gimmick = ShowdownMoveset.Gimmick.entries.find { it.id == response.gimmickID }
pendingActionRequests.forEach { it.moveSet?.pendingGimmickUsedThisTurn?.remove(gimmick) }
}
request.response = null
}
index++
}
}
@@ -68,7 +68,7 @@ class BattleMoveSelection(
var moveTiles = baseTiles
val backButton = BattleBackButton(x - 11F, Minecraft.getInstance().window.guiScaledHeight - 22F)
val gimmickButtons = moveSet.getGimmicks().mapIndexed { index, gimmick ->
val gimmickButtons = moveSet.getGimmicks().filter { it !in moveSet.pendingGimmickUsedThisTurn }.mapIndexed { index, gimmick ->
val initOff = BattleBackButton.WIDTH * 0.65F
val xOff = initOff + BattleGimmickButton.SPACING * index
BattleGimmickButton.create(gimmick, this, backButton.x + xOff, backButton.y)
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.battles.InBattleGimmickMove
import com.cobblemon.mod.common.battles.InBattleMove
import com.cobblemon.mod.common.battles.MoveActionResponse
import com.cobblemon.mod.common.battles.ShowdownMoveset
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.battle.ActiveClientBattlePokemon
@@ -127,7 +128,7 @@ class BattleTargetSelection(
private val isMultiTarget = multiTargetList?.firstOrNull { it.getPNX() == target.getPNX() } != null
private val isCurrentPokemon = request.activePokemon.battlePokemon?.uuid == target.battlePokemon!!.uuid
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget)
open val response: MoveActionResponse get() = MoveActionResponse(targetSelection.move.id, responseTarget, gimmickID)
val state = FloatingState()
open val selectable: Boolean get() = isMultiTarget || (responseTarget != null)
@@ -311,6 +312,13 @@ class BattleTargetSelection(
fun onClick() {
if (!selectable) return
targetSelection.playDownSound(Minecraft.getInstance().soundManager)
// If a gimmick is used, remove the ability to use it on any pending action requests ahead of it
if (response.gimmickID != null) {
val gimmick = ShowdownMoveset.Gimmick.entries.first { it.id == response.gimmickID }
CobblemonClient.battle?.pendingActionRequests?.forEach {
it.moveSet?.pendingGimmickUsedThisTurn?.add(gimmick)
}
}
targetSelection.battleGUI.selectAction(targetSelection.request, response)
}
}
@@ -592,6 +592,10 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
}
private fun switchForm(nextIndex: Boolean) {
if (visibleForms.isEmpty() || currentEntry == null) {
return
}
selectedPoseIndex = 0
if (nextIndex) {
@@ -602,6 +606,8 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
else selectedFormIndex = visibleForms.lastIndex
}
selectedFormIndex = selectedFormIndex.coerceIn(0, visibleForms.lastIndex)
setupButtons(currentEntry!!, visibleForms[selectedFormIndex])
updateAspects()
}
@@ -143,18 +143,18 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
}
private fun canAttemptDismount(player: LocalPlayer, selectedPartyPokemon: Pokemon?): Boolean {
if (player.vehicle !is PokemonEntity) return false
val vehicle = player.vehicle as PokemonEntity
if (player != vehicle.controllingPassenger) {
return true
}
val vehicle = player.vehicle as? PokemonEntity ?: return false
if (player != vehicle.controllingPassenger) return true
val isAirRide = vehicle.ridingController?.context?.style == RidingStyle.AIR
val hasLandRide = vehicle.rideProp.behaviours?.get(RidingStyle.LAND) != null
return if (isAirRide && hasLandRide) {
false
} else {
vehicle.pokemon.uuid == selectedPartyPokemon?.uuid
if (!Cobblemon.config.enableInFlightDismounting && isAirRide && hasLandRide) {
return false
}
return vehicle.pokemon.uuid == selectedPartyPokemon?.uuid
}
private fun isRidingPokemon(player: LocalPlayer, ignoreControlling: Boolean = false): Boolean {
@@ -16,8 +16,8 @@ import com.mojang.blaze3d.platform.InputConstants
object RidingFreelookBinding : CobblemonBlockingKeyBinding(
"key.cobblemon.ridingfreelook",
InputConstants.Type.MOUSE,
InputConstants.MOUSE_BUTTON_MIDDLE,
InputConstants.Type.KEYSYM,
InputConstants.KEY_LALT,
KeybindCategories.COBBLEMON_CATEGORY
) {
override fun onTick() {
@@ -0,0 +1,27 @@
/*
* 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.net.data
import com.cobblemon.mod.common.api.interaction.PokemonInteractions
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
import com.cobblemon.mod.common.net.messages.client.data.PokemonInteractionsSyncPacket
import net.minecraft.client.Minecraft
object PokemonInteractionsSyncHandler : ClientNetworkPacketHandler<PokemonInteractionsSyncPacket> {
override fun handle(
packet: PokemonInteractionsSyncPacket,
client: Minecraft,
) {
PokemonInteractions.speciesInteractions.clear()
PokemonInteractions.speciesInteractions.addAll(packet.speciesInteractions)
PokemonInteractions.generalInteractions.clear()
PokemonInteractions.generalInteractions.addAll(packet.generalInteractions)
}
}
@@ -8,6 +8,8 @@
package com.cobblemon.mod.common.client.persisted
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Cobblemon.LOGGER
import com.cobblemon.mod.common.config.CobblemonConfig
import java.io.BufferedReader
import java.io.BufferedWriter
@@ -31,7 +33,14 @@ object ClientPersistedData {
fun readSnapshotsData() : SnapshotAcknowledgementData? {
if (snapshotsPath.exists()) {
BufferedReader(InputStreamReader(FileInputStream(snapshotsPath.toFile()))).use { reader ->
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
try {
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
} catch (exception: Exception) {
LOGGER.error("Failed to load snapshots.json... Resetting File")
val data = SnapshotAcknowledgementData(Cobblemon.VERSION, false)
writeSnapshotsData(data)
return data
}
}
}
@@ -46,16 +55,23 @@ object ClientPersistedData {
fun readRidingPerspectivesData() : RidingPerspectiveData? {
if (ridingPerspectivesPath.exists()) {
BufferedReader(InputStreamReader(FileInputStream(ridingPerspectivesPath.toFile()))).use { reader ->
return gson.fromJson(reader, RidingPerspectiveData::class.java)
try {
return gson.fromJson(reader, RidingPerspectiveData::class.java)
} catch (exception: Exception) {
LOGGER.error("Failed to load riding_perspectives.json... Resetting File")
val data = RidingPerspectiveData()
saveRidingPerspectivesData(data)
return data
}
}
}
return null
}
fun saveRidingPerspectivesData() {
fun saveRidingPerspectivesData(data: RidingPerspectiveData) {
ridingPerspectivesPath.toFile().parentFile.mkdirs()
BufferedWriter(FileWriter(ridingPerspectivesPath.toFile())).use { writer -> gson.toJson(ridingPerspectives, writer) }
BufferedWriter(FileWriter(ridingPerspectivesPath.toFile())).use { writer -> gson.toJson(data, writer) }
}
data class SnapshotAcknowledgementData(val version: String, val dontShowAgain: Boolean)
@@ -64,7 +80,7 @@ object ClientPersistedData {
) {
fun updatePerspective(key: ResourceLocation, cameraType: CameraType) {
perspectives[key] = cameraType
saveRidingPerspectivesData()
saveRidingPerspectivesData(this)
}
}
}
@@ -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.client.render.models.blockbench.pokemon.gen9
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.ModelPartTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.isBattling
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class TinkatinkModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BimanualFrame {
override val rootPart = root.registerChildWithAllChildren("tinkatink")
override val head = getPart("head")
override val rightArm = getPart("arm_right")
override val leftArm = getPart("arm_left")
override val rightLeg = getPart("leg_right")
override val leftLeg = getPart("leg_left")
override var portraitScale = 2.0F
override var portraitTranslation = Vec3(0.0, -1.01, 0.0)
override var profileScale = 1.0F
override var profileTranslation = Vec3(0.0, 0.25, 0.0)
lateinit var standing: Pose
lateinit var walking: Pose
lateinit var sleep: Pose
lateinit var battleidle: Pose
lateinit var shoulderLeft: Pose
lateinit var shoulderRight: Pose
val shoulderOffset = 1
override val cryAnimation = CryProvider { bedrockStateful("tinkatink", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("tinkatink", "blink") }
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("tinkatink", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
condition = { !it.isBattling },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "ground_idle")
)
)
walking = registerPose(
poseName = "walking",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "battle_idle")
)
)
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
quirks = arrayOf(blink),
condition = { !it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "shoulder_left")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
quirks = arrayOf(blink),
condition = { !it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatink", "shoulder_right")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, -shoulderOffset)
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walking, battleidle, sleep)) bedrockStateful("tinkatink", "faint") else null
}
@@ -1,87 +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.render.models.blockbench.pokemon.gen9
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BimanualFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BipedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.util.isBattling
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class TinkatuffModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BimanualFrame {
override val rootPart = root.registerChildWithAllChildren("tinkatuff")
override val head = getPart("head")
override val rightArm = getPart("arm_right")
override val leftArm = getPart("arm_left")
override val rightLeg = getPart("leg_right")
override val leftLeg = getPart("leg_left")
override var portraitScale = 1.9F
override var portraitTranslation = Vec3(0.0, -0.41, 0.0)
override var profileScale = 0.9F
override var profileTranslation = Vec3(0.0, 0.4, 0.0)
lateinit var standing: Pose
lateinit var walking: Pose
lateinit var sleep: Pose
lateinit var battleidle: Pose
override val cryAnimation = CryProvider { bedrockStateful("tinkatuff", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("tinkatuff", "blink") }
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("tinkatuff", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
transformTicks = 10,
condition = { !it.isBattling },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatuff", "ground_idle")
)
)
walking = registerPose(
poseName = "walking",
poseTypes = PoseType.MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatuff", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("tinkatuff", "battle_idle")
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walking, battleidle, sleep)) bedrockStateful("tinkatuff", "faint") else null
}
@@ -477,8 +477,6 @@ object VaryingModelRepository {
inbuilt("illumise", ::IllumiseModel)
inbuilt("yamper", ::YamperModel)
inbuilt("boltund", ::BoltundModel)
inbuilt("tinkatink", ::TinkatinkModel)
inbuilt("tinkatuff", ::TinkatuffModel)
inbuilt("fuecoco", :: FuecocoModel)
inbuilt("crocalor", :: CrocalorModel)
inbuilt("skeledirge", :: SkeledirgeModel)
@@ -206,7 +206,7 @@ fun generateAdditionalRideBoostsTooltip(stack: ItemStack): MutableList<Component
val resultLines = mutableListOf<Component>()
resultLines.add(rideBoostSeasoningHeader)
for ((stat, value) in boosts) {
for ((stat, value) in boosts.toSortedMap()) {
val statName = stat.displayName.also { it.style = it.style.withColor(stat.flavour.colour) }
val valueText = if (value < 0) {
Component.literal("$value").red()
@@ -329,6 +329,9 @@ class CobblemonConfig {
@CobblemonConfigField(Category.Riding, lang = "remember_riding_camera", CLIENT)
var rememberRidingCamera = false
@CobblemonConfigField(Category.Riding, lang = "enable_in_flight_dismounting", CLIENT)
var enableInFlightDismounting = false
@CobblemonConfigField(Category.Debug, lang = "enable_debug_keys", CLIENT)
var enableDebugKeys = false
@@ -39,15 +39,16 @@ class FollowWalkTargetTask(
private var lookTargetPos: BlockPos? = null
private var speed = 0f
override fun checkExtraStartConditions(arg: ServerLevel, arg2: PathfinderMob): Boolean {
override fun checkExtraStartConditions(level: ServerLevel, entity: PathfinderMob): Boolean {
if (this.pathUpdateCountdownTicks > 0) {
--this.pathUpdateCountdownTicks
return false
} else {
val brain = arg2.brain
val brain = entity.brain
val walkTarget = brain.getMemory(MemoryModuleType.WALK_TARGET).get()
val hasReached = this.hasReached(arg2, walkTarget)
if (!hasReached && this.hasFinishedPath(arg2, walkTarget, arg.gameTime)) {
val hasReached = this.hasReached(entity, walkTarget)
resetPathUpdateCountdownTicks(entity)
if (!hasReached && this.hasFinishedPath(entity, walkTarget, level.gameTime)) {
this.lookTargetPos = walkTarget.target.currentBlockPosition()
return true
} else {
@@ -61,6 +62,10 @@ class FollowWalkTargetTask(
}
}
fun resetPathUpdateCountdownTicks(entity: PathfinderMob) {
pathUpdateCountdownTicks = entity.random.nextInt(20) + 20
}
override fun canStillUse(arg: ServerLevel, arg2: PathfinderMob, l: Long): Boolean {
if (this.path != null && this.lookTargetPos != null) {
val optional = arg2.brain.getMemory(MemoryModuleType.WALK_TARGET)
@@ -75,7 +80,7 @@ class FollowWalkTargetTask(
override fun stop(world: ServerLevel, entity: PathfinderMob, l: Long) {
val walkTarget = entity.brain.getMemory(MemoryModuleType.WALK_TARGET).orElse(null)
if (walkTarget != null && !this.hasReached(entity, walkTarget) && entity.navigation.isStuck) {
this.pathUpdateCountdownTicks = world.getRandom().nextInt(40)
resetPathUpdateCountdownTicks(entity)
}
entity.navigation.stop()
@@ -269,9 +269,6 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
// If we can fly and we're airborne, return the current Y position
return vec.y
}
if (world.getBlockState(blockPos).block == CobblemonBlocks.SACCHARINE_LEAVES && pather.canPathThroughSaccLeaves()) {
return vec.y + 0.5
}
return if ((canFloat()) && blockGetter.getFluidState(blockPos).`is`(FluidTags.WATER)) vec.y + 0.5 else super.getGroundY(vec)
}
@@ -802,13 +802,14 @@ class PokeRodFishingBobberEntity(type: EntityType<out PokeRodFishingBobberEntity
spawnAction.complete()
val result = spawnAction.future
if (result.isCompletedExceptionally) {
val resultingSpawn = result.get()
if (resultingSpawn == null) {
noBite(player)
return false
}
var spawnedPokemon: PokemonEntity? = null
val resultingSpawn = result.get()
if (resultingSpawn is EntitySpawnResult) {
for (entity in resultingSpawn.entities) {
@@ -547,6 +547,11 @@ open class PokemonEntity(
ifRidingAvailable { _, _, state -> pokemon.rideStamina = state.stamina.get() }
ridingController?.context?.state?.reset()
ridingAnimationData.clear()
// reset riding orientation
if (this is OrientationControllable) {
this.orientationController.reset()
}
}
}
@@ -1203,14 +1208,13 @@ open class PokemonEntity(
}
}
if (hand == InteractionHand.MAIN_HAND && player is ServerPlayer) {
if (player.isShiftKeyDown) {
if (hand == InteractionHand.MAIN_HAND) {
if (player.isShiftKeyDown && player is ServerPlayer) {
showInteractionWheel(player, itemStack)
return InteractionResult.sidedSuccess(level().isClientSide)
}
else if (pokemon.getOwnerPlayer() == player) {
// TODO #105
if (this.attemptItemInteraction(player, player.getItemInHand(hand))) return InteractionResult.SUCCESS
else if (this.ownerUUID == player.uuid && this.attemptItemInteraction(player, player.getItemInHand(hand))) {
return InteractionResult.sidedSuccess(level().isClientSide)
}
}
@@ -1277,7 +1281,7 @@ open class PokemonEntity(
}
override fun shouldBeSaved(): Boolean {
if (ownerUUID == null && !pokemon.isNPCOwned() && (Cobblemon.config.savePokemonToWorld || isPersistenceRequired || this.pokemon.canDropHeldItem)) {
if (ownerUUID == null && !pokemon.isNPCOwned() && (Cobblemon.config.savePokemonToWorld || isPersistenceRequired)) {
CobblemonEvents.POKEMON_ENTITY_SAVE_TO_WORLD.postThen(PokemonEntitySaveToWorldEvent(this)) {
return true
}
@@ -1386,18 +1390,24 @@ open class PokemonEntity(
return bagItemLike.handleInteraction(player, battlePokemon, stack)
}
if (player !is ServerPlayer || this.isBusy) {
if (this.isBusy) {
return false
}
val interaction = PokemonInteractions.findInteraction(this)
if (interaction != null && !pokemon.isOnInteractionCooldown(interaction.grouping)) {
interaction.effects.forEach { it.applyEffect(this, player) }
pokemon.interactionCooldowns.put(interaction.grouping, runtime.resolveInt(interaction.cooldown))
if (player is ServerPlayer) {
interaction.effects.forEach { it.applyEffect(this, player) }
pokemon.interactionCooldowns.put(interaction.grouping, runtime.resolveInt(interaction.cooldown))
}
return true
}
if (player !is ServerPlayer) {
return false
}
// Evolution item logic
if (pokemon.getOwnerPlayer() == player) {
val context = ItemInteractionEvolution.ItemInteractionContext(stack, player.level())
@@ -10,8 +10,11 @@ package com.cobblemon.mod.common.entity.pokemon.ai.sensors
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.util.getMemorySafely
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.Mob
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.NearestVisibleLivingEntities
import net.minecraft.world.entity.ai.sensing.Sensor
@@ -28,8 +31,17 @@ class DefendOwnerSensor : Sensor<PokemonEntity>(10) {
}
private fun setNearestAttacker(entity: PokemonEntity, visibleMobs: NearestVisibleLivingEntities, owner: LivingEntity) {
val nearestAttacker = visibleMobs.findClosest { mob ->
mob.lastHurtMob == owner
val nearestAttacker = visibleMobs.findClosest { livingEntity ->
// Prevents Pokémons from attacking players as owned Pokémons are currently invulnerable
if (livingEntity is ServerPlayer) return@findClosest false
if (livingEntity.lastHurtMob == owner) return@findClosest true
if (livingEntity is Mob && livingEntity.target == owner) return@findClosest true
val mobAttackTarget = livingEntity.brain.getMemorySafely(MemoryModuleType.ATTACK_TARGET)
if (mobAttackTarget.isPresent && mobAttackTarget.get() == owner) return@findClosest true
return@findClosest false
}.map { mob -> mob as LivingEntity }
entity.brain.setMemory(CobblemonMemories.NEAREST_VISIBLE_ATTACKER, nearestAttacker)
@@ -10,18 +10,10 @@ package com.cobblemon.mod.common.entity.pokemon.ai.tasks
import com.cobblemon.mod.common.CobblemonMemories
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.google.common.collect.ImmutableMap
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.ai.attributes.Attributes
import net.minecraft.world.entity.ai.behavior.Behavior
import net.minecraft.world.entity.ai.behavior.OneShot
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
import net.minecraft.world.entity.ai.memory.MemoryModuleType
import net.minecraft.world.entity.ai.memory.MemoryStatus
import net.minecraft.world.entity.ai.memory.WalkTarget
import net.minecraft.world.entity.ai.targeting.TargetingConditions
object DefendOwnerTask {
fun create(): OneShot<PokemonEntity> {
@@ -30,21 +30,13 @@ import com.cobblemon.mod.common.api.events.battles.BattleStartedEvent
import com.cobblemon.mod.common.api.events.battles.BattleVictoryEvent
import com.cobblemon.mod.common.api.events.fishing.PokerodCastEvent
import com.cobblemon.mod.common.api.events.fishing.PokerodReelEvent
import com.cobblemon.mod.common.api.events.pokemon.CollectEggEvent
import com.cobblemon.mod.common.api.events.pokemon.FossilRevivedEvent
import com.cobblemon.mod.common.api.events.pokemon.HatchEggEvent
import com.cobblemon.mod.common.api.events.pokemon.LevelUpEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonCapturedEvent
import com.cobblemon.mod.common.api.events.pokemon.PokemonGainedEvent
import com.cobblemon.mod.common.api.events.pokemon.RidePokemonEvent
import com.cobblemon.mod.common.api.events.pokemon.TradeEvent
import com.cobblemon.mod.common.api.events.pokemon.*
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
import com.cobblemon.mod.common.api.stats.CobblemonStats.getStat
import com.cobblemon.mod.common.util.getPlayer
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import java.util.UUID
import java.util.*
object StatHandler : EventHandler {
override fun registerListeners() {
@@ -100,13 +92,13 @@ object StatHandler : EventHandler {
fun onBattleStart(event : BattleStartedEvent) {
event.battle.players.forEach { player ->
player.awardStat(this.getStat(getStat(Cobblemon.statistics.BATTLES_TOTAL)))
player.awardStat(getStat(Cobblemon.statistics.BATTLES_TOTAL))
}
}
fun onDexEntryGain(event : PokemonGainedEvent) {
val player = event.pokemon.getOwnerPlayer()
player?.awardStat(getStat(getStat(Cobblemon.statistics.DEX_ENTRIES)))
player?.awardStat(getStat(Cobblemon.statistics.DEX_ENTRIES))
}
fun onCollectEgg(event : CollectEggEvent) {
@@ -139,12 +131,4 @@ object StatHandler : EventHandler {
fun onReelIn(event : PokerodReelEvent) {
event.player.awardStat(getStat(Cobblemon.statistics.REEL_INS))
}
fun getStat(resourceLocation: ResourceLocation) : ResourceLocation {
val stat = BuiltInRegistries.CUSTOM_STAT.get(resourceLocation)
if (stat == null) {
Cobblemon.LOGGER.error("Could not find stat with id {}", resourceLocation)
}
return stat ?: throw NullPointerException("Could not find stat with id $resourceLocation")
}
}
@@ -14,7 +14,7 @@ import juuxel.adorn.block.variant.CompatBlockVariantSet
class AdornCompatibility : CompatBlockVariantSet() {
override fun getWoodVariants(): List<BlockVariant?>? {
return this.createVariants({ BlockVariant.Wood(it) }, "apricorn")
return this.createVariants({ BlockVariant.Wood(it) }, "apricorn", "saccharine")
}
override fun getModId(): String? {
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.advancement.criterion.PokemonInteractContext
import com.cobblemon.mod.common.api.text.red
import com.cobblemon.mod.common.battles.BagItemActionResponse
import com.cobblemon.mod.common.battles.BagItems
import com.cobblemon.mod.common.battles.BattleRules
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
import com.cobblemon.mod.common.util.battleLang
import net.minecraft.core.registries.BuiltInRegistries
@@ -41,7 +42,7 @@ interface BagItemLike {
fun handleInteraction(player: ServerPlayer, battlePokemon: BattlePokemon, stack: ItemStack): Boolean {
val battle = battlePokemon.actor.battle
val bagItem = getBagItem(stack) ?: return false
if (!battlePokemon.actor.canFitForcedAction()) {
if (!battlePokemon.actor.canFitForcedAction() || battle.format.ruleSet.contains(BattleRules.BAG_CLAUSE)) {
player.sendSystemMessage(battleLang("bagitem.cannot").red())
return false
}
@@ -25,9 +25,7 @@ class MochiItem(stat: Stats): EVIncreaseItem(stat, 4) {
}
pokemon.feedPokemon(1)
stack.consume(1, player)
return super.applyToPokemon(player, stack, pokemon)
}
}
@@ -35,9 +35,16 @@ class SinisterTeaItem : Item(
val effectsComponent = stack.get(CobblemonItemComponents.MOB_EFFECTS)
if (effectsComponent != null) {
for (effect in effectsComponent.mobEffects) {
val effectCopy = MobEffectInstance(effect)
user.addEffect(effectCopy)
for (raw in effectsComponent.mobEffects) {
val inst = MobEffectInstance(raw)
val holder = inst.effect
val effect = holder.value()
if (effect.isInstantenous) {
effect.applyInstantenousEffect(user as? Player, null, user, inst.amplifier, 1.0)
} else {
user.addEffect(inst)
}
}
}
}
@@ -0,0 +1,48 @@
/*
* 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.net.messages.client.data
import com.cobblemon.mod.common.api.interaction.PokemonInteractionSet
import com.cobblemon.mod.common.api.net.NetworkPacket
import com.cobblemon.mod.common.util.cobblemonResource
import net.minecraft.network.RegistryFriendlyByteBuf
class PokemonInteractionsSyncPacket(
val speciesInteractions: List<PokemonInteractionSet>,
val generalInteractions: List<PokemonInteractionSet>,
) : NetworkPacket<PokemonInteractionsSyncPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeCollection(speciesInteractions) { it, speciesInteraction ->
speciesInteraction.encode(it)
}
buffer.writeCollection(generalInteractions) { it, generalInteraction ->
generalInteraction.encode(it)
}
}
companion object {
val ID = cobblemonResource("pokemon_interactions_sync")
fun decode(buffer: RegistryFriendlyByteBuf): PokemonInteractionsSyncPacket {
val speciesInteractions = buffer.readList { it ->
PokemonInteractionSet.decode(it)
}
val generalInteractions = buffer.readList { it ->
PokemonInteractionSet.decode(it)
}
return PokemonInteractionsSyncPacket(
speciesInteractions,
generalInteractions,
)
}
}
}
@@ -24,19 +24,10 @@ class ClientboundUpdateRidingStatePacket(
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
//We need to allow for encoding the data buffer instead of state for Flashback compat
//Flashback needs to be able to call encode on the packet it gets, which only has data, not state yet.
if (state == null && data == null) error("Expected state or data to be populated for encoding")
if (state == null) error("Expected state to be populated for encoding")
buffer.writeInt(entity)
buffer.writeResourceLocation(behaviour)
if (state != null) {
state.encode(buffer)
}
else if (data != null) {
buffer.writeBytes(data)
//So the buffer can be read in the future
data.resetReaderIndex()
}
state.encode(buffer)
}
companion object {
@@ -21,7 +21,9 @@ class PokemonStateUpdatePacket(pokemon: () -> Pokemon?, value: PokemonState): Si
value.writeToBuffer(buffer)
}
override fun set(pokemon: Pokemon, value: PokemonState) { pokemon.state = value }
override fun set(pokemon: Pokemon, value: PokemonState) {
pokemon.state = value
}
companion object {
val ID = cobblemonResource("state_update")
@@ -13,30 +13,24 @@ import com.cobblemon.mod.common.api.mark.Marks
import com.cobblemon.mod.common.api.pokeball.PokeBalls
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
import com.cobblemon.mod.common.api.riding.stats.RidingStat
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.entity.PlatformType
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.pokemon.Gender
import com.cobblemon.mod.common.util.cobblemonResource
import com.cobblemon.mod.common.util.readEnumConstant
import com.cobblemon.mod.common.util.readIdentifier
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.readText
import com.cobblemon.mod.common.util.writeEnumConstant
import com.cobblemon.mod.common.util.writeIdentifier
import com.cobblemon.mod.common.util.writeString
import com.cobblemon.mod.common.util.writeText
import java.util.UUID
import com.cobblemon.mod.common.util.*
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.entity.Entity
import java.util.*
class SpawnPokemonPacket(
var ownerId: UUID?,
var pokemonUUID: UUID,
var storageUUID: UUID?,
var scaleModifier: Float,
var speciesId: ResourceLocation,
var gender: Gender,
@@ -61,6 +55,7 @@ class SpawnPokemonPacket(
var tickSpawned: Int,
var rideBoosts: Map<RidingStat, Float>,
var rideStamina: Float,
var silent: Boolean,
vanillaSpawnPacket: ClientboundAddEntityPacket,
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
@@ -69,6 +64,7 @@ class SpawnPokemonPacket(
constructor(entity: PokemonEntity, vanillaSpawnPacket: ClientboundAddEntityPacket) : this(
entity.ownerUUID,
entity.pokemon.uuid,
entity.pokemon.storeCoordinates.get()?.store?.uuid,
entity.pokemon.scaleModifier,
entity.exposedSpecies.resourceIdentifier,
entity.pokemon.gender,
@@ -93,12 +89,14 @@ class SpawnPokemonPacket(
entity.tickCount,
entity.entityData.get(PokemonEntity.RIDE_BOOSTS),
entity.entityData.get(PokemonEntity.RIDE_STAMINA),
entity.isSilent,
vanillaSpawnPacket
)
override fun encodeEntityData(buffer: RegistryFriendlyByteBuf) {
buffer.writeNullable(ownerId) { _, v -> buffer.writeUUID(v) }
buffer.writeUUID(this.pokemonUUID)
buffer.writeNullable(this.storageUUID) { pb, value -> pb.writeUUID(value) }
buffer.writeFloat(this.scaleModifier)
buffer.writeIdentifier(this.speciesId)
buffer.writeEnumConstant(this.gender)
@@ -127,10 +125,21 @@ class SpawnPokemonPacket(
{ _, value -> buffer.writeFloat(value) }
)
buffer.writeFloat(rideStamina)
buffer.writeBoolean(silent)
}
override fun applyData(entity: PokemonEntity, level: ClientLevel) {
entity.ownerUUID = ownerId
// Reuse the stored Pokémon instance to avoid creating a duplicate,
// preventing client/entity desync issues.
this@SpawnPokemonPacket.storageUUID?.let {
val storedPokemon = CobblemonClient.storage.locatePokemon(it, this@SpawnPokemonPacket.pokemonUUID)
if (storedPokemon != null) {
entity.pokemon = storedPokemon
}
}
entity.pokemon.apply {
uuid = this@SpawnPokemonPacket.pokemonUUID
scaleModifier = this@SpawnPokemonPacket.scaleModifier
@@ -162,6 +171,7 @@ class SpawnPokemonPacket(
entity.entityData.set(PokemonEntity.RIDE_BOOSTS, rideBoosts)
entity.entityData.set(PokemonEntity.RIDE_STAMINA, rideStamina)
entity.entityData.set(PokemonEntity.SCALE_MODIFIER, scaleModifier)
entity.isSilent = silent
entity.ejectPassengers()
passengers.forEach {
@@ -179,6 +189,7 @@ class SpawnPokemonPacket(
fun decode(buffer: RegistryFriendlyByteBuf): SpawnPokemonPacket {
val ownerId = buffer.readNullable { buffer.readUUID() }
val pokemonUUID = buffer.readUUID()
val storageUUID = buffer.readNullable { buffer.readUUID() }
val scaleModifier = buffer.readFloat()
val speciesId = buffer.readIdentifier()
val gender = buffer.readEnumConstant(Gender::class.java)
@@ -206,11 +217,13 @@ class SpawnPokemonPacket(
{ buffer.readFloat() }
)
val rideStamina = buffer.readFloat()
val silent = buffer.readBoolean()
val vanillaPacket = decodeVanillaPacket(buffer)
return SpawnPokemonPacket(
ownerId,
pokemonUUID,
storageUUID,
scaleModifier,
speciesId,
gender,
@@ -235,6 +248,7 @@ class SpawnPokemonPacket(
tickSpawned,
rideBoosts,
rideStamina,
silent,
vanillaPacket
)
}
@@ -9,6 +9,7 @@
package com.cobblemon.mod.common.net.serverhandling.riding
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
import com.cobblemon.mod.common.api.riding.RidingStyle
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
import net.minecraft.server.MinecraftServer
@@ -25,12 +26,16 @@ object DismountPokemonPacketHandler : ServerNetworkPacketHandler<DismountPokemon
val pokemon = player.vehicle as PokemonEntity
if (!canPlayerStopRidingPokemon(pokemon, player)) return
val isRidingInAir = pokemon.ridingController?.context?.style == RidingStyle.AIR
if (pokemon.controllingPassenger == player) {
pokemon.passengers.forEach { it.stopRiding() }
}
else {
} else {
player.stopRiding()
}
if (isRidingInAir) pokemon.setFlying(true)
}
private fun canPlayerStopRidingPokemon(pokemon: PokemonEntity, player: ServerPlayer): Boolean {
@@ -199,6 +199,9 @@ open class Pokemon : ShowdownIdentifiable {
var form = species.standardForm
set(value) {
// If nothing actually changed, avoid running heavy logic (e.g. updateMovesOnFormChange when the form hasn't really "changed")
if (field == value) return
// Species updates already update HP but just a form change may require it
// Moved to before the field was set else it won't actually do the hp calc proper <3
val quotient = clamp(currentHealth / maxHealth.toFloat(), 0F, 1F)
@@ -1437,6 +1440,11 @@ open class Pokemon : ShowdownIdentifiable {
}
fun getOwnerEntity(): LivingEntity? {
if (isClient) {
val ownerUUID = entity?.ownerUUID ?: return null
return entity?.level()?.getPlayerByUUID(ownerUUID)
}
return storeCoordinates.get()?.let {
if (isPlayerOwned()) {
server()?.playerList?.getPlayer(it.store.uuid)
@@ -2139,16 +2147,26 @@ open class Pokemon : ShowdownIdentifiable {
*/
open fun self(): Pokemon = this
/**
* Function that sanitizes specific form-related moves when the form of this Pokémon changes.
* We only want to sanitize `form_change` moves here so that intended illegalities from the user are preserved.
*
* E.g, Removing Overheat from Rotom when it is no longer Rotom-Heat and the target form is not compatible with Overheat.
*/
private fun updateMovesOnFormChange(newForm: FormData) {
if (this.isClient) {
return
}
if (this.isClient) return
val oldFormChangeMoves = this.form.moves.formChangeMoves.toSet()
// Only remove moves that were provided by the old form's form-change moves AND are not learnable by the new form
for (i in 0 until MoveSet.MOVE_COUNT) {
val move = this.moveSet[i]
if (move != null && !LearnsetQuery.ANY.canLearn(move.template, newForm.moves)) {
if (move != null && move.template in oldFormChangeMoves) {
this.moveSet.setMove(i, null)
}
}
val benchedIterator = this.benchedMoves.iterator()
while (benchedIterator.hasNext()) {
val benchedMove = benchedIterator.next()
@@ -2156,11 +2174,18 @@ open class Pokemon : ShowdownIdentifiable {
benchedIterator.remove()
}
}
// Add form change moves
// Add new form's form-change moves
newForm.moves.formChangeMoves.forEach { move ->
// Under the hood these check if the moves already exist
this.benchedMoves.add(BenchedMove(move, 0))
if (this.moveSet.filterNotNull().none { it.template == move }) {
if (this.moveSet.hasSpace()) {
this.moveSet.add(move.create())
} else {
this.benchedMoves.add(BenchedMove(move, 0))
}
}
}
// If moveset is empty try to find one valid move to fill it
if (this.moveSet.filterNotNull().isEmpty()) {
val benchedMove = this.benchedMoves.firstOrNull()
@@ -8,13 +8,22 @@
package com.cobblemon.mod.common.pokemon.adapters
import com.cobblemon.mod.common.api.interaction.InteractionEffect
import com.cobblemon.mod.common.api.molang.ExpressionLike
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.pokemon.adapters.RequirementAdapter
import com.cobblemon.mod.common.api.pokemon.requirement.Requirement
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
import com.cobblemon.mod.common.pokemon.requirements.*
import com.cobblemon.mod.common.util.adapters.*
import com.cobblemon.mod.common.util.readString
import com.cobblemon.mod.common.util.writeString
import com.google.common.collect.HashBiMap
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonElement
import com.google.gson.JsonSerializationContext
import com.google.gson.*
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.LowerCaseEnumTypeAdapterFactory
import java.lang.reflect.Type
import kotlin.reflect.KClass
@@ -60,21 +69,60 @@ object CobblemonRequirementAdapter : RequirementAdapter {
this.registerType(OwnerHoldsItemRequirement.ADAPTER_VARIANT, OwnerHoldsItemRequirement::class)
}
val gson: Gson by lazy {
GsonBuilder()
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
.registerTypeAdapter(Requirement::class.java, CobblemonRequirementAdapter)
.registerTypeAdapter(InteractionEffect::class.java, InteractionEffectAdapter)
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
.registerTypeAdapterFactory(LowerCaseEnumTypeAdapterFactory())
.setPrettyPrinting()
.create()
}
override fun <T : Requirement> registerType(id: String, type: KClass<T>) {
this.types[id.lowercase()] = type
}
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Requirement {
val variant = json.asJsonObject.get(VARIANT).asString.lowercase()
val type = this.types[variant] ?: throw IllegalArgumentException("Cannot resolve evolution requirement type for variant $variant")
val type = getRequirementType(variant)
return context.deserialize(json, type.java)
}
override fun serialize(src: Requirement, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
val json = context.serialize(src, src::class.java).asJsonObject
val variant = this.types.inverse()[src::class] ?: throw IllegalArgumentException("Cannot resolve evolution requirement for type ${src::class.qualifiedName}")
override fun serialize(requirement: Requirement, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
val json = context.serialize(requirement, requirement::class.java).asJsonObject
val variant = getVariant(requirement)
json.addProperty(VARIANT, variant)
return json
}
fun encode(requirement: Requirement, buffer: FriendlyByteBuf) {
buffer.writeString(gson.toJson(requirement, Requirement::class.java))
}
fun decode(buffer: FriendlyByteBuf): Requirement {
return gson.fromJson(buffer.readString(), Requirement::class.java)
}
private fun getVariant(requirement: Requirement): String {
val variant = this.types.inverse()[requirement::class]
if (variant == null) {
throw IllegalArgumentException("Cannot resolve evolution requirement for type ${requirement::class.qualifiedName}")
}
return variant
}
private fun getRequirementType(variant: String): KClass<out Requirement> {
val requirementType = this.types[variant]
if (requirementType == null) {
throw IllegalArgumentException("Cannot resolve evolution requirement type for variant $variant")
}
return requirementType
}
}
@@ -562,8 +562,8 @@ class OmniPathNodeMaker : NodeEvaluator() {
//// PathType.WALKABLE
//// } else if (blockState.canPathfindThrough(world, pos, NavigationType.AIR) && !blockStateBelow.isSideSolid(world, below, Direction.UP, SideShapeType.FULL)) {
//// PathType.OPEN
// } else if (blockState.`is`(BlockTags.LEAVES) && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES && canPathThroughLeaves()) {
// return PathType.OPEN
if (canPathThroughLeaves() && blockState.block == CobblemonBlocks.SACCHARINE_LEAVES)
return PathType.OPEN
// } else PathType.BLOCKED
// This is the 1.6.1 logic but with some optimizations
@@ -633,9 +633,6 @@ class OmniPathNodeMaker : NodeEvaluator() {
pfContext, x, y, z, sizeX, sizeY, sizeZ, canOpenDoors, canPassDoors, set, PathType.BLOCKED, BlockPos(x, y, z), returnedEarlyPathType
)
if (PathType.LEAVES in set) {
return PathType.OPEN
}
if (PathType.FENCE in set) {
return PathType.FENCE
@@ -755,7 +752,7 @@ class OmniPathNodeMaker : NodeEvaluator() {
} else if (type == PathType.RAIL && block !is BaseRailBlock && pfContext.getCachedBlockState(pos.below()).block !is BaseRailBlock) {
PathType.UNPASSABLE_RAIL
} else if (type == PathType.LEAVES) {
if (blockState.block === CobblemonBlocks.SACCHARINE_LEAVES && canPathThroughLeaves()) {
if (canPathThroughLeaves() && blockState.block === CobblemonBlocks.SACCHARINE_LEAVES) {
PathType.OPEN
} else {
PathType.BLOCKED
@@ -6,19 +6,15 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.pokemon.properties.tags
package com.cobblemon.mod.common.pokemon.properties
import com.cobblemon.mod.common.api.properties.CustomPokemonPropertyType
import com.cobblemon.mod.common.pokemon.properties.StringProperty
object PokemonFlagProperty : CustomPokemonPropertyType<StringProperty> {
private const val KEY = "tag"
override val keys = setOf(KEY)
object LabelProperty : CustomPokemonPropertyType<StringProperty> {
override val keys = setOf("label", "tag")
override val needsKey = true
override fun fromString(value: String?) = if (value == null) null else StringProperty(KEY, value, { _, _ -> }, { pokemon, underlyingValue -> pokemon.hasLabels(underlyingValue) })
override fun fromString(value: String?) = if (value == null) null else StringProperty(keys.first(), value, { _, _ -> }, { pokemon, underlyingValue -> pokemon.hasLabels(underlyingValue) })
override fun examples() = emptySet<String>()
}
@@ -11,9 +11,9 @@ package com.cobblemon.mod.common.pokemon.requirements
import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation
import kotlin.collections.iterator
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.player.Player
/**
* An [com.cobblemon.mod.common.api.pokemon.requirement.Requirement] that checks if the player has a certain [net.minecraft.advancements.Advancement]
@@ -26,13 +26,16 @@ class AdvancementRequirement(val requiredAdvancement: ResourceLocation) : OwnerQ
override fun checkPlayer(
pokemon: Pokemon,
owner: ServerPlayer
owner: Player
): Boolean {
for (entry in owner.advancements.progress) {
val serverPlayer = owner as? ServerPlayer ?: return false
for (entry in serverPlayer.advancements.progress) {
if (entry.key.id == requiredAdvancement && entry.value.isDone) {
return true
}
}
return false
}
@@ -12,11 +12,9 @@ import com.cobblemon.mod.common.api.pokemon.requirement.OwnerQueryRequirement
import com.cobblemon.mod.common.entity.npc.NPCEntity
import com.cobblemon.mod.common.pokemon.Pokemon
import net.minecraft.advancements.critereon.ItemPredicate
import net.minecraft.server.level.ServerPlayer
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.InteractionHand
import net.minecraft.world.entity.LivingEntity
import kotlin.collections.iterator
import net.minecraft.world.entity.player.Player
/**
* An [OwnerQueryRequirement] that checks if the player/npc is holding a certain [ItemPredicate]
@@ -30,7 +28,7 @@ class OwnerHoldsItemRequirement(val itemCondition: ItemPredicate)
override fun checkPlayer(
pokemon: Pokemon,
owner: ServerPlayer
owner: Player
): Boolean {
return checkItem(owner)
}
@@ -8,22 +8,22 @@
package com.cobblemon.mod.common.util.adapters
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import com.google.gson.*
import com.mojang.serialization.Codec
import com.mojang.serialization.JsonOps
import java.lang.reflect.Type
class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSerializer<T> {
override fun deserialize(
jElement: JsonElement,
typeOfT: Type,
context: JsonDeserializationContext
): T {
return JsonOps.INSTANCE.withDecoder(codec).apply(jElement).result().get().first as T
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
val result = ops.withDecoder(codec).apply(jElement)
return result.result().orElseThrow {
IllegalStateException("Failed to deserialize $jElement: ${result.error().orElse(null)}")
}.first
}
override fun serialize(
@@ -31,6 +31,10 @@ class CodecBackedAdapter<T>(val codec: Codec<T>) : JsonDeserializer<T>, JsonSeri
typeOfSrc: Type?,
context: JsonSerializationContext?
): JsonElement {
return JsonOps.INSTANCE.withEncoder(codec).apply(src).result().get()
val ops = RegistryOpsProvider.getOpsWithDefaultFallback()
val result = ops.withEncoder(codec).apply(src)
return result.result().orElseThrow {
IllegalStateException("Failed to serialize $src: ${result.error().orElse(null)}")
}
}
}
@@ -0,0 +1,41 @@
/*
* 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.util.adapters
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.Environment
import com.cobblemon.mod.common.util.server
import com.google.gson.JsonElement
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.JsonOps
import net.minecraft.client.Minecraft
import net.minecraft.resources.RegistryOps
/**
* Utility for obtaining RegistryOps with the correct client/server registry access.
* Used when manually encoding/decoding registry-backed values (e.g., items, predicates).
*/
object RegistryOpsProvider {
fun getOpsWithDefaultFallback(): DynamicOps<JsonElement> {
if (Cobblemon.implementation.environment() == Environment.CLIENT) {
val minecraft = Minecraft.getInstance()
if (minecraft != null && minecraft.level != null)
return RegistryOps.create(JsonOps.INSTANCE, minecraft.level!!.registryAccess())
}
if (Cobblemon.implementation.environment() == Environment.SERVER) {
val server = server()
if (server != null)
return RegistryOps.create(JsonOps.INSTANCE, server.registryAccess())
}
return JsonOps.INSTANCE
}
}
@@ -10,13 +10,14 @@ package com.cobblemon.mod.common.world.feature
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonBlocks
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
import com.cobblemon.mod.common.api.tags.CobblemonBiomeTags
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.Direction.UP
import net.minecraft.nbt.CompoundTag
import net.minecraft.tags.BlockTags
import net.minecraft.util.RandomSource
import net.minecraft.world.item.component.CustomData
import net.minecraft.world.level.WorldGenLevel
import net.minecraft.world.level.block.Block.UPDATE_ALL
import net.minecraft.world.level.block.Block.UPDATE_CLIENTS
@@ -227,12 +228,20 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
val i: Int = 2 + randomSource.nextInt(2)
for (j in 0..<i) {
if (isCombee > 0) {
beehiveBlockEntity!!.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)))
beehiveBlockEntity?.storeBee(BeehiveBlockEntity.Occupant.create(randomSource.nextInt(599)))
} else {
// We want to create a Pokemon entity here and turn it into a compound tag to store in the hive.
// But creating a Pokemon entity during world generation can cause issues.
// So instead we create custom compound tag that is a placeholder for an incomplete Pokemon.
// This is caught and handled by BeeOccupantMixin.java, which turns it into a complete entity.
val properties = "${POKEMON_ARGS} lvl=${LEVEL_RANGE.random()}"
val pokemon = PokemonProperties.parse(properties)
val entity = pokemon.createEntity(worldGenLevel.level)
beehiveBlockEntity!!.addOccupant(entity)
val compoundTag = CompoundTag()
compoundTag.putString("id", POKEMON_PLACEHOLD_ID)
compoundTag.putString("pokemonProperties", properties)
val occupant = BeehiveBlockEntity.Occupant(
CustomData.of(compoundTag), randomSource.nextInt(599), 600
)
beehiveBlockEntity?.storeBee(occupant)
}
}
})
@@ -351,5 +360,6 @@ class SaccharineTreeFeature : Feature<BlockStateConfiguration>(BlockStateConfigu
companion object {
val POKEMON_ARGS = "combee"
val LEVEL_RANGE = 5..15
val POKEMON_PLACEHOLD_ID = "cobblemon_pokemon_entity_placeholder"
}
}
@@ -297,6 +297,11 @@
"1.0833": [0, 0, 0]
}
}
},
"sound_effects": {
"0.25": {
"effect": "pokemon.ditto.cry"
}
}
},
"animation.ditto.blink": {
@@ -3,7 +3,7 @@
"animations": {
"animation.metagross.ground_idle": {
"loop": true,
"animation_length": 11.4167,
"animation_length": 0,
"bones": {
"body2": {
"position": [0, -11.9, 0]
@@ -299,6 +299,14 @@
"rotation": [0, 0, 15]
}
}
},
"animation.eelektrik.cry": {
"animation_length": 1.25,
"sound_effects": {
"0.0417": {
"effect": "pokemon.eelektrik.cry"
}
}
}
}
}
@@ -869,6 +869,14 @@
"position": [-0.1, 0, 0]
}
}
},
"animation.eelektross.cry": {
"animation_length": 1.25,
"sound_effects": {
"0.0417": {
"effect": "pokemon.eelektross.cry"
}
}
}
}
}
@@ -84,7 +84,7 @@
"position": [0, "0+Math.cos((query.anim_time) * 90 * 8 - 60) * -0.1", 0]
},
"hair3": {
"rotation": ["0+Math.cos((query.anim_time) * 90 * 8 - 100) * 3", 0, 0]
"rotation": ["-2+Math.cos((query.anim_time) * 90 * 8 - 100) * 3", 0, 0]
},
"hair": {
"rotation": ["0+Math.cos((query.anim_time) * 90 * 8 - 120) * 10", 12.5, "0+Math.cos((query.anim_time) * 90 * 4 - 180) * 10"]
@@ -356,7 +356,7 @@
"position": [-1.63659, -1.07651, 3.16823]
},
"arm_right": {
"rotation": [-80.89079, -82.69097, -6.55875]
"rotation": [-99.86576, -52.80463, 0.06108]
},
"finger_right": {
"rotation": [0, 0, 17.5]
@@ -375,6 +375,21 @@
},
"arm_hammer_left": {
"rotation": [-85, 100, 0]
},
"hand_right": {
"rotation": [0, 0, -22.5]
},
"brow_right": {
"position": [0, -0.75, 0]
},
"brow_left": {
"position": [0, -0.75, 0]
},
"eyes_ditto": {
"position": [0, 0, 0.1]
},
"eyes_blink_ditto": {
"position": [0, 0, -0.1]
}
}
},
@@ -460,40 +475,26 @@
"1.875": [0, 0, 0]
}
},
"eyelid_right": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, 0, -0.125],
"0.625": [0, 0, -0.125],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, 0, -0.125],
"1.5833": [0, 0, -0.125],
"1.625": [0, 0, 0],
"1.7083": [0, 0, 0],
"1.75": [0, 0, -0.125]
}
},
"eyelid_left": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, 0, -0.125],
"0.625": [0, 0, -0.125],
"0.4167": [0, 0, -0.1],
"0.625": [0, 0, -0.1],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, 0, -0.125],
"1.5833": [0, 0, -0.125],
"1.625": [0, 0, 0],
"0.875": [0, 0, -0.1],
"1.5833": [0, 0, -0.1],
"1.625": [0, 0, 1],
"1.7083": [0, 0, 0],
"1.75": [0, 0, -0.125]
"1.75": [0, 0, -0.1]
}
},
"mouth_open": {
"mouth_open_cry": {
"position": {
"0.8333": [0, 0, 0],
"0.875": [0, 0, -0.125],
"1.875": [0, 0, -0.125],
"1.9167": [0, 0, 0]
"0.875": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.875": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"1.9167": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
},
"arm_left": {
@@ -556,13 +557,6 @@
"1.75": [0, 0, 0]
}
},
"eye_right": {
"scale": {
"1.5833": [1, 1, 1],
"1.625": [1.4, 1.4, 3.3],
"1.7083": [1, 1, 1]
}
},
"eye_left": {
"scale": {
"1.5833": [1, 1, 1],
@@ -722,6 +716,55 @@
"1.7083": [1, 1, 1]
}
},
"leg_left": {
"rotation": {
"0.0": [0, 0, 0],
"0.2917": [0, -20, -2.5],
"0.4167": [-5.68, -13.75, -2.5],
"0.5833": [-32.36, -7.5, -2.5],
"0.7083": [-40.5, 2.5, -2.5],
"0.75": [-33.83, 2.5, -2.5],
"0.8333": [-30.5, 2.5, -2.5]
},
"position": {
"0.4167": [0, 0, 0],
"0.5833": [0, 0, -0.75],
"1.5833": [0, 0, -0.75],
"1.625": [1.25, 0, -0.75],
"1.75": [0, 0, 0]
}
},
"arm_hammer_left": {
"rotation": {
"0.0": [0, 0, 17.5],
"0.25": [0, -25, 5],
"0.4167": [0, -32.5, 3.5],
"0.5": [-11.25, 40.75, -16.75],
"0.5833": [-22.5, 46.75, -37],
"0.7083": [-25, 44, -40.75]
}
},
"eye_right": {
"scale": {
"1.5833": [1, 1, 1],
"1.625": [1.4, 1.4, 3.3],
"1.7083": [1, 1, 1]
}
},
"eyelid_right": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, 0, -0.1],
"0.625": [0, 0, -0.1],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, 0, -0.1],
"1.5833": [0, 0, -0.1],
"1.625": [0, 0, 1],
"1.7083": [0, 0, 0],
"1.75": [0, 0, -0.1]
}
},
"arm_right": {
"rotation": {
"0.0": [0, 0, -20],
@@ -753,24 +796,6 @@
"finger_right3": {
"rotation": [0, 0, -22.5]
},
"leg_left": {
"rotation": {
"0.0": [0, 0, 0],
"0.2917": [0, -20, -2.5],
"0.4167": [-5.68, -13.75, -2.5],
"0.5833": [-32.36, -7.5, -2.5],
"0.7083": [-40.5, 2.5, -2.5],
"0.75": [-33.83, 2.5, -2.5],
"0.8333": [-30.5, 2.5, -2.5]
},
"position": {
"0.4167": [0, 0, 0],
"0.5833": [0, 0, -0.75],
"1.5833": [0, 0, -0.75],
"1.625": [1.25, 0, -0.75],
"1.75": [0, 0, 0]
}
},
"leg_right": {
"rotation": {
"0.0": [0, 0, 0],
@@ -789,33 +814,146 @@
"1.75": [-0.5, 0, 0]
}
},
"arm_hammer_left": {
"rotation": {
"0.0": [0, 0, 17.5],
"0.25": [0, -25, 5],
"0.4167": [0, -32.5, 3.5],
"0.5": [-11.25, 40.75, -16.75],
"0.5833": [-22.5, 46.75, -37],
"0.7083": [-25, 44, -40.75]
"brow_left": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, -0.75, 0],
"0.625": [0, -0.75, 0],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, -0.75, 0],
"1.5833": [0, -0.75, 0],
"1.625": [0, 0, 0],
"1.7083": [0, 0, 0],
"1.75": [0, -0.75, 0]
}
},
"brow_right": {
"position": {
"0.375": [0, 0, 0],
"0.4167": [0, -0.75, 0],
"0.625": [0, -0.75, 0],
"0.6667": [0, 0, 0],
"0.8333": [0, 0, 0],
"0.875": [0, -0.75, 0],
"1.5833": [0, -0.75, 0],
"1.625": [0, 0, 0],
"1.7083": [0, 0, 0],
"1.75": [0, -0.75, 0]
}
},
"mouth_closed": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, -0.5, 0]},
"1.875": {"pre": [0, -0.5, 0], "post": [0, -0.5, 0]},
"1.9167": {"pre": [0, -0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_lip_top": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.875": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
"1.9167": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_ditto": {
"position": {
"0.375": [0, 0, 0],
"0.4167": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"0.625": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
"0.6667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]},
"0.8333": {"pre": [0, 0, 0], "post": [0, 0, 0]},
"0.875": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.5833": {"pre": [0, 0, 0.1], "post": [0, 0, 0]},
"1.75": {"pre": [0, 0, 0], "post": [0, 0, 0.1]}
},
"scale": {
"1.5833": [1, 1, 1],
"1.625": [1.4, 1.4, 3.3],
"1.7083": [1, 1, 1]
}
},
"eyes_blink_ditto": {
"position": {
"0.375": [0, 0, 0],
"0.4167": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"0.625": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"0.6667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]},
"0.8333": {"pre": [0, 0, 0], "post": [0, 0, 0]},
"0.875": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.5833": {"pre": [0, 0, -0.1], "post": [0, 0, 0]},
"1.75": {"pre": [0, 0, 0], "post": [0, 0, -0.1]}
}
},
"mouth_ditto": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.875": {"pre": [0, 0, 0.1], "post": [0, 0, 0.1]},
"1.9167": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_open_ditto": {
"position": {
"0.8333": [0, 0, 0],
"0.875": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.875": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"1.9167": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
}
},
"animation.tinkatink.blink": {
"animation_length": 0.16667,
"animation_length": 0.1667,
"bones": {
"eyelid_right": {
"position": {
"0.0": [0, 0, -0.1],
"0.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, -0.1],
"0.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
},
"brow_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"brow_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eye_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_ditto": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"eyes_blink_ditto": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
}
@@ -823,38 +961,6 @@
"animation.tinkatink.cry": {
"animation_length": 1.5,
"bones": {
"neck": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": [10, 0, 0],
"1.25": [10, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, -2, 0],
"1.25": [0, -2, 0],
"1.5": [0, 0, 0]
}
},
"mouth2": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, -5, 0],
"1.25": [0, -5, 0],
"1.5": [0, 0, 0]
}
},
"jaw": {
"position": {
"0.0": [0, 0, 0],
"0.25": [0, -3, 0],
"1.25": [0, -3, 0],
"1.5": [0, 0, 0]
}
},
"head": {
"rotation": {
"0.0": [0, 0, 0],
@@ -863,60 +969,12 @@
"1.5": [0, 0, 0]
}
},
"head2": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": [-15, 0, 0],
"1.25": [-15, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth_closed2": {
"position": {
"0.25": [0, 0, -0.1],
"0.3333": [0, 0, 0],
"1.1667": [0, 0, 0],
"1.25": [0, 0, -0.1]
}
},
"mouth_open2": {
"position": {
"0.0": [0, 0, 0.1],
"0.25": [0, 0, 0],
"1.25": [0, 0, 0],
"1.5": [0, 0, 0.1]
}
},
"head3": {
"rotation": {
"0.0": [0, 0, 0],
"0.25": [-15, 0, 0],
"1.25": [-15, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth_closed3": {
"position": {
"0.25": [0, 0, -0.1],
"0.3333": [0, 0, 0],
"1.1667": [0, 0, 0],
"1.25": [0, 0, -0.1]
}
},
"mouth_open3": {
"position": {
"0.0": [0, 0, 0.1],
"0.25": [0, 0, 0],
"1.25": [0, 0, 0],
"1.5": [0, 0, 0.1]
}
},
"mouth_open": {
"mouth_open_cry": {
"position": {
"0.0833": [0, 0, 0],
"0.1667": [0, 0, -0.15],
"1.25": [0, 0, -0.15],
"1.3333": [0, 0, 0]
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.25": {"pre": [0, 0, -0.1], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
},
"arm_left": {
@@ -948,10 +1006,38 @@
"1.25": [0, 0, -2.4],
"1.5": [0, 0, 0]
}
},
"mouth_closed": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, -0.5, 0]},
"1.3333": {"pre": [0, -0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_lip_top": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.3333": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.3333": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.1667": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
},
"sound_effects": {
"0.25": {
"0.0": {
"effect": "pokemon.tinkatink.cry"
}
}
@@ -1062,6 +1148,128 @@
"rotation": [0, 0, 32.5]
}
}
},
"animation.tinkatink.ditto_face": {
"loop": true,
"bones": {
"face": {
"position": [0, 0, 0.1],
"scale": 0
},
"face_ditto": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatink.happy": {
"loop": true,
"bones": {
"brow_left": {
"position": [0, 0, 0.1]
},
"brow_right": {
"position": [0, 0, 0.1]
},
"eye_left": {
"position": [0, 0, 0.1]
},
"eye_right": {
"position": [0, 0, 0.1]
},
"mouth_closed": {
"position": [0, 0, 0.1]
},
"mouth_lip_top": {
"position": [0, 0, 0.1]
},
"mouth_open_happy": {
"position": [0, 0, -0.1]
},
"eyelid_happy_left": {
"position": [0, 0, -0.1]
},
"eyelid_happy_right": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatink.angry": {
"loop": true,
"bones": {
"eye_emote_left": {
"scale": [1, 0.5, 1]
},
"eye_emote_right": {
"scale": [1, 0.5, 1]
},
"eye_emote_left2": {
"position": [0.25, 0, 0],
"scale": [0.5, 1, 1]
},
"eye_emote_right2": {
"position": [-0.25, 0, 0],
"scale": [0.5, 1, 1]
}
}
},
"animation.tinkatink.very_sad": {
"loop": true,
"bones": {
"eye_emote_left": {
"scale": [1, 0.5, 1]
},
"eye_emote_right": {
"scale": [1, 0.5, 1]
},
"eye_emote_left2": {
"position": [-0.25, 0, 0],
"scale": [0.5, 1, 1]
},
"eye_emote_right2": {
"position": [0.25, 0, 0],
"scale": [0.5, 1, 1]
}
}
},
"animation.tinkatink.hurt": {
"loop": true,
"bones": {
"brow_left": {
"position": [0, 0, 0.1]
},
"brow_right": {
"position": [0, 0, 0.1]
},
"eye_left": {
"position": [0, 0, 0.1]
},
"eye_right": {
"position": [0, 0, 0.1]
},
"eyelid_hurt_left": {
"position": [0, 0, -0.1]
},
"eyelid_hurt_right": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatink.disinterested": {
"loop": true,
"bones": {
"eye_emote_left": {
"scale": [1, 0.5, 1]
},
"eye_emote_right": {
"scale": [1, 0.5, 1]
},
"eye_emote_left2": {
"position": [0, 0, 0.1]
},
"eye_emote_right2": {
"position": [0, 0, 0.1]
}
}
}
}
}
@@ -4,12 +4,6 @@
"animation.tinkatuff.ground_idle": {
"loop": true,
"bones": {
"tail": {
"rotation": [12.5, 0, 0]
},
"tail2": {
"rotation": [12.5, 0, 0]
},
"arm_right": {
"rotation": [55.98303, 0.22836, "-40.7651+Math.cos((query.anim_time) * 90 * 2 - 120) * 1"],
"position": [-0.25, -0.5, 0]
@@ -21,7 +15,8 @@
"rotation": [0, 0, -5]
},
"finger_right2": {
"rotation": [0, -10, 37.5]
"rotation": [0, -17.5, 37.5],
"position": [-0.25, 0, 0]
},
"arm_left": {
"rotation": [-84.39003, 4.58778, "53.5046+Math.cos((query.anim_time) * 90 * 2 - 120) * 1"]
@@ -30,17 +25,11 @@
"rotation": [0, -15, 55]
},
"finger_left": {
"rotation": [0, 0, -25]
"rotation": [0, 0, -40]
},
"finger_left2": {
"rotation": [20, 0, 0]
},
"hand_left": {
"rotation": [0, 17.5, 0]
},
"hand_right": {
"rotation": [0, -17.5, 0]
},
"leg_left": {
"rotation": [0, -12.5, -5]
},
@@ -48,7 +37,7 @@
"rotation": [0, 12.5, 5]
},
"finger_left3": {
"rotation": [0, 0, 57.5]
"rotation": [0, 0, 67.5]
},
"finger_right3": {
"rotation": [0, 0, -20]
@@ -78,9 +67,6 @@
"head": {
"rotation": ["12.5+Math.cos((query.anim_time) * 90 * 2 - 50) * 2", 0, 0]
},
"mouth_closed": {
"position": [0, 0, 0]
},
"ponytail": {
"rotation": ["0+Math.cos((query.anim_time) * 90 * 2 - 120) * 1", 0, 0]
},
@@ -187,10 +173,24 @@
}
},
"finger_right2": {
"rotation": [7.5, 0, 10]
"rotation": [7.5, 0, 42.5],
"position": [-0.25, 0.25, 0]
},
"finger_right3": {
"rotation": [-0.88045, -9.96156, 5.07673]
},
"finger_left": {
"rotation": [0, 0, -55],
"position": [0, 0.5, 0]
},
"finger_left2": {
"rotation": [0, 0, -17.5]
},
"finger_left3": {
"rotation": [0, 0, 22.5]
},
"finger_right": {
"rotation": [0, 0, 20]
}
}
},
@@ -210,7 +210,7 @@
"rotation": [-15, -2.5, 62.5]
},
"finger_left3": {
"rotation": [0, 0, 52.5]
"rotation": [0, 0, 22.5]
},
"arm_right": {
"rotation": [22.5, -10, -35],
@@ -299,18 +299,29 @@
},
"arm_hammer_right2": {
"rotation": [0, -70, 0]
},
"finger_left": {
"rotation": [0, 0, -52.5],
"position": [0, 0.75, 0]
},
"finger_left2": {
"rotation": [0, 0, -15]
},
"finger_right": {
"rotation": [0, 0, 20]
},
"finger_right2": {
"rotation": [7.5, 0, 37.5],
"position": [-0.25, 0.25, 0]
},
"finger_right3": {
"rotation": [0, 0, -32.5]
}
}
},
"animation.tinkatuff.battle_idle": {
"loop": true,
"bones": {
"tail": {
"rotation": [12.5, 0, 0]
},
"tail2": {
"rotation": [12.5, 0, 0]
},
"arm_right": {
"rotation": [40.98303, 0.22836, "-45.7651+Math.cos((query.anim_time) * 90 * 2 - 40) * 2"]
},
@@ -318,7 +329,8 @@
"rotation": [0, -52.5, 0]
},
"finger_right": {
"rotation": [0, 0, -5]
"rotation": [0, 0, 37.5],
"position": [0, 0.25, 0]
},
"finger_right2": {
"rotation": [0, 0, 37.5]
@@ -330,17 +342,12 @@
"rotation": [0, 0, "55+Math.cos((query.anim_time) * 90 * 2 - 40) * -2"]
},
"finger_left": {
"rotation": [0, 0, -25]
"rotation": [0, 0, -47.5],
"position": [0, 0.5, 0]
},
"finger_left2": {
"rotation": [20, 0, 0]
},
"hand_left": {
"rotation": [0, 17.5, 0]
},
"hand_right": {
"rotation": [0, -17.5, 0]
},
"leg_left": {
"rotation": ["-11.2025+Math.cos((query.anim_time) * 90 * 2) * 3", -21.49336, -9.33448]
},
@@ -348,10 +355,11 @@
"rotation": ["-13.5954+Math.cos((query.anim_time) * 90 * 2) * 3", 22.38126, 10.45107]
},
"finger_left3": {
"rotation": [0, 0, 57.5]
"rotation": [0, 0, 42.5],
"position": [-0.5, -0.25, 0]
},
"finger_right3": {
"rotation": [0, 0, -20]
"rotation": [0, 0, -40]
},
"hammer": {
"rotation": [-12.18122, -2.58318, 113.79667]
@@ -416,7 +424,8 @@
"position": [-0.5, 0, 0]
},
"hammer": {
"rotation": [15, 0, 0]
"rotation": [15, 0, 0],
"position": [0, 0.5, 3.75]
},
"hammer2": {
"rotation": ["90+Math.cos((query.anim_time) * 90 * 1) * -1", 0, 0],
@@ -456,43 +465,18 @@
},
"leg_right": {
"rotation": [-90, 20, 0]
},
"eyes_ditto": {
"position": [0, 0, 0.1]
},
"eyes_blink_ditto": {
"position": [0, 0, -0.1]
}
}
},
"animation.tinkatuff.faint": {
"animation_length": 3,
"bones": {
"arm_right": {
"rotation": {
"0.0": [40.98303, 0.22836, -45.7651],
"0.2083": [5.98, 0.23, -45.77],
"0.2917": [35.98, 0.23, -45.77],
"0.75": [18.48, 5.23, -23.27],
"0.9167": [60.98, -12.27, -35.77],
"1.2083": [30.98, -59.77, -35.77],
"1.3333": [32.05, -62.98, -35.77],
"1.5": [33.48, -67.27, -35.77],
"1.8333": [15.98, -79.77, -35.77],
"1.9167": [67.65, -129.77, -110.77],
"1.9583": [93.48, -154.77, -148.27],
"2.0833": [93.48, -174.77, -168.27],
"2.3333": [93.48, -169.77, -168.27]
}
},
"arm_right2": {
"rotation": {
"0.0": [0, -52.5, 0],
"1.0": [0, -52.5, 0],
"1.2083": [0, -57.5, 0],
"1.5": [0, -30, 0]
}
},
"finger_right": {
"rotation": [0, 0, -5]
},
"finger_right2": {
"rotation": [0, 0, 37.5]
},
"arm_left": {
"rotation": {
"0.0": [-84.39003, 24.58778, 53.5046],
@@ -547,30 +531,9 @@
"2.375": [-30.37, 0, -5]
}
},
"leg_right": {
"rotation": {
"0.0": [-13.6, 22.38, 10.45],
"0.1667": [-31.1, 22.38, 10.45],
"0.25": [-26.1, 22.38, 10.45],
"0.5": [-3.6, 22.38, 10.45],
"0.7917": [6.4, 22.38, 10.45],
"0.9167": [-31.1, 22.38, 10.45],
"1.2083": [-31.1, 42.38, 10.45],
"1.375": [-30, 0, 0],
"1.6667": [-30, 0, 5],
"1.875": [70, 0, 5],
"2.0417": [40.36, 0, 5],
"2.1667": [-30, 0, 5],
"2.25": [-45, 0, 5],
"2.375": [-35, 0, 5]
}
},
"finger_left3": {
"rotation": [0, 0, 57.5]
},
"finger_right3": {
"rotation": [0, 0, -20]
},
"hammer": {
"rotation": {
"0.0": [-0.78, -6.26, 38.97],
@@ -593,9 +556,6 @@
"skirt_left": {
"rotation": [0, 0, -15]
},
"skirt_right": {
"rotation": [-10, 0, 15]
},
"leg_left2": {
"rotation": {
"0.0": [20, 0, 0],
@@ -611,18 +571,6 @@
"2.0417": [15, 0, 0]
}
},
"leg_right2": {
"rotation": {
"0.0": [15, 0, -10],
"0.1667": [35, 0, -10],
"0.25": [-10, 0, -10],
"0.5": [27.5, 0, 5],
"0.7917": [5, 0, 5],
"0.9167": [35, 0, 5],
"1.375": [35, 0, 0],
"1.6667": [22.5, 0, 0]
}
},
"body": {
"rotation": {
"0.9167": [0, 0, 0],
@@ -851,134 +799,519 @@
},
"eyelid_left": {
"position": {
"0.2083": [0, 0, 0],
"0.25": [0, 0, -0.15],
"0.375": [0, 0, -0.15],
"0.4167": [0, 0, 0],
"0.9167": [0, 0, 0],
"0.9583": [0, 0, -0.15],
"1.75": [0, 0, -0.15],
"1.7917": [0, 0, 0],
"2.0": [0, 0, 0],
"2.0417": [0, 0, -0.15]
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.4167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"1.7917": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
}
}
},
"mouth_top": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0.5, 0]
},
"0.9167": {
"pre": [0, 0.5, 0],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0.5, 0]
},
"2.0417": {
"pre": [0, 0.5, 0],
"post": [0, 0, 0]
}
}
},
"eyelid_right": {
"position": {
"0.2083": [0, 0, 0],
"0.25": [0, 0, -0.15],
"0.375": [0, 0, -0.15],
"0.4167": [0, 0, 0],
"0.9167": [0, 0, 0],
"0.9583": [0, 0, -0.15],
"1.75": [0, 0, -0.15],
"1.7917": [0, 0, 0],
"2.0": [0, 0, 0],
"2.0417": [0, 0, -0.15]
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.4167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"1.7917": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
}
}
},
"mouth_open": {
"position": {
"0.2083": [0, 0, 0],
"0.25": [0, 0, -0.15],
"0.875": [0, 0, -0.15],
"0.9167": [0, 0, 0],
"1.25": [0, 0, 0],
"1.2917": [0, 0, -0.15],
"2.0": [0, 0, -0.15],
"2.0417": [0, 0, 0]
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.9167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"2.0417": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"mouth_closed": {
"position": {
"0.2083": [0, 0, 0],
"0.25": [0, 0, 0.1],
"0.875": [0, 0, 0.1],
"0.9167": [0, 0, 0],
"1.25": [0, 0, 0],
"1.2917": [0, 0, 0.1],
"2.0": [0, 0, 0.1],
"2.0417": [0, 0, 0]
}
}
}
},
"animation.tinkatuff.blink": {
"animation_length": 0.16667,
"bones": {
"eyelid_right": {
"position": {
"0.0": [0, 0, -0.1],
"0.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
"arm_right": {
"rotation": {
"0.0": [40.98303, 0.22836, -45.7651],
"0.2083": [5.98, 0.23, -45.77],
"0.2917": [35.98, 0.23, -45.77],
"0.75": [18.48, 5.23, -23.27],
"0.9167": [60.98, -12.27, -35.77],
"1.2083": [30.98, -59.77, -35.77],
"1.3333": [32.05, -62.98, -35.77],
"1.5": [33.48, -67.27, -35.77],
"1.8333": [15.98, -79.77, -35.77],
"1.9167": [67.65, -129.77, -110.77],
"1.9583": [93.48, -154.77, -148.27],
"2.0833": [93.48, -174.77, -168.27],
"2.3333": [93.48, -169.77, -168.27]
}
},
"eyelid_left": {
"arm_right2": {
"rotation": {
"0.0": [0, -52.5, 0],
"1.0": [0, -52.5, 0],
"1.2083": [0, -57.5, 0],
"1.5": [0, -30, 0]
}
},
"finger_right": {
"rotation": [0, 0, -5]
},
"finger_right2": {
"rotation": [0, 0, 37.5]
},
"finger_right3": {
"rotation": [0, 0, -20]
},
"skirt_right": {
"rotation": [-10, 0, 15]
},
"leg_right": {
"rotation": {
"0.0": [-13.6, 22.38, 10.45],
"0.1667": [-31.1, 22.38, 10.45],
"0.25": [-26.1, 22.38, 10.45],
"0.5": [-3.6, 22.38, 10.45],
"0.7917": [6.4, 22.38, 10.45],
"0.9167": [-31.1, 22.38, 10.45],
"1.2083": [-31.1, 42.38, 10.45],
"1.375": [-30, 0, 0],
"1.6667": [-30, 0, 5],
"1.875": [70, 0, 5],
"2.0417": [40.36, 0, 5],
"2.1667": [-30, 0, 5],
"2.25": [-45, 0, 5],
"2.375": [-35, 0, 5]
}
},
"leg_right2": {
"rotation": {
"0.0": [15, 0, -10],
"0.1667": [35, 0, -10],
"0.25": [-10, 0, -10],
"0.5": [27.5, 0, 5],
"0.7917": [5, 0, 5],
"0.9167": [35, 0, 5],
"1.375": [35, 0, 0],
"1.6667": [22.5, 0, 0]
}
},
"brow_left": {
"position": {
"0.0": [0, 0, -0.1],
"0.125": [0, 0, -0.1],
"0.1667": [0, 0, 0]
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"brow_right": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"mouth_bottom": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, -0.5, 0]
},
"0.9167": {
"pre": [0, -0.5, 0],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, -0.5, 0]
},
"2.0417": {
"pre": [0, -0.5, 0],
"post": [0, 0, 0]
}
}
},
"eye_emote_left": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"eye_emote_right": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"eyes_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.4167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"1.7917": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
}
}
},
"eyes_blink_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.4167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"0.9583": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"1.7917": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"2.0417": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"0.9167": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0, 0.1]
},
"2.0417": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"0.9167": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
},
"1.2917": {
"pre": [0, 0, 0],
"post": [0, 0, -0.1]
},
"2.0417": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
}
}
},
"animation.tinkatuff.cry": {
"animation_length": 0.91667,
"animation_length": 1.5,
"bones": {
"head": {
"rotation": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [-15, 0, 0],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [-15, 0, 0],
"lerp_mode": "catmullrom"
},
"0.9167": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
}
},
"mouth_closed": {
"position": {
"0.25": [0, 0, 0],
"0.3333": [0, 0, 0.1],
"0.5833": [0, 0, 0.1],
"0.6667": [0, 0, 0]
"0.0": [0, 0, 0],
"0.25": [-15, 0, 0],
"1.25": [-15, 0, 0],
"1.5": [0, 0, 0]
}
},
"mouth_open": {
"position": {
"0.0": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
},
"0.25": {
"post": [0, 0, -0.1],
"lerp_mode": "catmullrom"
},
"0.6667": {
"post": [0, 0, -0.1],
"lerp_mode": "catmullrom"
},
"0.9167": {
"post": [0, 0, 0],
"lerp_mode": "catmullrom"
}
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
},
"mouth_top": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0.5, 0]},
"1.3333": {"pre": [0, 0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_bottom": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, -0.5, 0]},
"1.3333": {"pre": [0, -0.5, 0], "post": [0, 0, 0]}
}
},
"mouth_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0, 0.1]},
"1.3333": {"pre": [0, 0, 0.1], "post": [0, 0, 0]}
}
},
"mouth_open_ditto": {
"position": {
"0.0": [0, 0, 0],
"0.25": {"pre": [0, 0, 0], "post": [0, 0, -0.1]},
"1.3333": {"pre": [0, 0, -0.1], "post": [0, 0, 0]}
}
}
},
"sound_effects": {
"0.1667": {
"0.0": {
"effect": "pokemon.tinkatuff.cry"
}
}
},
"animation.tinkatuff.blink": {
"animation_length": 0.1667,
"bones": {
"eyelid_right": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"eyelid_left": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
},
"brow_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"brow_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"eye_left": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"eye_right": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"eyes_ditto": {
"position": {
"0.0": [0, 0, 0.1],
"0.1667": {
"pre": [0, 0, 0.1],
"post": [0, 0, 0]
}
}
},
"eyes_blink_ditto": {
"position": {
"0.0": [0, 0, -0.1],
"0.1667": {
"pre": [0, 0, -0.1],
"post": [0, 0, 0]
}
}
}
}
},
"animation.tinkatuff.ditto_face": {
"loop": true,
"bones": {
"face": {
"position": [0, 0, 0.1],
"scale": 0
},
"face_ditto": {
"position": [0, 0, -0.1]
}
}
}
}
}
@@ -90,7 +90,7 @@
"parent": "chest",
"pivot": [0, 17, -5],
"cubes": [
{"origin": [-2.75, 16, -7.5], "size": [5.5, 5, 5], "uv": [22, 0]},
{"origin": [-2.25, 16, -7.5], "size": [5, 5, 5], "uv": [22, 0]},
{"origin": [0, 18, -2.5], "size": [0, 4, 2], "uv": [30, 37]}
]
},
@@ -486,7 +486,7 @@
"parent": "eye_left",
"pivot": [4.2, 34.1, -10.53],
"cubes": [
{"origin": [4.98, 33.99, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [132, 116]}
{"origin": [4.98, 34.01, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [132, 116]}
]
},
{
@@ -782,7 +782,7 @@
"parent": "eye_right",
"pivot": [-4.2, 34.1, -10.53],
"cubes": [
{"origin": [-7.98, 33.99, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [140, 116]}
{"origin": [-7.98, 34.01, -10.53], "size": [3, 1, 1], "inflate": 0.01, "uv": [140, 116]}
]
},
{
@@ -15,18 +15,58 @@
"name": "tinkatink",
"pivot": [0, 0, 0]
},
{
"name": "locator_root",
"parent": "tinkatink",
"pivot": [0, 0, 0],
"locators": {
"root": [0, 0, 0]
}
},
{
"name": "locator_top",
"parent": "tinkatink",
"pivot": [0, 14, 0],
"locators": {
"top": [0, 14, 0]
}
},
{
"name": "locator_special",
"parent": "tinkatink",
"pivot": [0, 6, -7],
"locators": {
"special": [0, 6, -7]
}
},
{
"name": "body",
"parent": "tinkatink",
"pivot": [0, 3.75, 0]
},
{
"name": "locator_target",
"parent": "body",
"pivot": [0, 6, -6],
"locators": {
"target": [0, 6, -6]
}
},
{
"name": "locator_middle",
"parent": "body",
"pivot": [0, 6, 0],
"locators": {
"middle": [0, 6, 0]
}
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 1.75, -0.25],
"pivot": [0, 2.5, -0.25],
"cubes": [
{"origin": [-2, 1.5, -2], "size": [4, 3, 4], "uv": [0, 12]},
{"origin": [-1, 2, -2.75], "size": [2, 2, 1], "pivot": [0, 3, -2.25], "rotation": [0, 0, 45], "uv": [12, 12]}
{"origin": [-1.5, 2, -1.5], "size": [3, 3, 3], "uv": [30, 6]},
{"origin": [-1, 1.5, -2.5], "size": [2, 2, 1], "pivot": [0, 2.5, -2], "rotation": [0, 0, 45], "uv": [47, 12]}
]
},
{
@@ -34,199 +74,509 @@
"parent": "torso",
"pivot": [0, 4.25, -0.25],
"cubes": [
{"origin": [-3.5, 4.25, -3.25], "size": [7, 6, 6], "uv": [0, 0]}
{"origin": [-4, 4.25, -3.75], "size": [8, 7, 7], "uv": [0, 0]}
]
},
{
"name": "hair3",
"name": "locator_item_hat",
"parent": "head",
"pivot": [0, 10.25, -0.25],
"rotation": [-5, 0, 0],
"cubes": [
{"origin": [-2.5, 10.25, -3.25], "size": [5, 0, 3], "uv": [11, 21]}
]
"pivot": [0, 12.25, -0.25],
"locators": {
"item_hat": [0, 12.25, -0.25]
}
},
{
"name": "hair4",
"parent": "hair3",
"pivot": [0, 10.25, -3.25],
"rotation": [-15, 0, 0],
"cubes": [
{"origin": [-2.5, 8.25, -3.25], "size": [5, 2, 0], "uv": [43, 0]}
]
},
{
"name": "eye_right",
"name": "locator_head",
"parent": "head",
"pivot": [-2.75, 6.5, -2.76],
"rotation": [0, 0, -5],
"pivot": [0, 11.25, -3.25],
"locators": {
"head": [0, 11.25, -3.25]
}
},
{
"name": "locator_mouth",
"parent": "head",
"pivot": [0, 5.7, -3.75],
"locators": {
"mouth": [0, 5.7, -3.75]
}
},
{
"name": "locator_item_face",
"parent": "head",
"pivot": [0, 8.25, -3.75],
"locators": {
"item_face": [0, 8.25, -3.75]
}
},
{
"name": "locator_face",
"parent": "head",
"pivot": [0, 7.25, -3.75],
"locators": {
"face": [0, 7.25, -3.75]
}
},
{
"name": "face_ditto",
"parent": "head",
"pivot": [0, 7, -3.65]
},
{
"name": "eyes_ditto",
"parent": "face_ditto",
"pivot": [0, 7.75, -3.67],
"cubes": [
{"origin": [-2.75, 6, -3.26], "size": [1, 2, 1], "uv": [51, 2]}
{"origin": [-3, 7.25, -3.67], "size": [6, 1, 0], "uv": [51, 23]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-0.5, 3.5, -0.15],
"name": "eyes_blink_ditto",
"parent": "face_ditto",
"pivot": [0, 7.75, -3.57],
"cubes": [
{"origin": [-2.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [47, 2]}
{"origin": [-3.5, 7.25, -3.57], "size": [7, 1, 0], "uv": [49, 27]},
{"origin": [-3, 7.75, -3.58], "size": [6, 1, 0], "uv": [51, 21]}
]
},
{
"name": "mouth_ditto",
"parent": "face_ditto",
"pivot": [0, 6, -3.65],
"cubes": [
{"origin": [-2.5, 5.25, -3.66], "size": [5, 1, 0], "uv": [53, 19]},
{"origin": [-3.5, 5.75, -3.66], "size": [7, 1, 0], "uv": [49, 25]}
]
},
{
"name": "mouth_open_ditto",
"parent": "face_ditto",
"pivot": [0, 5.75, -3.56],
"cubes": [
{"origin": [-3.5, 4.75, -3.56], "size": [7, 2, 0], "uv": [49, 29]}
]
},
{
"name": "face",
"parent": "head",
"pivot": [0, 6.75, -3.75]
},
{
"name": "eyes",
"parent": "face",
"pivot": [0, 6.75, -3.26]
},
{
"name": "brow_left",
"parent": "eyes",
"pivot": [2.25, 8.5, -3.25],
"cubes": [
{"origin": [1.75, 8, -3.75], "size": [1, 1, 1], "inflate": 0.01, "pivot": [2.25, 8.5, -3.25], "rotation": [0, 0, 5], "uv": [32, 29]}
]
},
{
"name": "brow_right",
"parent": "eyes",
"pivot": [-2.25, 8.5, -3.25],
"cubes": [
{"origin": [-2.75, 8, -3.75], "size": [1, 1, 1], "inflate": 0.01, "pivot": [-2.25, 8.5, -3.25], "rotation": [0, 0, -5], "uv": [32, 25]}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.75, 6.5, -2.76],
"rotation": [0, 0, 5],
"parent": "eyes",
"pivot": [2.5, 7.75, -3.26],
"cubes": [
{"origin": [1.75, 6, -3.26], "size": [1, 2, 1], "uv": [26, 7]}
{"origin": [2, 6.75, -3.75], "size": [1, 1, 1], "inflate": 0.01, "uv": [28, 29]}
]
},
{
"name": "locator_eye_left",
"parent": "eye_left",
"pivot": [2.5, 7.7, -3.75],
"locators": {
"eye2": [2.5, 7.7, -3.75]
}
},
{
"name": "eye_emote_left",
"parent": "eye_left",
"pivot": [2.5, 7.75, -3.75],
"cubes": [
{"origin": [2, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.025, "uv": [24, 29]}
]
},
{
"name": "eye_emote_left2",
"parent": "eye_left",
"pivot": [2.5, 7.75, -3.75],
"cubes": [
{"origin": [2, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.02, "uv": [20, 29]}
]
},
{
"name": "eye_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.26],
"cubes": [
{"origin": [-3, 6.75, -3.75], "size": [1, 1, 1], "inflate": 0.01, "uv": [28, 25]}
]
},
{
"name": "locator_eye_right",
"parent": "eye_right",
"pivot": [-2.5, 7.7, -3.75],
"locators": {
"eye1": [-2.5, 7.7, -3.75]
}
},
{
"name": "eye_emote_right",
"parent": "eye_right",
"pivot": [-2.5, 7.75, -3.75],
"cubes": [
{"origin": [-3, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.025, "uv": [24, 25]}
]
},
{
"name": "eye_emote_right2",
"parent": "eye_right",
"pivot": [-2.5, 7.75, -3.75],
"cubes": [
{"origin": [-3, 7.75, -3.75], "size": [1, 1, 1], "inflate": 0.02, "uv": [20, 25]}
]
},
{
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [0.5, 3.5, -0.15],
"parent": "eyes",
"pivot": [2.5, 7.75, -3.16],
"cubes": [
{"origin": [1.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [32, 8]}
{"origin": [1.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [0, 28]}
]
},
{
"name": "hair",
"name": "eyelid_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.16],
"cubes": [
{"origin": [-3.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [0, 24]}
]
},
{
"name": "eyelid_happy_left",
"parent": "eyes",
"pivot": [2.5, 7.75, -3.16],
"cubes": [
{"origin": [1, 6.75, -3.66], "size": [3, 2, 1], "uv": [12, 28]}
]
},
{
"name": "eyelid_happy_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.16],
"cubes": [
{"origin": [-4, 6.75, -3.66], "size": [3, 2, 1], "uv": [12, 24]}
]
},
{
"name": "eyelid_hurt_left",
"parent": "eyes",
"pivot": [2.5, 7.75, -3.16],
"cubes": [
{"origin": [1.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [6, 28]}
]
},
{
"name": "eyelid_hurt_right",
"parent": "eyes",
"pivot": [-2.5, 7.75, -3.16],
"cubes": [
{"origin": [-3.5, 6.75, -3.65], "size": [2, 2, 1], "inflate": 0.03, "uv": [6, 24]}
]
},
{
"name": "mouths",
"parent": "face",
"pivot": [0, 4.25, -0.75]
},
{
"name": "mouth_closed",
"parent": "mouths",
"pivot": [0, 5.75, -3.25],
"cubes": [
{"origin": [-1.5, 4.75, -3.76], "size": [3, 1, 1], "inflate": 0.02, "uv": [38, 13]},
{"origin": [-0.5, 5.25, -3.76], "size": [1, 1, 1], "inflate": 0.04, "uv": [46, 16]}
]
},
{
"name": "mouth_lip_top",
"parent": "mouth_closed",
"pivot": [0, 6.25, -3.25],
"cubes": [
{"origin": [-1, 5.75, -3.77], "size": [2, 1, 1], "uv": [39, 16]},
{"origin": [-2, 5.25, -3.76], "size": [4, 1, 1], "uv": [29, 22]}
]
},
{
"name": "mouth_open_cry",
"parent": "mouths",
"pivot": [0.4, 4.25, -1.75],
"cubes": [
{"origin": [-2, 4.75, -3.65], "size": [4, 2, 1], "inflate": 0.01, "uv": [29, 19]}
]
},
{
"name": "mouth_open_happy",
"parent": "mouths",
"pivot": [0.4, 4.25, -1.75],
"cubes": [
{"origin": [-2, 4.75, -3.65], "size": [4, 2, 1], "inflate": 0.01, "uv": [40, 19]},
{"origin": [-1.5, 4.75, -3.65], "size": [3, 1, 1], "inflate": 0.02, "uv": [40, 22]},
{"origin": [-0.5, 5.4, -3.65], "size": [1, 1, 1], "inflate": 0.03, "uv": [42, 7]}
]
},
{
"name": "hair_main",
"parent": "head",
"pivot": [0, 10.25, 0.25],
"pivot": [0, 10.75, -0.75]
},
{
"name": "hair",
"parent": "hair_main",
"pivot": [0, 10.75, -0.75],
"rotation": [12.5, 0, 0],
"cubes": [
{"origin": [0, 9.75, -0.75], "size": [0, 2, 1], "uv": [4, 0]}
{"origin": [-0.5, 10.25, -1.75], "size": [1, 2, 1], "uv": [25, 15]}
]
},
{
"name": "hair2",
"parent": "hair",
"pivot": [0, 11.75, 0.25],
"rotation": [22.5, 0, 0],
"pivot": [1, 12.25, -0.75],
"rotation": [35, 0, 0],
"cubes": [
{"origin": [0, 11.75, -1.75], "size": [0, 3, 2], "inflate": 0.01, "uv": [0, 10]}
{"origin": [-1, 12.25, -2.25], "size": [2, 3, 2], "inflate": 0.01, "uv": [30, 13]}
]
},
{
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 4.25, -0.25],
"name": "hair3",
"parent": "hair_main",
"pivot": [0, 11.25, -0.75],
"rotation": [-2.5, 0, 0],
"cubes": [
{"origin": [-2.5, 4.75, -3.2575], "size": [5, 2, 0], "inflate": 0.001, "uv": [26, 5]}
{"origin": [-2.5, 11.25, -3.75], "size": [5, 0, 3], "uv": [34, 25]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [-0.1, 4.25, -1.25],
"name": "hair4",
"parent": "hair3",
"pivot": [0, 11.25, -3.75],
"rotation": [-7.5, 0, 0],
"cubes": [
{"origin": [-1.5, 4.75, -3.1575], "size": [3, 2, 0], "uv": [25, 12]}
{"origin": [-3, 9.25, -3.75], "size": [6, 2, 0], "uv": [36, 29]},
{"origin": [-0.5, 9.25, -3.75], "size": [1, 2, 0], "inflate": 0.01, "uv": [43, 10]}
]
},
{
"name": "arm_hammer_left",
"name": "arms",
"parent": "torso",
"pivot": [2, 3.25, 0]
},
{
"name": "hammer",
"parent": "arm_hammer_left",
"pivot": [6.75, 3, -0.5]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [6.75, 7.41875, -0.525],
"cubes": [
{"origin": [5.25, 5.25, -2], "size": [3, 6, 3], "uv": [16, 12]},
{"origin": [6.25, 1.75, -1], "size": [1, 4, 1], "uv": [0, 0]},
{"origin": [5.75, 7, -5.65], "size": [2, 0, 2], "pivot": [6.5, 6.4375, -2.575], "rotation": [-90, 0, 0], "uv": [22, 22]},
{"origin": [6.25, 6.925, -5.8], "size": [1, 0, 1], "pivot": [6.5, 6.4375, -2.575], "rotation": [-90, 0, 0], "uv": [23, 21]}
]
"pivot": [0, 3.25, 0]
},
{
"name": "arm_left",
"parent": "torso",
"pivot": [2, 3.25, 0],
"parent": "arms",
"pivot": [1.5, 3.25, 0],
"cubes": [
{"origin": [2, 2.25, -1.5], "size": [4, 2, 3], "uv": [0, 19]}
{"origin": [1.25, 2.25, -1], "size": [2, 2, 2], "uv": [8, 19]}
]
},
{
"name": "finger_left",
"name": "hand_left",
"parent": "arm_left",
"pivot": [6, 3.5, 0],
"pivot": [3.25, 3.25, 0],
"cubes": [
{"origin": [6, 2.5, -0.5], "size": [1, 1, 1], "uv": [26, 10]}
{"origin": [3.25, 2.25, -1.5], "size": [3, 2, 3], "inflate": 0.25, "uv": [12, 14]}
]
},
{
"name": "locator_hand_secondary",
"parent": "hand_left",
"pivot": [6, 3.25, 0],
"rotation": [0, -90, 0],
"locators": {
"hand_secondary": [6, 3.25, 0]
}
},
{
"name": "fingers_left",
"parent": "hand_left",
"pivot": [6.5, 3.85, 0]
},
{
"name": "finger_left",
"parent": "fingers_left",
"pivot": [6.5, 3.85, 0],
"cubes": [
{"origin": [6.5, 2.85, -0.5], "size": [1, 1, 1], "inflate": 0.1, "uv": [20, 21]}
]
},
{
"name": "finger_left2",
"parent": "arm_left",
"pivot": [6, 3.5, -0.5],
"rotation": [0, 12.5, 0],
"parent": "fingers_left",
"pivot": [6.5, 3.85, -0.6],
"rotation": [0, 17.5, 0],
"cubes": [
{"origin": [6, 2.5, -1.5], "size": [1, 1, 1], "uv": [43, 2]}
{"origin": [6.5, 2.85, -1.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [16, 21]}
]
},
{
"name": "finger_left3",
"parent": "arm_left",
"pivot": [6, 3.5, 0.5],
"rotation": [0, -12.5, 0],
"parent": "fingers_left",
"pivot": [6.5, 3.85, 0.6],
"rotation": [0, -17.5, 0],
"cubes": [
{"origin": [6, 2.5, 0.5], "size": [1, 1, 1], "uv": [11, 19]}
{"origin": [6.5, 2.85, 0.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [24, 21]}
]
},
{
"name": "arm_right",
"parent": "torso",
"pivot": [-2, 3.25, 0],
"parent": "arms",
"pivot": [-1.5, 3.25, 0],
"cubes": [
{"origin": [-6, 2.25, -1.5], "size": [4, 2, 3], "uv": [20, 0]}
{"origin": [-3.25, 2.25, -1], "size": [2, 2, 2], "uv": [0, 19]}
]
},
{
"name": "finger_right",
"name": "hand_right",
"parent": "arm_right",
"pivot": [-6, 3.5, 0],
"pivot": [-3.25, 3.25, 0],
"cubes": [
{"origin": [-7, 2.5, -0.5], "size": [1, 1, 1], "uv": [28, 14]}
{"origin": [-6.25, 2.25, -1.5], "size": [3, 2, 3], "inflate": 0.25, "uv": [0, 14]}
]
},
{
"name": "locator_hand_primary",
"parent": "hand_right",
"pivot": [-6, 3.25, 0],
"rotation": [0, 90, 0],
"locators": {
"hand_primary": [-6, 3.25, 0]
}
},
{
"name": "locator_item",
"parent": "hand_right",
"pivot": [-6, 2.25, 0],
"locators": {
"item": [-6, 2.25, 0]
}
},
{
"name": "fingers_right",
"parent": "hand_right",
"pivot": [-6.5, 3.85, 0]
},
{
"name": "finger_right",
"parent": "fingers_right",
"pivot": [-6.5, 3.85, 0],
"cubes": [
{"origin": [-7.5, 2.85, -0.5], "size": [1, 1, 1], "inflate": 0.1, "uv": [20, 19]}
]
},
{
"name": "finger_right2",
"parent": "arm_right",
"pivot": [-6, 3.5, -0.5],
"rotation": [0, -12.5, 0],
"parent": "fingers_right",
"pivot": [-6.5, 3.85, -0.6],
"rotation": [0, -17.5, 0],
"cubes": [
{"origin": [-7, 2.5, -1.5], "size": [1, 1, 1], "uv": [56, 9]}
{"origin": [-7.5, 2.85, -1.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [16, 19]}
]
},
{
"name": "finger_right3",
"parent": "arm_right",
"pivot": [-6, 3.5, 0.5],
"rotation": [0, 12.5, 0],
"parent": "fingers_right",
"pivot": [-6.5, 3.85, 0.6],
"rotation": [0, 17.5, 0],
"cubes": [
{"origin": [-7, 2.5, 0.5], "size": [1, 1, 1], "uv": [52, 9]}
{"origin": [-7.5, 2.85, 0.7], "size": [1, 1, 1], "inflate": 0.1, "uv": [24, 19]}
]
},
{
"name": "arm_hammer_left",
"parent": "arms",
"pivot": [1.5, 3.25, 0]
},
{
"name": "hammer",
"parent": "arm_hammer_left",
"pivot": [7.25, 3, -0.5]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [7.5, 7.41875, -0.525],
"cubes": [
{"origin": [7, 1.25, -1], "size": [1, 4, 1], "uv": [54, 12]},
{"origin": [7, 1.25, -1], "size": [1, 4, 1], "inflate": 0.1, "uv": [59, 12]}
]
},
{
"name": "rattle",
"parent": "hammer2",
"pivot": [7.5, 9.75, -2],
"cubes": [
{"origin": [7, 9.25, -2.5], "size": [1, 1, 1], "inflate": 0.01, "pivot": [7.5, 9.75, -2], "rotation": [0, 0, 45], "uv": [60, 1]},
{"origin": [6.5, 7.25, -2.4], "size": [2, 2, 1], "inflate": 0.11, "pivot": [7.5, 8.25, -1.9], "rotation": [0, 0, 45], "uv": [46, 0]},
{"origin": [5.5, 4.75, -2.5], "size": [4, 7, 4], "uv": [48, 0]}
]
},
{
"name": "locator_physical",
"parent": "rattle",
"pivot": [7.5, 11.75, -0.5],
"locators": {
"physical": [7.5, 11.75, -0.5]
}
},
{
"name": "legs",
"parent": "body",
"pivot": [0, 1.5, 0]
},
{
"name": "leg_left",
"parent": "body",
"pivot": [0.75, 1.5, 0],
"parent": "legs",
"pivot": [1.25, 1.5, 0],
"cubes": [
{"origin": [0.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [35, 0]}
{"origin": [-0.25, -0.25, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [35, 0]}
]
},
{
"name": "locator_foot_secondary",
"parent": "leg_left",
"pivot": [1.4, 0.5, 0.1],
"rotation": [90, 0, 0],
"locators": {
"foot_secondary": [1.4, 0.5, 0.1]
}
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-0.75, 1.5, 0],
"parent": "legs",
"pivot": [-1.25, 1.5, 0],
"cubes": [
{"origin": [-2.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [52, 3]}
{"origin": [-2.75, -0.25, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [23, 0]}
]
},
{
"name": "locator_foot_primary",
"parent": "leg_right",
"pivot": [-1.4, 0.5, 0.1],
"rotation": [90, 0, 0],
"locators": {
"foot_primary": [-1.4, 0.5, 0.1]
}
}
]
}
@@ -1,233 +0,0 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.tinkatink_dot",
"texture_width": 64,
"texture_height": 32,
"visible_bounds_width": 2,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "tinkatink",
"pivot": [0, 0, 0]
},
{
"name": "body",
"parent": "tinkatink",
"pivot": [0, 3.75, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 1.75, -0.25],
"cubes": [
{"origin": [-2, 1.5, -2], "size": [4, 3, 4], "uv": [0, 12]},
{"origin": [-1, 2, -2.75], "size": [2, 2, 1], "pivot": [0, 3, -2.25], "rotation": [0, 0, 45], "uv": [12, 12]}
]
},
{
"name": "head",
"parent": "torso",
"pivot": [0, 4.25, -0.25],
"cubes": [
{"origin": [-3.5, 4.25, -3.25], "size": [7, 6, 6], "uv": [0, 0]}
]
},
{
"name": "hair3",
"parent": "head",
"pivot": [0, 10.25, -0.25],
"rotation": [-5, 0, 0],
"cubes": [
{"origin": [-2.5, 10.25, -3.25], "size": [5, 0, 3], "uv": [11, 21]}
]
},
{
"name": "hair4",
"parent": "hair3",
"pivot": [0, 10.25, -3.25],
"rotation": [-15, 0, 0],
"cubes": [
{"origin": [-2.5, 8.25, -3.25], "size": [5, 2, 0], "uv": [43, 0]}
]
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.75, 6.5, -2.76],
"rotation": [0, 0, -5],
"cubes": [
{"origin": [-2.75, 6, -3.26], "size": [1, 2, 1], "uv": [51, 2]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-0.5, 3.5, -0.15],
"cubes": [
{"origin": [-2.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [47, 2]}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.75, 6.5, -2.76],
"rotation": [0, 0, 5],
"cubes": [
{"origin": [1.75, 6, -3.26], "size": [1, 2, 1], "uv": [26, 7]}
]
},
{
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [0.5, 3.5, -0.15],
"cubes": [
{"origin": [1.75, 6, -3.16], "size": [1, 2, 1], "inflate": 0.01, "uv": [32, 8]}
]
},
{
"name": "hair",
"parent": "head",
"pivot": [0, 10.25, 0.25],
"rotation": [12.5, 0, 0],
"cubes": [
{"origin": [0, 9.75, -0.75], "size": [0, 2, 1], "uv": [4, 0]}
]
},
{
"name": "hair2",
"parent": "hair",
"pivot": [0, 11.75, 0.25],
"rotation": [22.5, 0, 0],
"cubes": [
{"origin": [0, 11.75, -1.75], "size": [0, 3, 2], "inflate": 0.01, "uv": [0, 10]}
]
},
{
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 4.25, -0.25],
"cubes": [
{"origin": [-2.5, 4.75, -3.2575], "size": [5, 2, 0], "inflate": 0.001, "uv": [26, 5]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [-0.1, 4.25, -1.25],
"cubes": [
{"origin": [-1.5, 4.75, -3.1575], "size": [3, 2, 0], "uv": [25, 12]}
]
},
{
"name": "arm_hammer_left",
"parent": "torso",
"pivot": [2, 3.25, 0]
},
{
"name": "hammer",
"parent": "arm_hammer_left",
"pivot": [6.75, 3, -0.5]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [6.75, 7.41875, -0.525],
"cubes": [
{"origin": [5.25, 5.25, -2], "size": [3, 6, 3], "uv": [16, 12]},
{"origin": [6.25, 1.75, -1], "size": [1, 4, 1], "uv": [0, 0]},
{"origin": [5.75, 8.2625, -3.0125], "size": [2, 0, 2], "pivot": [6.75, 8.2625, -2.0125], "rotation": [-90, 0, 45], "uv": [-2, 24]}
]
},
{
"name": "arm_left",
"parent": "torso",
"pivot": [2, 3.25, 0],
"cubes": [
{"origin": [2, 2.25, -1.5], "size": [4, 2, 3], "uv": [0, 19]}
]
},
{
"name": "finger_left",
"parent": "arm_left",
"pivot": [6, 3.5, 0],
"cubes": [
{"origin": [6, 2.5, -0.5], "size": [1, 1, 1], "uv": [26, 10]}
]
},
{
"name": "finger_left2",
"parent": "arm_left",
"pivot": [6, 3.5, -0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [6, 2.5, -1.5], "size": [1, 1, 1], "uv": [43, 2]}
]
},
{
"name": "finger_left3",
"parent": "arm_left",
"pivot": [6, 3.5, 0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [6, 2.5, 0.5], "size": [1, 1, 1], "uv": [11, 19]}
]
},
{
"name": "arm_right",
"parent": "torso",
"pivot": [-2, 3.25, 0],
"cubes": [
{"origin": [-6, 2.25, -1.5], "size": [4, 2, 3], "uv": [20, 0]}
]
},
{
"name": "finger_right",
"parent": "arm_right",
"pivot": [-6, 3.5, 0],
"cubes": [
{"origin": [-7, 2.5, -0.5], "size": [1, 1, 1], "uv": [28, 14]}
]
},
{
"name": "finger_right2",
"parent": "arm_right",
"pivot": [-6, 3.5, -0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-7, 2.5, -1.5], "size": [1, 1, 1], "uv": [56, 9]}
]
},
{
"name": "finger_right3",
"parent": "arm_right",
"pivot": [-6, 3.5, 0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-7, 2.5, 0.5], "size": [1, 1, 1], "uv": [52, 9]}
]
},
{
"name": "leg_left",
"parent": "body",
"pivot": [0.75, 1.5, 0],
"cubes": [
{"origin": [0.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [35, 0]}
]
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-0.75, 1.5, 0],
"cubes": [
{"origin": [-2.25, 0, -2], "size": [2, 2, 4], "inflate": 0.01, "uv": [52, 3]}
]
}
]
}
]
}
@@ -4,7 +4,7 @@
{
"description": {
"identifier": "geometry.tinkatuff",
"texture_width": 64,
"texture_width": 128,
"texture_height": 64,
"visible_bounds_width": 3,
"visible_bounds_height": 2.5,
@@ -15,289 +15,680 @@
"name": "tinkatuff",
"pivot": [0, 0, 0]
},
{
"name": "locator_root",
"parent": "tinkatuff",
"pivot": [0, 0, 0],
"locators": {
"root": [0, 0, 0]
}
},
{
"name": "locator_top",
"parent": "tinkatuff",
"pivot": [0, 22, 0],
"locators": {
"top": [0, 22, 0]
}
},
{
"name": "locator_special",
"parent": "tinkatuff",
"pivot": [0, 8, -8],
"locators": {
"special": [0, 8, -8]
}
},
{
"name": "body",
"parent": "tinkatuff",
"pivot": [0, 6, 0]
"pivot": [0, 6.25, 0]
},
{
"name": "locator_target",
"parent": "body",
"pivot": [0, 8, -6],
"locators": {
"target": [0, 8, -6]
}
},
{
"name": "locator_middle",
"parent": "body",
"pivot": [0, 9, 0],
"locators": {
"middle": [0, 9, 0]
}
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 4.25, 0],
"pivot": [0, 4.5, 0],
"cubes": [
{"origin": [-2, 7.5, -1.5], "size": [4, 3, 3], "uv": [41, 41]},
{"origin": [-2.5, 3, -2], "size": [5, 5, 4], "uv": [36, 0]}
{"origin": [-2.5, 3.25, -2], "size": [5, 3, 4], "inflate": 0.25, "uv": [0, 14]},
{"origin": [-2.5, 3.25, -2], "size": [5, 3, 4], "inflate": 0.5, "uv": [18, 14]}
]
},
{
"name": "skirt_left",
"name": "chest",
"parent": "torso",
"pivot": [2.5, 3, 0],
"rotation": [0, 0, 45],
"pivot": [0, 6, 0],
"cubes": [
{"origin": [2.5, 3, -1.5], "size": [3, 0, 3], "uv": [6, 15]}
]
},
{
"name": "skirt_right",
"parent": "torso",
"pivot": [-2.5, 3, 0],
"rotation": [0, 0, -45],
"cubes": [
{"origin": [-5.5, 3, -1.5], "size": [3, 0, 3], "uv": [0, 15]}
]
},
{
"name": "arm_left",
"parent": "torso",
"pivot": [2, 8, 0],
"cubes": [
{"origin": [1, 7, -1], "size": [4, 2, 2], "uv": [35, 47]}
]
},
{
"name": "arm_left2",
"parent": "arm_left",
"pivot": [5, 9, 1],
"cubes": [
{"origin": [5, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 35]}
]
},
{
"name": "finger_left",
"parent": "arm_left2",
"pivot": [9, 7.75, -0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [9, 7.75, -1.5], "size": [1, 1, 1], "uv": [33, 44]}
]
},
{
"name": "finger_left2",
"parent": "arm_left2",
"pivot": [9, 7.75, 0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [9, 7.75, 0.5], "size": [1, 1, 1], "uv": [40, 30]}
]
},
{
"name": "finger_left3",
"parent": "arm_left2",
"pivot": [9, 8, 0],
"cubes": [
{"origin": [9, 7, -0.5], "size": [1, 1, 1], "uv": [36, 30]}
]
},
{
"name": "arm_hammer_right",
"parent": "torso",
"pivot": [-2, 8, 0]
},
{
"name": "arm_hammer_right2",
"parent": "arm_hammer_right",
"pivot": [-5, 9, 1]
},
{
"name": "hammer",
"parent": "arm_hammer_right2",
"pivot": [-9.75, 8, 0]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [-9.55, 7.9675, -9.0675],
"cubes": [
{"origin": [-11, 6.5, -20], "size": [3, 3, 6], "uv": [30, 9]},
{"origin": [-10.5, 6.475, -18.25], "size": [2, 0, 2], "uv": [-1, 54]},
{"origin": [-10, 6.4, -18.4], "size": [1, 0, 1], "uv": [-1, 54]},
{"origin": [-11, 6.5, -12.5], "size": [3, 3, 3], "uv": [0, 47]},
{"origin": [-10, 7.5, -14.5], "size": [1, 1, 18], "inflate": 0.001, "uv": [0, 0]},
{"origin": [-15.5, 4.025, -18.525], "size": [12, 11, 0], "pivot": [-9.5, 9.525, -18.525], "rotation": [-90, -180, 0], "uv": [0, 36]},
{"origin": [-15.5, 3.5, -30.5], "size": [0, 8, 5], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [34, 31]},
{"origin": [-15.5, 3.5, -30.5], "size": [3, 8, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [47, 47]},
{"origin": [-7.5, 2.5, -30.5], "size": [4, 9, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [12, 47]},
{"origin": [-3.5, 2.525, -20.025], "size": [0, 9, 5], "pivot": [-3.5, 7.025, -17.525], "rotation": [90, 180, 0], "uv": [24, 31]},
{"origin": [-13.5, 12.5, -29.5], "size": [8, 1, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [0, 7]},
{"origin": [-13.5, 7.525, -26.025], "size": [8, 0, 4], "pivot": [-9.5, 7.525, -24.025], "rotation": [90, 180, 0], "uv": [17, 19]}
]
},
{
"name": "arm_right",
"parent": "torso",
"pivot": [-2, 8, 0],
"cubes": [
{"origin": [-5, 7, -1], "size": [4, 2, 2], "uv": [0, 32]}
]
},
{
"name": "arm_right2",
"parent": "arm_right",
"pivot": [-5, 9, 1],
"cubes": [
{"origin": [-9, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 30]}
]
},
{
"name": "finger_right",
"parent": "arm_right2",
"pivot": [-9, 7.75, -0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-10, 7.75, -1.5], "size": [1, 1, 1], "uv": [36, 2]}
]
},
{
"name": "finger_right2",
"parent": "arm_right2",
"pivot": [-9, 7.75, 0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-10, 7.75, 0.5], "size": [1, 1, 1], "uv": [36, 0]}
]
},
{
"name": "finger_right3",
"parent": "arm_right2",
"pivot": [-9, 8, 0],
"cubes": [
{"origin": [-10, 7, -0.5], "size": [1, 1, 1], "uv": [10, 32]}
{"origin": [-2, 5.75, -2], "size": [4, 4, 4], "uv": [24, 0]}
]
},
{
"name": "head",
"parent": "torso",
"pivot": [0, 9, 0.5],
"parent": "chest",
"pivot": [0, 8.75, 0.5],
"cubes": [
{"origin": [-3.5, 9, -3.5], "size": [7, 6, 7], "uv": [0, 19]},
{"origin": [-4, 17.30092, -3.63266], "size": [8, 0, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [12, 0]},
{"origin": [4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [20, 0]},
{"origin": [-4, 10.30092, 4.36734], "size": [8, 7, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]},
{"origin": [-4, 11.30092, -3.63266], "size": [8, 6, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [42, 9]},
{"origin": [-4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]}
{"origin": [-4, 8.75, -4], "size": [8, 6, 8], "uv": [0, 0]}
]
},
{
"name": "locator_mouth",
"parent": "head",
"pivot": [0, 9.75, -4],
"locators": {
"mouth": [0, 9.75, -4]
}
},
{
"name": "locator_item_face",
"parent": "head",
"pivot": [0, 12.25, -4],
"locators": {
"item_face": [0, 12.25, -4]
}
},
{
"name": "locator_face",
"parent": "head",
"pivot": [0, 11.75, -4],
"locators": {
"face": [0, 11.75, -4]
}
},
{
"name": "face_ditto",
"parent": "head",
"pivot": [0, 11, -3.9]
},
{
"name": "eyes_ditto",
"parent": "face_ditto",
"pivot": [0, 11.75, -3.92],
"cubes": [
{"origin": [-3, 11.25, -3.92], "size": [6, 1, 0], "uv": [22, 49]}
]
},
{
"name": "eyes_blink_ditto",
"parent": "face_ditto",
"pivot": [0, 11.75, -3.82],
"cubes": [
{"origin": [-3.5, 11.25, -3.82], "size": [7, 1, 0], "uv": [21, 51]},
{"origin": [-3, 11.75, -3.83], "size": [6, 1, 0], "uv": [22, 53]}
]
},
{
"name": "mouth_ditto",
"parent": "face_ditto",
"pivot": [0, 10, -3.9],
"cubes": [
{"origin": [-2.5, 9.25, -3.91], "size": [5, 1, 0], "uv": [23, 57]},
{"origin": [-3.5, 9.75, -3.91], "size": [7, 1, 0], "uv": [21, 55]}
]
},
{
"name": "mouth_open_ditto",
"parent": "face_ditto",
"pivot": [0, 9.75, -3.81],
"cubes": [
{"origin": [-3.5, 8.75, -3.81], "size": [7, 2, 0], "uv": [21, 59]}
]
},
{
"name": "face",
"parent": "head",
"pivot": [0, 11.75, -4.01]
},
{
"name": "eyes",
"parent": "face",
"pivot": [0, 12, -3.51]
},
{
"name": "brow_left",
"parent": "eyes",
"pivot": [2.25, 12.75, -3.5],
"cubes": [
{"origin": [1.75, 12.25, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [16, 52]}
]
},
{
"name": "brow_right",
"parent": "eyes",
"pivot": [-2.25, 12.75, -3.5],
"cubes": [
{"origin": [-2.75, 12.25, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [11, 52], "mirror": true}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.25, 12.25, -3.01],
"rotation": [0, 0, -7.5],
"parent": "eyes",
"pivot": [2.5, 12, -3.51],
"cubes": [
{"origin": [1.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [21, 23]}
{"origin": [2, 11, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [6, 52]}
]
},
{
"name": "eyelid_left",
"name": "locator_eye_left",
"parent": "eye_left",
"pivot": [2.25, 12.25, -2.91],
"pivot": [2.5, 12, -4],
"locators": {
"eye2": [2.5, 12, -4]
}
},
{
"name": "eye_emote_left",
"parent": "eye_left",
"pivot": [2.5, 12, -4],
"cubes": [
{"origin": [1.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [26, 15]}
{"origin": [2, 12, -4], "size": [1, 1, 1], "inflate": 0.025, "uv": [6, 49]}
]
},
{
"name": "eye_emote_left2",
"parent": "eye_left",
"pivot": [2.5, 12, -4],
"cubes": [
{"origin": [2, 12, -4], "size": [1, 1, 1], "inflate": 0.02, "uv": [16, 49]}
]
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.25, 12.25, -3.01],
"rotation": [0, 0, 7.5],
"parent": "eyes",
"pivot": [-2.5, 12, -3.51],
"cubes": [
{"origin": [-2.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [0, 21]}
{"origin": [-3, 11, -4], "size": [1, 1, 1], "inflate": 0.01, "uv": [1, 52], "mirror": true}
]
},
{
"name": "locator_eye_right",
"parent": "eye_right",
"pivot": [-2.5, 12, -4],
"locators": {
"eye1": [-2.5, 12, -4]
}
},
{
"name": "eye_emote_right",
"parent": "eye_right",
"pivot": [-2.5, 12, -4],
"cubes": [
{"origin": [-3, 12, -4], "size": [1, 1, 1], "inflate": 0.025, "uv": [1, 49], "mirror": true}
]
},
{
"name": "eye_emote_right2",
"parent": "eye_right",
"pivot": [-2.5, 12, -4],
"cubes": [
{"origin": [-3, 12, -4], "size": [1, 1, 1], "inflate": 0.02, "uv": [11, 49], "mirror": true}
]
},
{
"name": "eyelid_left",
"parent": "eyes",
"pivot": [2.5, 12, -3.41],
"cubes": [
{"origin": [1.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [8, 45]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-2.25, 12.25, -2.91],
"parent": "eyes",
"pivot": [-2.5, 12, -3.41],
"cubes": [
{"origin": [-2.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [3, 23]}
{"origin": [-3.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [1, 45], "mirror": true}
]
},
{
"name": "eyelid_hurt_left",
"parent": "eyes",
"pivot": [2.5, 12, -3.41],
"cubes": [
{"origin": [1.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [22, 45]}
]
},
{
"name": "eyelid_hurt_right",
"parent": "eyes",
"pivot": [-2.5, 12, -3.41],
"cubes": [
{"origin": [-3.5, 11, -3.9], "size": [2, 2, 1], "inflate": 0.03, "uv": [15, 45], "mirror": true}
]
},
{
"name": "eyelid_happy_left",
"parent": "eyes",
"pivot": [2.5, 12, -3.41],
"cubes": [
{"origin": [1, 11, -3.91], "size": [3, 2, 1], "uv": [38, 45]}
]
},
{
"name": "eyelid_happy_right",
"parent": "eyes",
"pivot": [-2.5, 12, -3.41],
"cubes": [
{"origin": [-4, 11, -3.91], "size": [3, 2, 1], "uv": [29, 45], "mirror": true}
]
},
{
"name": "mouths",
"parent": "face",
"pivot": [0, 10.25, -3.91],
"cubes": [
{"origin": [-1.5, 9.75, -4], "size": [3, 1, 1], "inflate": 0.01, "uv": [1, 55]}
]
},
{
"name": "mouth_top",
"parent": "mouths",
"pivot": [0, 11.25, -4.01],
"cubes": [
{"origin": [-0.5, 10.27, -4], "size": [1, 1, 1], "inflate": 0.03, "uv": [10, 55]}
]
},
{
"name": "mouth_bottom",
"parent": "mouths",
"pivot": [0, 10.25, -4.01],
"cubes": [
{"origin": [-0.5, 9.23, -4], "size": [1, 1, 1], "inflate": 0.03, "uv": [10, 59]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [0, 10.5, -3.41],
"parent": "mouths",
"pivot": [0, 10.25, -3.91],
"cubes": [
{"origin": [-1.5, 9.5, -3.41], "size": [3, 2, 0], "uv": [20, 15]}
{"origin": [-1.5, 9.25, -3.9], "size": [3, 2, 1], "inflate": 0.02, "uv": [1, 58]}
]
},
{
"name": "mouth_closed",
"name": "hair",
"parent": "head",
"pivot": [0, 10.5, -3.51],
"pivot": [0, 17.25, 0.7],
"rotation": [-10, 0, 0],
"cubes": [
{"origin": [-1.5, 9.5, -3.51], "size": [3, 2, 0], "uv": [0, 19]}
{"origin": [4.5, 10.25, -3.8], "size": [0, 3, 9], "pivot": [4.5, 13.25, 0.7], "rotation": [0, 0, 9], "uv": [49, 47]},
{"origin": [-4.5, 10.25, -3.8], "size": [0, 3, 9], "pivot": [-4.5, 13.25, 0.7], "rotation": [0, 0, -9], "uv": [49, 51], "mirror": true},
{"origin": [-4.5, 13.25, -3.8], "size": [9, 4, 9], "uv": [33, 0]},
{"origin": [-2.5, 10.25, -3.8], "size": [5, 3, 0], "pivot": [0, 13.25, -3.8], "rotation": [13.5, 0, 0], "uv": [53, 48]},
{"origin": [0.5, 10.25, 5.2], "size": [4, 3, 0], "pivot": [4.5, 13.25, 5.2], "rotation": [0, 0, 9], "uv": [49, 52]},
{"origin": [-4.5, 10.25, 5.2], "size": [4, 3, 0], "pivot": [-4.5, 13.25, 5.2], "rotation": [0, 0, -9], "uv": [59, 52], "mirror": true}
]
},
{
"name": "locator_head",
"parent": "hair",
"pivot": [0, 16.25, -3.8],
"locators": {
"head": [0, 16.25, -3.8]
}
},
{
"name": "locator_item_hat",
"parent": "hair",
"pivot": [0, 17.25, 0.7],
"locators": {
"item_hat": [0, 17.25, 0.7]
}
},
{
"name": "hair2",
"parent": "hair",
"pivot": [4.5, 14.25, -0.8],
"rotation": [22.5, -90, 0]
},
{
"name": "hair3",
"parent": "hair2",
"pivot": [4.5, 14.25, -0.8],
"cubes": [
{"origin": [2.5, 14.25, -0.8], "size": [4, 7, 0], "uv": [40, 56]}
]
},
{
"name": "ponytail",
"parent": "head",
"pivot": [0, 16.81524, 1.82582],
"rotation": [2.5, 0, 0],
"parent": "hair",
"pivot": [0, 16.25, 1.2],
"rotation": [-20, 0, 0],
"cubes": [
{"origin": [-2, 16.62133, -0.28751], "size": [4, 4, 8], "uv": [20, 24]}
{"origin": [-4, 15.25, 0.2], "size": [8, 7, 7], "uv": [37, 13]}
]
},
{
"name": "ponytail2",
"parent": "ponytail",
"pivot": [0, 16.62133, 3.71249],
"pivot": [0, 18.25, 6.7],
"rotation": [-22.5, 0, 0],
"cubes": [
{"origin": [-2, 9.62133, 3.71249], "size": [4, 7, 4], "inflate": -0.001, "uv": [36, 19]}
{"origin": [-3, 15.75, 5.2], "size": [6, 5, 7], "uv": [39, 27]}
]
},
{
"name": "ponytail3",
"parent": "ponytail2",
"pivot": [0, 11.62133, 7.71249],
"pivot": [0, 17.75, 11.2],
"rotation": [52.5, 0, 0],
"cubes": [
{"origin": [-2, 9.62133, 7.71249], "size": [4, 2, 3], "inflate": -0.002, "uv": [21, 45]}
{"origin": [-1.5, 16.25, 10.7], "size": [3, 3, 5], "uv": [60, 0]}
]
},
{
"name": "hair2",
"parent": "head",
"pivot": [3.25, 16.625, -1.925],
"rotation": [-30, 0, 27.5]
"name": "arms",
"parent": "chest",
"pivot": [0, 7.5, 0]
},
{
"name": "hair3",
"parent": "hair2",
"pivot": [3.25, 16.625, -1.925],
"name": "arm_left",
"parent": "arms",
"pivot": [2, 7.5, 0],
"cubes": [
{"origin": [1.25, 16.625, -1.925], "size": [4, 6, 0], "uv": [48, 15]}
{"origin": [1, 6.5, -1.5], "size": [4, 2, 3], "uv": [14, 28]}
]
},
{
"name": "arm_left2",
"parent": "arm_left",
"pivot": [5, 8.5, 1],
"cubes": [
{"origin": [5, 6, -2], "size": [4, 3, 4], "inflate": 0.001, "uv": [16, 21]}
]
},
{
"name": "locator_hand_secondary",
"parent": "arm_left2",
"pivot": [8.5, 7.45, 0],
"rotation": [0, -90, 0],
"locators": {
"hand_secondary": [8.5, 7.45, 0]
}
},
{
"name": "fingers_left",
"parent": "arm_left2",
"pivot": [9, 7.25, -0.5]
},
{
"name": "finger_left",
"parent": "fingers_left",
"pivot": [9, 7.75, -0.75],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [9, 7.75, -1.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [0, 23]}
]
},
{
"name": "finger_left2",
"parent": "fingers_left",
"pivot": [9, 7.75, 0.75],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [9, 7.75, 0.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [12, 23]}
]
},
{
"name": "finger_left3",
"parent": "fingers_left",
"pivot": [9, 7.25, 0],
"cubes": [
{"origin": [9, 6.25, -0.5], "size": [1, 1, 1], "inflate": 0.25, "uv": [16, 23]}
]
},
{
"name": "arm_right",
"parent": "arms",
"pivot": [-2, 7.5, 0],
"cubes": [
{"origin": [-5, 6.5, -1.5], "size": [4, 2, 3], "uv": [0, 28], "mirror": true}
]
},
{
"name": "arm_right2",
"parent": "arm_right",
"pivot": [-5, 8.5, 1.5],
"cubes": [
{"origin": [-9, 6, -2], "size": [4, 3, 4], "inflate": 0.001, "uv": [0, 21], "mirror": true}
]
},
{
"name": "locator_hand_primary",
"parent": "arm_right2",
"pivot": [-8.5, 7.45, 0],
"rotation": [0, 90, 0],
"locators": {
"hand_primary": [-8.5, 7.45, 0]
}
},
{
"name": "fingers_right",
"parent": "arm_right2",
"pivot": [-9, 7.25, -0.5]
},
{
"name": "finger_right",
"parent": "fingers_right",
"pivot": [-9, 7.75, -0.75],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-10, 7.75, -1.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [0, 21], "mirror": true}
]
},
{
"name": "finger_right2",
"parent": "fingers_right",
"pivot": [-9, 7.75, 0.75],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-10, 7.75, 0.75], "size": [1, 1, 1], "inflate": 0.25, "uv": [12, 21], "mirror": true}
]
},
{
"name": "finger_right3",
"parent": "fingers_right",
"pivot": [-9, 7.25, 0],
"cubes": [
{"origin": [-10, 6.25, -0.5], "size": [1, 1, 1], "inflate": 0.25, "uv": [16, 21], "mirror": true}
]
},
{
"name": "arm_hammer_right",
"parent": "arms",
"pivot": [-2, 7.5, 0]
},
{
"name": "arm_hammer_right2",
"parent": "arm_hammer_right",
"pivot": [-5, 8.5, 1.5]
},
{
"name": "hammer",
"parent": "arm_hammer_right2",
"pivot": [-10, 7.5, 0]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [-10.05, 7.5, -11.25],
"cubes": [
{"origin": [-11, 6.5, -11.85], "size": [2, 2, 16], "inflate": -0.1, "uv": [91, 18]}
]
},
{
"name": "ball",
"parent": "hammer2",
"pivot": [-10, 7.5, -14.75],
"cubes": [
{"origin": [-11.5, 6, -14.75], "size": [3, 3, 3], "uv": [94, 27]},
{"origin": [-11.5, 6, -14.75], "size": [3, 3, 3], "inflate": 0.1, "uv": [112, 27]}
]
},
{
"name": "rattle",
"parent": "hammer2",
"pivot": [-10, 7.5, -15.25],
"cubes": [
{"origin": [-11.5, 6, -22.75], "size": [3, 3, 6], "uv": [84, 37]},
{"origin": [-10.5, 7, -16.75], "size": [1, 1, 2], "uv": [97, 23]},
{"origin": [-10.5, 6, -21.25], "size": [1, 1, 1], "inflate": 0.02, "pivot": [-10, 6.5, -20.75], "rotation": [0, -45, 0], "uv": [97, 40]},
{"origin": [-11, 6, -20.25], "size": [2, 1, 2], "inflate": 0.02, "pivot": [-10, 6.5, -19.25], "rotation": [0, -45, 0], "uv": [81, 38]},
{"origin": [-11, 6, -20.75], "size": [2, 1, 2], "inflate": 0.01, "uv": [114, 23]}
]
},
{
"name": "locator_item",
"parent": "rattle",
"pivot": [-10, 5.3, -19],
"locators": {
"item": {
"offset": [-10, 5.3, -19],
"rotation": [0, 135, 0]
}
}
},
{
"name": "plates",
"parent": "hammer2",
"pivot": [-10, 9.025, -20.275]
},
{
"name": "plate_top",
"parent": "plates",
"pivot": [-3.5, 9.525, -20.275],
"cubes": [
{"origin": [-4, 4.5, -20.26], "size": [6, 8, 0], "pivot": [-4, 10, -20.25], "rotation": [-90, -180, 0], "uv": [115, 46]},
{"origin": [0, -1.5, -20.26], "size": [4, 8, 0], "pivot": [-2, 4, -20.25], "rotation": [-90, -180, 0], "uv": [117, 37]},
{"origin": [8, 4.5, -20.26], "size": [0, 8, 6], "pivot": [2, 10, -20.25], "rotation": [-90, -180, 0], "uv": [115, 49]}
]
},
{
"name": "plate_middle",
"parent": "plates",
"pivot": [-6.5, 9.525, -21.775],
"cubes": [
{"origin": [-10, 4.5, -21.75], "size": [8, 9, 0], "pivot": [-8, 10, -21.75], "rotation": [-90, -180, 0], "uv": [85, 47]},
{"origin": [-10, 4.5, -30.75], "size": [8, 0, 6], "pivot": [-8, 10, -30.75], "rotation": [-90, -180, 0], "uv": [79, 57]}
]
},
{
"name": "plate_bottom",
"parent": "plates",
"pivot": [-16.5, 10.525, -20.775],
"cubes": [
{"origin": [-21, 4.5, -20.74], "size": [5, 8, 0], "pivot": [-16, 10, -20.75], "rotation": [-90, 180, 0], "uv": [103, 46]},
{"origin": [-24, -1.5, -20.74], "size": [4, 8, 0], "pivot": [-18, 4, -20.75], "rotation": [-90, 180, 0], "uv": [104, 37], "mirror": true},
{"origin": [-28, 4.5, -20.74], "size": [0, 8, 6], "pivot": [-22, 10, -20.75], "rotation": [-90, 180, 0], "uv": [102, 49], "mirror": true}
]
},
{
"name": "locator_physical",
"parent": "plate_bottom",
"pivot": [-16, 7, -19],
"locators": {
"physical": [-16, 7, -19]
}
},
{
"name": "bandage",
"parent": "plates",
"pivot": [-8, 10, -22.25],
"cubes": [
{"origin": [-10.75, 10.2, -23.25], "size": [2, 0, 6], "pivot": [-9.75, 13, -20.25], "rotation": [0, 45, 0], "uv": [74, 57]},
{"origin": [-10.75, 10.1, -23.25], "size": [2, 0, 6], "pivot": [-9.75, 13, -20.25], "rotation": [0, -55, 0], "uv": [69, 57]}
]
},
{
"name": "skirt",
"parent": "torso",
"pivot": [0, 3, 0]
},
{
"name": "skirt_left",
"parent": "skirt",
"pivot": [2.7, 3, -0.5],
"rotation": [0, 0, 30],
"cubes": [
{"origin": [2.7, 3, -2], "size": [3, 0, 3], "uv": [65, 60]}
]
},
{
"name": "skirt_right",
"parent": "skirt",
"pivot": [-2.7, 3, -0.5],
"rotation": [0, 0, -30],
"cubes": [
{"origin": [-5.7, 3, -2], "size": [3, 0, 3], "uv": [65, 56], "mirror": true}
]
},
{
"name": "legs",
"parent": "body",
"pivot": [-0.2, 4.5, 0]
},
{
"name": "leg_left",
"parent": "body",
"pivot": [1.25, 4, 0],
"parent": "legs",
"pivot": [1.55, 4, 0],
"cubes": [
{"origin": [0.25, 2, -1], "size": [2, 2, 2], "uv": [28, 50]}
{"origin": [0.05, 1.5, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [12, 33]}
]
},
{
"name": "leg_left2",
"parent": "leg_left",
"pivot": [1.25, 2, -1],
"pivot": [1.55, 1.7, -1.4],
"cubes": [
{"origin": [0.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [50, 0]}
{"origin": [0.05, 0, -1.5], "size": [3, 2, 3], "uv": [12, 39]}
]
},
{
"name": "locator_foot_secondary",
"parent": "leg_left2",
"pivot": [1.6, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_secondary": [1.6, 0.5, 0]
}
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-1.25, 4, 0],
"parent": "legs",
"pivot": [-1.55, 4, 0],
"cubes": [
{"origin": [-2.25, 2, -1], "size": [2, 2, 2], "uv": [20, 50]}
{"origin": [-3.05, 1.5, -1.5], "size": [3, 3, 3], "inflate": -0.25, "uv": [0, 33], "mirror": true}
]
},
{
"name": "leg_right2",
"parent": "leg_right",
"pivot": [-1.25, 2, -1],
"pivot": [-1.55, 1.7, -1.4],
"cubes": [
{"origin": [-2.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [12, 32]}
{"origin": [-3.05, 0, -1.5], "size": [3, 2, 3], "uv": [0, 39], "mirror": true}
]
},
{
"name": "locator_foot_primary",
"parent": "leg_right2",
"pivot": [-1.6, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_primary": [-1.6, 0.5, 0]
}
}
]
}
@@ -1,305 +0,0 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.tinkatuff_dot",
"texture_width": 64,
"texture_height": 64,
"visible_bounds_width": 3,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "tinkatuff",
"pivot": [0, 0, 0]
},
{
"name": "body",
"parent": "tinkatuff",
"pivot": [0, 6, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 4.25, 0],
"cubes": [
{"origin": [-2, 7.5, -1.5], "size": [4, 3, 3], "uv": [41, 41]},
{"origin": [-2.5, 3, -2], "size": [5, 5, 4], "uv": [36, 0]}
]
},
{
"name": "skirt_left",
"parent": "torso",
"pivot": [2.5, 3, 0],
"rotation": [0, 0, 45],
"cubes": [
{"origin": [2.5, 3, -1.5], "size": [3, 0, 3], "uv": [6, 15]}
]
},
{
"name": "skirt_right",
"parent": "torso",
"pivot": [-2.5, 3, 0],
"rotation": [0, 0, -45],
"cubes": [
{"origin": [-5.5, 3, -1.5], "size": [3, 0, 3], "uv": [0, 15]}
]
},
{
"name": "arm_left",
"parent": "torso",
"pivot": [2, 8, 0],
"cubes": [
{"origin": [1, 7, -1], "size": [4, 2, 2], "uv": [35, 47]}
]
},
{
"name": "arm_left2",
"parent": "arm_left",
"pivot": [5, 9, 1],
"cubes": [
{"origin": [5, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 35]}
]
},
{
"name": "finger_left",
"parent": "arm_left2",
"pivot": [9, 7.75, -0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [9, 7.75, -1.5], "size": [1, 1, 1], "uv": [33, 44]}
]
},
{
"name": "finger_left2",
"parent": "arm_left2",
"pivot": [9, 7.75, 0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [9, 7.75, 0.5], "size": [1, 1, 1], "uv": [40, 30]}
]
},
{
"name": "finger_left3",
"parent": "arm_left2",
"pivot": [9, 8, 0],
"cubes": [
{"origin": [9, 7, -0.5], "size": [1, 1, 1], "uv": [36, 30]}
]
},
{
"name": "arm_hammer_right",
"parent": "torso",
"pivot": [-2, 8, 0]
},
{
"name": "arm_hammer_right2",
"parent": "arm_hammer_right",
"pivot": [-5, 9, 1]
},
{
"name": "hammer",
"parent": "arm_hammer_right2",
"pivot": [-9.75, 8, 0]
},
{
"name": "hammer2",
"parent": "hammer",
"pivot": [-9.55, 7.9675, -9.0675],
"cubes": [
{"origin": [-11, 6.5, -20], "size": [3, 3, 6], "uv": [30, 9]},
{"origin": [-10.5, 6.475, -18], "size": [2, 0, 2], "pivot": [-9.5, 6.475, -17], "rotation": [0, 45, 0], "uv": [-1, 54]},
{"origin": [-11, 6.5, -12.5], "size": [3, 3, 3], "uv": [0, 47]},
{"origin": [-10, 7.5, -14.5], "size": [1, 1, 18], "inflate": 0.001, "uv": [0, 0]},
{"origin": [-15.5, 4.025, -18.525], "size": [12, 11, 0], "pivot": [-9.5, 9.525, -18.525], "rotation": [-90, -180, 0], "uv": [0, 36]},
{"origin": [-15, 6.53, -18.04], "size": [7, 7, 0], "pivot": [-11, 9.53, -18.04], "rotation": [90, -45, -180], "uv": [42, 56]},
{"origin": [-15.5, 3.5, -30.5], "size": [0, 8, 5], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [34, 31]},
{"origin": [-15.5, 3.5, -30.5], "size": [3, 8, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [47, 47]},
{"origin": [-7.5, 2.5, -30.5], "size": [4, 9, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [12, 47]},
{"origin": [-3.5, 2.525, -20.025], "size": [0, 9, 5], "pivot": [-3.5, 7.025, -17.525], "rotation": [90, 180, 0], "uv": [24, 31]},
{"origin": [-13.5, 12.5, -29.5], "size": [8, 1, 0], "pivot": [-9.5, 12.25, -22.775], "rotation": [90, 0, 0], "uv": [0, 7]},
{"origin": [-13.5, 7.525, -26.025], "size": [8, 0, 4], "pivot": [-9.5, 7.525, -24.025], "rotation": [90, 180, 0], "uv": [17, 19]}
]
},
{
"name": "arm_right",
"parent": "torso",
"pivot": [-2, 8, 0],
"cubes": [
{"origin": [-5, 7, -1], "size": [4, 2, 2], "uv": [0, 32]}
]
},
{
"name": "arm_right2",
"parent": "arm_right",
"pivot": [-5, 9, 1],
"cubes": [
{"origin": [-9, 7, -1.5], "size": [4, 2, 3], "inflate": 0.001, "uv": [44, 30]}
]
},
{
"name": "finger_right",
"parent": "arm_right2",
"pivot": [-9, 7.75, -0.5],
"rotation": [0, -12.5, 0],
"cubes": [
{"origin": [-10, 7.75, -1.5], "size": [1, 1, 1], "uv": [36, 2]}
]
},
{
"name": "finger_right2",
"parent": "arm_right2",
"pivot": [-9, 7.75, 0.5],
"rotation": [0, 12.5, 0],
"cubes": [
{"origin": [-10, 7.75, 0.5], "size": [1, 1, 1], "uv": [36, 0]}
]
},
{
"name": "finger_right3",
"parent": "arm_right2",
"pivot": [-9, 8, 0],
"cubes": [
{"origin": [-10, 7, -0.5], "size": [1, 1, 1], "uv": [10, 32]}
]
},
{
"name": "head",
"parent": "torso",
"pivot": [0, 9, 0.5],
"cubes": [
{"origin": [-3.5, 9, -3.5], "size": [7, 6, 7], "uv": [0, 19]},
{"origin": [-4, 17.30092, -3.63266], "size": [8, 0, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [12, 0]},
{"origin": [4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [20, 0]},
{"origin": [-4, 10.30092, 4.36734], "size": [8, 7, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]},
{"origin": [-4, 11.30092, -3.63266], "size": [8, 6, 0], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [42, 9]},
{"origin": [-4, 10.30092, -3.63266], "size": [0, 7, 8], "pivot": [0, 13.80092, 0.36734], "rotation": [-7.5, 0, 0], "uv": [0, 0]}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.25, 12.25, -3.01],
"rotation": [0, 0, -7.5],
"cubes": [
{"origin": [1.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [21, 23]}
]
},
{
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [2.25, 12.25, -2.91],
"cubes": [
{"origin": [1.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [26, 15]}
]
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.25, 12.25, -3.01],
"rotation": [0, 0, 7.5],
"cubes": [
{"origin": [-2.75, 11.25, -3.51], "size": [1, 2, 1], "uv": [0, 21]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-2.25, 12.25, -2.91],
"cubes": [
{"origin": [-2.75, 11.25, -3.41], "size": [1, 2, 1], "inflate": 0.01, "uv": [3, 23]}
]
},
{
"name": "mouth_open",
"parent": "head",
"pivot": [0, 10.5, -3.41],
"cubes": [
{"origin": [-1.5, 9.5, -3.41], "size": [3, 2, 0], "uv": [20, 15]}
]
},
{
"name": "mouth_closed",
"parent": "head",
"pivot": [0, 10.5, -3.51],
"cubes": [
{"origin": [-1.5, 9.5, -3.51], "size": [3, 2, 0], "uv": [0, 19]}
]
},
{
"name": "ponytail",
"parent": "head",
"pivot": [0, 16.81524, 1.82582],
"rotation": [2.5, 0, 0],
"cubes": [
{"origin": [-2, 16.62133, -0.28751], "size": [4, 4, 8], "uv": [20, 24]}
]
},
{
"name": "ponytail2",
"parent": "ponytail",
"pivot": [0, 16.62133, 3.71249],
"cubes": [
{"origin": [-2, 9.62133, 3.71249], "size": [4, 7, 4], "inflate": -0.001, "uv": [36, 19]}
]
},
{
"name": "ponytail3",
"parent": "ponytail2",
"pivot": [0, 11.62133, 7.71249],
"cubes": [
{"origin": [-2, 9.62133, 7.71249], "size": [4, 2, 3], "inflate": -0.002, "uv": [21, 45]}
]
},
{
"name": "hair2",
"parent": "head",
"pivot": [3.25, 16.625, -1.925],
"rotation": [-30, 0, 27.5]
},
{
"name": "hair3",
"parent": "hair2",
"pivot": [3.25, 16.625, -1.925],
"cubes": [
{"origin": [1.25, 16.625, -1.925], "size": [4, 6, 0], "uv": [48, 15]}
]
},
{
"name": "leg_left",
"parent": "body",
"pivot": [1.25, 4, 0],
"cubes": [
{"origin": [0.25, 2, -1], "size": [2, 2, 2], "uv": [28, 50]}
]
},
{
"name": "leg_left2",
"parent": "leg_left",
"pivot": [1.25, 2, -1],
"cubes": [
{"origin": [0.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [50, 0]}
]
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-1.25, 4, 0],
"cubes": [
{"origin": [-2.25, 2, -1], "size": [2, 2, 2], "uv": [20, 50]}
]
},
{
"name": "leg_right2",
"parent": "leg_right",
"pivot": [-1.25, 2, -1],
"cubes": [
{"origin": [-2.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [12, 32]}
]
}
]
}
]
}
@@ -1,650 +0,0 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.tinkaton_dot",
"texture_width": 128,
"texture_height": 128,
"visible_bounds_width": 5,
"visible_bounds_height": 4.5,
"visible_bounds_offset": [0, 1.75, 0]
},
"bones": [
{
"name": "bb_main",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-2, 0, 0], "size": [2, 2, 2], "uv": [0, 0]}
]
},
{
"name": "tinkaton",
"pivot": [0, 0, 0]
},
{
"name": "body_hammer",
"parent": "tinkaton",
"pivot": [0, 7, 0]
},
{
"name": "torso_hammer",
"parent": "body_hammer",
"pivot": [0, 4, 0]
},
{
"name": "arms_hammer",
"parent": "torso_hammer",
"pivot": [0, 7, 0]
},
{
"name": "arm_hammer_right",
"parent": "arms_hammer",
"pivot": [-1.5, 6.5, 0]
},
{
"name": "hand_hammer_right",
"parent": "arm_hammer_right",
"pivot": [-4.5, 6.5, 1.5]
},
{
"name": "hammer",
"parent": "hand_hammer_right",
"pivot": [-8, 5.125, -0.5]
},
{
"name": "hammer_handle",
"parent": "hammer",
"pivot": [-8, 5.375, -15.75],
"cubes": [
{"origin": [-8, 1.25, -23], "size": [0, 4, 4], "uv": [64, 48]},
{"origin": [-9.5, 5.25, -23], "size": [3, 4, 5], "inflate": -0.001, "uv": [87, 0]},
{"origin": [-9.5, 3.25, -19], "size": [3, 5, 4], "uv": [88, 34]},
{"origin": [-9, 4.25, -15], "size": [2, 2, 21], "uv": [0, 27]}
]
},
{
"name": "hammer_middle",
"parent": "hammer_handle",
"pivot": [-8.8, 5.25, -29],
"cubes": [
{"origin": [-14, 12.252, -35], "size": [12, 0, 12], "inflate": 0.001, "uv": [37, 27]},
{"origin": [-14, -0.752, -35], "size": [12, 0, 12], "inflate": 0.001, "uv": [13, 27]},
{"origin": [-14, -0.75, -35], "size": [12, 13, 0], "inflate": 0.001, "uv": [80, 60]},
{"origin": [-14, -0.75, -35], "size": [0, 13, 12], "inflate": 0.001, "uv": [24, 50]},
{"origin": [-14, -0.75, -23], "size": [12, 13, 0], "inflate": 0.001, "uv": [20, 75]},
{"origin": [-2, -0.75, -35], "size": [0, 13, 12], "inflate": 0.001, "uv": [0, 38]},
{"origin": [-8, -2.75, -46], "size": [0, 12, 11], "uv": [48, 51]},
{"origin": [-9.3375, 5.7875, -30.025], "size": [2, 0, 2], "pivot": [-8.3375, 5.7875, -29.025], "rotation": [0, -45, -90], "uv": [93, 14]},
{"origin": [-13, -0.75, -24], "size": [10, 13, 0], "uv": [68, 83]},
{"origin": [-13, -0.75, -34], "size": [0, 13, 10], "uv": [0, 53]},
{"origin": [-3, -0.75, -34], "size": [0, 13, 10], "uv": [0, 17]},
{"origin": [-13, -0.75, -34], "size": [10, 13, 0], "uv": [0, 76]},
{"origin": [-13, -0.75, -34], "size": [10, 0, 10], "uv": [47, 0]},
{"origin": [-13, 12.25, -34], "size": [10, 0, 10], "uv": [36, 39]},
{"origin": [-10.5, 0.75, -28], "size": [1, 8, 1], "pivot": [-10, 5.75, -27.5], "rotation": [90, 0, 0], "uv": [20, 63]},
{"origin": [-11.5, 2.75, -30.5], "size": [3, 6, 3], "pivot": [-10, 5.75, -29], "rotation": [90, 0, -90], "uv": [57, 10]}
]
},
{
"name": "hammer_front",
"parent": "hammer_middle",
"pivot": [-7.4, 12.3, -28.5],
"cubes": [
{"origin": [-12, 12.25, -33], "size": [8, 3, 8], "uv": [64, 41]},
{"origin": [-17.5, 15.25, -38.25], "size": [19, 8, 19], "uv": [0, 0]},
{"origin": [-17.5, 15.25, -40.25], "size": [0, 8, 2], "uv": [16, 38]},
{"origin": [-17.5, 15.25, -40.25], "size": [5, 0, 2], "uv": [0, 46]},
{"origin": [-17.5, 23.25, -40.25], "size": [5, 0, 2], "uv": [0, 17]},
{"origin": [-17.5, 15.25, -40.25], "size": [15, 8, 0], "uv": [73, 52]}
]
},
{
"name": "nail",
"parent": "hammer_front",
"pivot": [-5.5, 20.25, -38.25],
"rotation": [10, 0, 0],
"cubes": [
{"origin": [-6.5, 19.25, -42.25], "size": [2, 2, 5], "uv": [88, 73]},
{"origin": [-8, 17.75, -43.25], "size": [5, 5, 1], "uv": [24, 56]}
]
},
{
"name": "locator_hammer",
"parent": "hammer_front",
"pivot": [-8, 23, -28.75],
"rotation": [90, 0, 0],
"locators": {
"hammer": [-8, 23, -28.75],
"physical": [-8, 23, -28.75],
"special2": [-8, 23, -28.75]
}
},
{
"name": "hammer_back",
"parent": "hammer_middle",
"pivot": [-8, -1, -29],
"cubes": [
{"origin": [-11, -3.75, -32], "size": [6, 3, 6], "uv": [44, 77]},
{"origin": [-12.5, -7.75, -33.5], "size": [9, 4, 9], "uv": [37, 49]}
]
},
{
"name": "seat_1_locator",
"parent": "hammer_middle",
"pivot": [-8, 0, -35],
"rotation": [105, 0, 0],
"locators": {
"seat_1": [-8, 0, -35]
}
},
{
"name": "body",
"parent": "tinkaton",
"pivot": [0, 7, 0]
},
{
"name": "torso",
"parent": "body",
"pivot": [0, 4, 0],
"cubes": [
{"origin": [-2, 6.5, -1.5], "size": [4, 3, 3], "inflate": 0.001, "uv": [88, 43]},
{"origin": [-2.5, 3, -2], "size": [5, 4, 4], "uv": [0, 0]}
]
},
{
"name": "skirt_front_right",
"parent": "torso",
"pivot": [-1.75, 3, -1.25],
"rotation": [30, 45, 0],
"cubes": [
{"origin": [-3.25, 3, -4.25], "size": [3, 0, 3], "uv": [37, 50]}
]
},
{
"name": "skirt_front_left",
"parent": "torso",
"pivot": [1.75, 3, -1.25],
"rotation": [30, -45, 0],
"cubes": [
{"origin": [0.25, 3, -4.25], "size": [3, 0, 3], "uv": [36, 45]}
]
},
{
"name": "skirt_back_left",
"parent": "torso",
"pivot": [1.75, 3, 1.25],
"rotation": [-30, 45, 0],
"cubes": [
{"origin": [0.25, 3, 1.25], "size": [3, 0, 3], "uv": [36, 42]}
]
},
{
"name": "skirt_back_right",
"parent": "torso",
"pivot": [-1.75, 3, 1.25],
"rotation": [-30, -45, 0],
"cubes": [
{"origin": [-3.25, 3, 1.25], "size": [3, 0, 3], "uv": [36, 39]}
]
},
{
"name": "head",
"parent": "torso",
"pivot": [0, 7.75, 0],
"cubes": [
{"origin": [-3.5, 7.75, -3.5], "size": [7, 7, 7], "uv": [73, 20]},
{"origin": [-3.5, 9.25, -4], "size": [0, 6, 8], "inflate": 0.01, "uv": [24, 42]},
{"origin": [3.5, 9.25, -4], "size": [0, 6, 8], "inflate": 0.01, "uv": [0, 32]},
{"origin": [-3.5, 8.25, 4], "size": [7, 7, 0], "inflate": 0.01, "uv": [88, 80]},
{"origin": [-3.5, 11.25, -4], "size": [7, 4, 0], "inflate": 0.01, "uv": [28, 88]},
{"origin": [-3.5, 15.25, -4], "size": [7, 0, 8], "inflate": 0.01, "uv": [17, 39]}
]
},
{
"name": "ear_left",
"parent": "head",
"pivot": [0, 14.75, 0],
"rotation": [0, 0, 10],
"cubes": [
{"origin": [0, 14.75, -1], "size": [3, 6, 2], "uv": [0, 89]}
]
},
{
"name": "ear_left2",
"parent": "head",
"pivot": [3, 14.75, 0],
"rotation": [0, 0, 20],
"cubes": [
{"origin": [3, 13.75, 0], "size": [2, 3, 0], "uv": [44, 78]}
]
},
{
"name": "ear_right",
"parent": "head",
"pivot": [0, 14.75, 0],
"rotation": [0, 0, -10],
"cubes": [
{"origin": [-3, 14.75, -1], "size": [3, 6, 2], "uv": [88, 87]}
]
},
{
"name": "ear_right2",
"parent": "head",
"pivot": [-3, 14.75, 0],
"cubes": [
{"origin": [-5, 13.75, 0], "size": [2, 3, 0], "pivot": [-3, 14.75, -0.5], "rotation": [0, 0, -20], "uv": [76, 22]}
]
},
{
"name": "eye_left",
"parent": "head",
"pivot": [2.5, 11.25, -3.025],
"cubes": [
{"origin": [2, 10.25, -3.525], "size": [1, 2, 1], "uv": [14, 0]}
]
},
{
"name": "eyelid_left",
"parent": "eye_left",
"pivot": [2.5, 11.25, -2.925],
"cubes": [
{"origin": [2, 10.25, -3.425], "size": [1, 2, 1], "inflate": 0.01, "uv": [76, 19]}
]
},
{
"name": "locator_eye_left",
"parent": "eye_left",
"pivot": [-2.5, 11.25, -3.5],
"locators": {
"eye1": [-2.5, 11.25, -3.5]
}
},
{
"name": "eye_right",
"parent": "head",
"pivot": [-2.5, 11.25, -3.025],
"cubes": [
{"origin": [-3, 10.25, -3.525], "size": [1, 2, 1], "uv": [0, 0]}
]
},
{
"name": "eyelid_right",
"parent": "eye_right",
"pivot": [-2.5, 11.25, -2.925],
"cubes": [
{"origin": [-3, 10.25, -3.425], "size": [1, 2, 1], "inflate": 0.01, "uv": [20, 72]}
]
},
{
"name": "locator_eye_right",
"parent": "eye_right",
"pivot": [2.5, 11.25, -3.5],
"locators": {
"eye2": [2.5, 11.25, -3.5]
}
},
{
"name": "mouths",
"parent": "head",
"pivot": [0, 9.25, -3.525]
},
{
"name": "mouth_open",
"parent": "mouths",
"pivot": [0, 9.25, -3.61],
"cubes": [
{"origin": [-2.5, 8.25, -3.41], "size": [5, 2, 0], "uv": [77, 0]}
]
},
{
"name": "locator_mouth",
"parent": "mouth_open",
"pivot": [0, 9.25, -3.5],
"locators": {
"mouth": [0, 9.25, -3.5]
}
},
{
"name": "mouth_closed",
"parent": "mouths",
"pivot": [0, 9.25, -3.41],
"cubes": [
{"origin": [-3.5, 8.25, -3.51], "size": [7, 2, 0], "uv": [48, 74]}
]
},
{
"name": "hair_right",
"parent": "head",
"pivot": [-3.5, 13.75, 0],
"cubes": [
{"origin": [-7, 9.75, -3], "size": [4, 5, 6], "uv": [14, 88]}
]
},
{
"name": "hair_right2",
"parent": "hair_right",
"pivot": [-3, 9.5, 0],
"cubes": [
{"origin": [-8, 0.75, -4], "size": [5, 9, 8], "uv": [69, 2]}
]
},
{
"name": "hair_right3",
"parent": "hair_right2",
"pivot": [-5.5, 0.75, 0],
"cubes": [
{"origin": [-5.5, -3.25, -4.5], "size": [0, 4, 9], "uv": [0, 4]}
]
},
{
"name": "hair_left",
"parent": "head",
"pivot": [3.5, 14.25, 0],
"cubes": [
{"origin": [3, 10.25, -3], "size": [4, 5, 6], "uv": [38, 86]}
]
},
{
"name": "hair_left2",
"parent": "hair_left",
"pivot": [3, 10, 0],
"cubes": [
{"origin": [3, 1.25, -4], "size": [5, 9, 8], "uv": [62, 66]}
]
},
{
"name": "hair_left3",
"parent": "hair_left2",
"pivot": [5.5, 1.25, 0],
"cubes": [
{"origin": [5.5, -2.75, -4.5], "size": [0, 4, 9], "uv": [0, 0]}
]
},
{
"name": "locator_head",
"parent": "head",
"pivot": [0, 15.25, -2.5],
"locators": {
"head": [0, 15.25, -2.5]
}
},
{
"name": "locator_item_hat",
"parent": "head",
"pivot": [0, 16.25, 0],
"locators": {
"item_hat": [0, 16.25, 0]
}
},
{
"name": "locator_tera_hat",
"parent": "head",
"pivot": [0, 15.25, 0],
"locators": {
"tera_hat": [0, 15.25, 0]
}
},
{
"name": "locator_face",
"parent": "head",
"pivot": [0, 10.25, -3.5],
"locators": {
"face": [0, 10.25, -3.5]
}
},
{
"name": "locator_item_face",
"parent": "head",
"pivot": [0, 11.5, -3.5],
"locators": {
"item_face": [0, 11.5, -3.5]
}
},
{
"name": "arms",
"parent": "torso",
"pivot": [0, 7, 0]
},
{
"name": "arm_left",
"parent": "arms",
"pivot": [1.5, 6.5, 0],
"cubes": [
{"origin": [1.5, 5.5, -1.5], "size": [3, 2, 3], "uv": [94, 16]}
]
},
{
"name": "hand_left",
"parent": "arm_left",
"pivot": [4.5, 6.5, 1.5],
"cubes": [
{"origin": [4.5, 5.5, -2], "size": [4, 2, 4], "inflate": 0.01, "uv": [52, 86]}
]
},
{
"name": "locator_hand_secondary",
"parent": "hand_left",
"pivot": [7.75, 6.5, 0],
"rotation": [0, -90, 0],
"locators": {
"hand_secondary": [7.75, 6.5, 0]
}
},
{
"name": "locator_item",
"parent": "hand_left",
"pivot": [9.5, 5.75, 0],
"locators": {
"item": [9.5, 5.75, 0]
}
},
{
"name": "finger_left",
"parent": "hand_left",
"pivot": [8.25, 7, -1.5],
"rotation": [0, 17.5, 0],
"cubes": [
{"origin": [8.25, 6, -2], "size": [2, 1, 1], "uv": [44, 76]}
]
},
{
"name": "finger_left2",
"parent": "hand_left",
"pivot": [8.5, 7, -0.5],
"rotation": [0, 5, 0],
"cubes": [
{"origin": [8.5, 6, -1], "size": [2, 1, 1], "uv": [73, 60]}
]
},
{
"name": "finger_left3",
"parent": "hand_left",
"pivot": [8.5, 7, 0.5],
"rotation": [0, -5, 0],
"cubes": [
{"origin": [8.5, 6, 0], "size": [2, 1, 1], "uv": [66, 47]}
]
},
{
"name": "finger_left4",
"parent": "hand_left",
"pivot": [8.25, 7, 1.5],
"rotation": [0, -17.5, 0],
"cubes": [
{"origin": [8.25, 6, 1], "size": [2, 1, 1], "uv": [66, 45]}
]
},
{
"name": "thumb_left",
"parent": "hand_left",
"pivot": [5, 5.5, -0.5],
"rotation": [0, 0, 42.5],
"cubes": [
{"origin": [5, 5.5, -1.5], "size": [2, 1, 2], "inflate": 0.01, "uv": [94, 24]}
]
},
{
"name": "arm_right",
"parent": "arms",
"pivot": [-1.5, 6.5, 0],
"cubes": [
{"origin": [-4.5, 5.5, -1.5], "size": [3, 2, 3], "uv": [58, 93]}
]
},
{
"name": "hand_right",
"parent": "arm_right",
"pivot": [-4.5, 6.5, 1.5],
"cubes": [
{"origin": [-8.5, 5.5, -2], "size": [4, 2, 4], "inflate": 0.01, "uv": [69, 35]}
]
},
{
"name": "locator_hand_primary",
"parent": "hand_right",
"pivot": [-7.75, 6.5, 0],
"rotation": [0, 90, 0],
"locators": {
"hand_primary": [-7.75, 6.5, 0]
}
},
{
"name": "finger_right",
"parent": "hand_right",
"pivot": [-8.25, 7, -1.5],
"rotation": [0, -17.5, 0],
"cubes": [
{"origin": [-10.25, 6, -2], "size": [2, 1, 1], "uv": [66, 43]}
]
},
{
"name": "finger_right2",
"parent": "hand_right",
"pivot": [-8.5, 7, -0.5],
"rotation": [0, -5, 0],
"cubes": [
{"origin": [-10.5, 6, -1], "size": [2, 1, 1], "uv": [66, 41]}
]
},
{
"name": "finger_right3",
"parent": "hand_right",
"pivot": [-8.5, 7, 0.5],
"rotation": [0, 5, 0],
"cubes": [
{"origin": [-10.5, 6, 0], "size": [2, 1, 1], "uv": [64, 56]}
]
},
{
"name": "finger_right4",
"parent": "hand_right",
"pivot": [-8.25, 7, 1.5],
"rotation": [0, 17.5, 0],
"cubes": [
{"origin": [-10.25, 6, 1], "size": [2, 1, 1], "uv": [12, 17]}
]
},
{
"name": "thumb_right",
"parent": "hand_right",
"pivot": [-5, 5.5, -0.5],
"rotation": [0, 0, -42.5],
"cubes": [
{"origin": [-7, 5.5, -1.5], "size": [2, 1, 2], "inflate": 0.01, "uv": [94, 21]}
]
},
{
"name": "leg_right",
"parent": "body",
"pivot": [-1.25, 4, 0],
"cubes": [
{"origin": [-2.25, 2, -1], "size": [2, 2, 2], "uv": [10, 89]}
]
},
{
"name": "leg_right2",
"parent": "leg_right",
"pivot": [-1.25, 2, -1],
"cubes": [
{"origin": [-2.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [81, 34]}
]
},
{
"name": "locator_foot_primary",
"parent": "leg_right2",
"pivot": [-1.25, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_primary": [-1.25, 0.5, 0]
}
},
{
"name": "leg_left",
"parent": "body",
"pivot": [1.25, 4, 0],
"cubes": [
{"origin": [0.25, 2, -1], "size": [2, 2, 2], "uv": [70, 62]}
]
},
{
"name": "leg_left2",
"parent": "leg_left",
"pivot": [1.25, 2, -1],
"cubes": [
{"origin": [0.25, 0, -1], "size": [2, 2, 2], "inflate": 0.2, "uv": [38, 54]}
]
},
{
"name": "locator_foot_secondary",
"parent": "leg_left2",
"pivot": [1.25, 0.5, 0],
"rotation": [90, 0, 0],
"locators": {
"foot_secondary": [1.25, 0.5, 0]
}
},
{
"name": "locator_middle",
"parent": "body",
"pivot": [0, 7, 0],
"locators": {
"middle": [0, 7, 0]
}
},
{
"name": "locator_target",
"parent": "body",
"pivot": [0, 7, -6],
"locators": {
"target": [0, 7, -6]
}
},
{
"name": "locator_root",
"parent": "tinkaton",
"pivot": [0, 0, 0],
"locators": {
"root": [0, 0, 0]
}
},
{
"name": "locator_special",
"parent": "tinkaton",
"pivot": [0, 7, -8],
"locators": {
"special": [0, 7, -8]
}
},
{
"name": "locator_top",
"parent": "tinkaton",
"pivot": [0, 23, 0],
"locators": {
"top": [0, 23, 0]
}
}
]
}
]
}
@@ -41,7 +41,7 @@
},
"walking": {
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.in_air && q.has_entity ? !q.is_sprinting : 1.0",
"condition": "!q.in_air && !q.is_sprinting",
"animations": [
"q.bedrock('heracross', 'ground_walk')",
{
@@ -53,7 +53,7 @@
},
"running": {
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.in_air && q.has_entity ? q.is_sprinting : 0.0",
"condition": "!q.in_air && q.is_sprinting",
"animations": [
"q.bedrock('heracross', 'ground_run')",
{
@@ -5,8 +5,7 @@
"profileTranslation": [0, 0.46, 0],
"rootBone": "mudkip",
"animations": {
"cry": "q.bedrock_stateful('mudkip', 'cry')",
"recoil": "q.bedrock_stateful('mudkip', 'recoil')"
"cry": "q.bedrock_stateful('mudkip', 'cry')"
},
"poses": {
"standing": {
@@ -5,8 +5,7 @@
"profileTranslation": [0, 0.65, 0],
"rootBone": "marshtomp",
"animations": {
"cry": "q.bedrock_stateful('marshtomp', 'cry')",
"recoil": "q.bedrock_stateful('marshtomp', 'recoil')"
"cry": "q.bedrock_stateful('marshtomp', 'cry')"
},
"poses": {
"standing": {
@@ -5,8 +5,7 @@
"profileTranslation": [0, 0.96, 0],
"rootBone": "swampert",
"animations": {
"cry": "q.bedrock_stateful('swampert', 'cry')",
"recoil": "q.bedrock_stateful('swampert', 'recoil')"
"cry": "q.bedrock_stateful('swampert', 'cry')"
},
"poses": {
"standing": {
@@ -1,16 +1,8 @@
{
"portraitScale": 2.48,
"portraitTranslation": [
-0.33,
-0.93,
0
],
"portraitTranslation": [-0.33, -0.93, 0],
"profileScale": 0.7,
"profileTranslation": [
0.02,
0.76,
0
],
"profileTranslation": [0.02, 0.76, 0],
"rootBone": "rufflet",
"animations": {
"cry": "q.bedrock_stateful('rufflet', 'cry')",
@@ -18,13 +10,7 @@
},
"poses": {
"standing": {
"poseTypes": [
"STAND",
"NONE",
"PORTRAIT",
"PROFILE"
],
"isBattle": false,
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"animations": [
"q.look('head')",
"q.bedrock('rufflet', 'ground_idle')"
@@ -36,10 +22,7 @@
]
},
"walking": {
"poseTypes": [
"WALK",
"SWIM"
],
"poseTypes": ["WALK", "SWIM"],
"animations": [
"q.look('head')",
"q.bedrock('rufflet', 'ground_walk')"
@@ -51,9 +34,7 @@
]
},
"hover": {
"poseTypes": [
"HOVER"
],
"poseTypes": ["HOVER"],
"animations": [
"q.pitch_tilt('body', 1)",
"q.look('head')",
@@ -65,9 +46,7 @@
]
},
"fly": {
"poseTypes": [
"FLY"
],
"poseTypes": ["FLY"],
"animations": [
"q.pitch_tilt('body', 1)",
"q.look('head')",
@@ -81,6 +60,9 @@
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('rufflet', 'sleep')"],
"transformTicks": 10
}
@@ -22,7 +22,6 @@
"poses": {
"standing": {
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"isBattle": false,
"animations": [
"q.look('neck1', 1, 1, 5, -5, 10, -10)",
"q.look('neck2', 1, 1, 35, -10, 15, -15)",
@@ -96,6 +95,9 @@
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('braviary', 'sleep')"],
"transformTicks": 10
}
@@ -22,7 +22,6 @@
"poses": {
"standing": {
"poseTypes": ["STAND", "NONE", "PORTRAIT", "PROFILE"],
"isBattle": false,
"animations": [
"q.look('neck', 1, 1, 3, -20, 10, -10)",
"q.look('neck2', 1, 1, 1, -35, 15, -15)",
@@ -96,6 +95,9 @@
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('braviary_hisuian', 'sleep')"],
"transformTicks": 10
}
@@ -19,28 +19,9 @@
"cry": "q.bedrock_stateful('mudsdale', 'cry')"
},
"poses": {
"standing": {
"poseName": "standing",
"poseTypes": ["STAND", "FLOAT", "NONE", "PORTRAIT", "PROFILE"],
"condition": "q.has_entity ? !q.in_air : 1.0",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
"q.look('head', 0.4, 0.25, 5, -5, 10, -10)",
"q.bedrock('mudsdale', 'ground_idle')",
"q.bedrock_stateful('mudsdale', 'blink')"
],
"transformTicks": 10
},
"sleep": {
"poseName": "sleep",
"poseTypes": ["SLEEP"],
"animations": ["q.bedrock('mudsdale', 'sleep')"]
},
"in-air": {
"poseTypes": ["STAND", "WALK"],
"condition": "q.in_air",
"isBattle": false,
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
@@ -52,26 +33,21 @@
"transformTicks": 5,
"transformToTicks": 5
},
"walk": {
"poseName": "walk",
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.is_sprinting",
"standing": {
"poseTypes": ["STAND", "FLOAT", "NONE", "PORTRAIT", "PROFILE"],
"condition": "!q.in_air",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
"q.look('head', 0.4, 0.25, 5, -5, 10, -10)",
"q.bedrock('mudsdale', 'ground_walk')",
"q.bedrock_stateful('mudsdale', 'blink')",
{
"condition": "q.is_ridden && q.has_entity && !q.in_air",
"animation": "q.bedrock('mudsdale', 'ride_ground_walk')"
}
"q.bedrock('mudsdale', 'ground_idle')",
"q.bedrock_stateful('mudsdale', 'blink')"
],
"transformTicks": 10
"transformTicks": 5
},
"run": {
"poseTypes": ["WALK", "SWIM"],
"condition": "q.is_sprinting",
"condition": "!q.in_air && q.is_sprinting",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
@@ -83,7 +59,30 @@
"animation": "q.bedrock('mudsdale', 'ride_ground_run')"
}
],
"transformTicks": 10
"transformTicks": 5
},
"walk": {
"poseTypes": ["WALK", "SWIM"],
"condition": "!q.in_air && !q.is_sprinting",
"animations": [
"q.look('neck', 0.5, 0.5, 15, -15, 30, -30)",
"q.look('neck2', 0.5, 0.5, 10, -10, 25, -25)",
"q.look('head', 0.4, 0.25, 5, -5, 10, -10)",
"q.bedrock('mudsdale', 'ground_walk')",
"q.bedrock_stateful('mudsdale', 'blink')",
{
"condition": "q.is_ridden && q.has_entity && !q.in_air",
"animation": "q.bedrock('mudsdale', 'ride_ground_walk')"
}
],
"transformTicks": 5
},
"sleep": {
"poseTypes": ["SLEEP"],
"namedAnimations": {
"cry": "q.bedrock_stateful('dummy', 'cry')"
},
"animations": ["q.bedrock('mudsdale', 'sleep')"]
}
}
}
Loaded 100 of 371 files, more files were not shown because too many files have changed in this diff. Show more