Compare commits

...
Author SHA1 Message Date
Plastered_Crab 1d8c3df1ab More cleanup 2026-06-19 23:36:40 -07:00
Plastered_Crab ca8ae8f999 Clean up 2026-06-19 20:33:57 -07:00
Plastered_Crab d902e4dbab bye bye white texture 2026-06-19 20:30:23 -07:00
Plastered_Crab 001efd86f3 Remove experimental tinting FX on recalled pokemon 2026-06-19 20:25:18 -07:00
Plastered_Crab 1f2b6173d4 when recalling replace Pokemon texture with a plain white texture and then tint it red 2026-06-19 19:59:31 -07:00
Plastered_Crab e4844c18fb Clean up 2026-06-19 13:12:07 -07:00
Plastered_Crab 2305a1792d Make red recall effect on PokemonRenderer stronger, fix placement of beam from pokeball when catching, show pokeball in hand when recalling party pokemon in both 1st and 3rd person 2026-06-19 12:59:14 -07:00
Plastered_Crab cf0a6d17e0 changes to return pokemon effect 2026-06-19 07:04:39 -07:00
Polymeta 6148b58fdc Merge branch 'qa-fixes-84' into 'main'
Qa fixes 84

See merge request cable-mc/cobblemon!2314
2026-06-17 11:17:33 +00:00
Faintful 1e4936aeac Add changelog 2026-06-16 20:40:08 +02:00
Faintful 15ea72e777 Fixed Smoked Tail Curry returning a wooden bowl when consumed 2026-06-16 20:38:56 +02:00
Polymeta 3c3d4e4552 [skip-ci] changelogging 2026-06-16 17:43:50 +00:00
Polymeta 796e416578 Merge branch 'fix-auto-third-person-mod-compat' into 'main'
Add check for remember ride camera config when dismounting

Closes #2012

See merge request cable-mc/cobblemon!2308
2026-06-16 17:37:08 +00:00
lionandPolymeta 7608dfde94 Add check for remember ride camera config when dismounting 2026-06-16 17:37:07 +00:00
Polymeta b2b871617a Merge branch 'qa-fixes-85' into 'main'
Qa fixes 85

See merge request cable-mc/cobblemon!2313
2026-06-16 17:19:16 +00:00
Faintful bc4c8d13b7 Fix Panpour consuming a held item when evolving with a Water Stone 2026-06-16 17:07:36 +02:00
Faintful 0f9c51f7dd Fixed full heal stackable block not dropping full heals 2026-06-16 16:05:06 +02:00
Polymeta 2c2623e0f9 Merge branch 'summary-and-pokedex-profile-translations' into 'main'
Add profile translation and scale properties specific to the Pokédex and summary

See merge request cable-mc/cobblemon!2309
2026-06-16 13:44:41 +00:00
lionandPolymeta 8ec85e7d2f Add profile translation and scale properties specific to the Pokédex and summary 2026-06-16 13:44:41 +00:00
Paul d5a08314eb Merge remote-tracking branch 'origin/lang-updates' 2026-06-16 20:36:49 +10:00
Paul 062c32be2a Correct the parsing of phases in habitat GUI (they aren't moon phases) 2026-06-16 20:33:54 +10:00
阿鱼andWeblate 09590b49cd Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.9% (8988 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 10:14:47 +00:00
Polymeta 420cbd2c99 Merge branch 'fix-pvn-fainted-party-battle' into 'main'
Fix PvN battle start with fainted parties

See merge request cable-mc/cobblemon!2311
2026-06-16 09:45:36 +00:00
Jongho Hong 0380013f37 Add changelog entry 2026-06-16 18:41:43 +09:00
阿鱼andWeblate 6c1fcc103a Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.7% (8973 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 09:14:38 +00:00
阿鱼andWeblate 59b01c3988 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.7% (8971 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:58:39 +00:00
阿鱼andWeblate 678fa2d0ce Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.6% (8961 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:28:14 +00:00
Jongho Hong 94abd79923 Fix PvN battle start with fainted parties 2026-06-16 17:22:50 +09:00
阿鱼andWeblate 0a1931aaae Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.6% (8958 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:21:26 +00:00
阿鱼andWeblate 85d76dcc29 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.5% (8952 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 08:07:26 +00:00
阿鱼andWeblate bd0a9ef654 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.4% (8944 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 07:27:07 +00:00
阿鱼andWeblate 7a702e276c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.2% (8926 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 05:41:55 +00:00
阿鱼andWeblate 3f9a2825cb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 94.2% (8921 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 05:30:18 +00:00
阿鱼andWeblate d1462bc27b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.9% (8892 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 05:05:07 +00:00
阿鱼andWeblate 211b14dbd0 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.5% (8852 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 04:59:55 +00:00
阿鱼andWeblate 47e83003c3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8850 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 04:59:34 +00:00
阿鱼andWeblate 59134c4212 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8849 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-16 04:32:46 +00:00
阿鱼andWeblate 44b434562c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8847 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-15 20:32:05 +00:00
Faintful 7af9b0854a Fixed Status Cure items not returning a bottle after use 2026-06-15 17:55:22 +02:00
Hiroku 344b0750f9 Merge branch 'implement_pokemon' into 'main'
more QA fixes

See merge request cable-mc/cobblemon!2310
2026-06-15 04:26:30 +00:00
ewwww 10d9d97c11 restored broken or missing seat locators for Ariados, Bastiodon, Dhelmise, Dondozo, Drifblim, Girafarig, and Klinklang 2026-06-15 00:06:56 -04:00
Paul 94bcfba076 Phase count should be derived, not set 2026-06-14 22:10:46 +10:00
RedGenesectNinja 69a75ffcd4 Fixed broken Alola bias Exeggcute textures 2026-06-13 13:25:57 -05:00
阿鱼andWeblate cc1317dd06 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.4% (8845 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-13 07:46:03 +00:00
Polymeta e15ac73b1b Merge branch 'fix-enchanted-fossil-items' into 'main'
Fix crash when using enchanted items in the ressurection machine

Closes #1973

See merge request cable-mc/cobblemon!2307
2026-06-11 21:48:56 +00:00
lionandPolymeta 6c6576c117 Fix crash when using enchanted items in the ressurection machine 2026-06-11 21:48:55 +00:00
Polymeta ebdfa7edc0 Merge branch 'fix-pokemon-properties-nickname-parsing-to-json' into 'main'
Add pokémon nickname when serializing and deserializing to json on pokémon properties

Closes #1981

See merge request cable-mc/cobblemon!2306
2026-06-11 13:48:21 +00:00
lionandPolymeta 297e8eae77 Add pokémon nickname when serializing and deserializing to json on pokémon properties 2026-06-11 13:48:21 +00:00
Polymeta ea8179018d Merge branch 'modded-discs-compat' into 'main'
Add modded discs compatibility with disc shelves

See merge request cable-mc/cobblemon!2305
2026-06-11 08:20:18 +00:00
lionandPolymeta 14fccfae1d Add modded discs compatibility with disc shelves 2026-06-11 08:20:18 +00:00
Polymeta 26386638ad Merge branch 'PathingThresholds' into 'main'
Fixed wider pokemon being completely unable to hop up ledges

See merge request cable-mc/cobblemon!2304
2026-06-10 08:21:01 +00:00
JazzMcNade 5d1d99b64a Rolled back jump height change 2026-06-09 23:58:44 -05:00
RedGenesectNinja a3c5a6c377 Implemented Yamask fixes 2026-06-09 21:58:33 -05:00
Polymeta eb2a5837eb Merge branch 'oops-unsynced-tms' into 'main'
Sync TM Data

See merge request cable-mc/cobblemon!2303
2026-06-09 18:35:59 +00:00
Gertimoshka 93298d9a87 Sync TM Data 2026-06-09 20:48:35 +03:00
Watuneni iteiteandWeblate abb5346305 Translated using Weblate (Japanese)
Currently translated at 96.5% (9139 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-09 15:19:33 +00:00
Watuneni iteiteandWeblate 9466f66721 Translated using Weblate (Japanese)
Currently translated at 96.4% (9129 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-09 14:13:54 +00:00
Watuneni iteiteandWeblate 716ea55bc7 Translated using Weblate (Japanese)
Currently translated at 96.2% (9115 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-09 14:01:57 +00:00
Polymeta 4d1f46c37c remove unused config values
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-06-08 14:55:41 +01:00
ManriqueandWeblate 15f0ad1821 Translated using Weblate (Spanish)
Currently translated at 97.2% (9211 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-06-08 08:42:34 +00:00
Polymeta a2101b5759 whoops
Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-06-08 09:29:49 +01:00
Polymeta 187a190ec6 fix size categories not working properly on servers with non-default scales
Closes #2022

Signed-off-by: Polymeta <4726322-polymeta@users.noreply.gitlab.com>
2026-06-08 09:16:57 +01:00
JazzMcNade 0d433ff394 Fixed wider pokemon being completely unable to hop up ledges
Fixed pokemon not being able to hop up snow
2026-06-07 23:26:31 -05:00
Watuneni iteiteandWeblate a16975c750 Translated using Weblate (Japanese)
Currently translated at 96.1% (9105 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-07 15:19:10 +00:00
Watuneni iteiteandWeblate c0e6d87c40 Translated using Weblate (Japanese)
Currently translated at 96.1% (9105 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-07 12:39:38 +00:00
Watuneni iteiteandWeblate 91078b917e Translated using Weblate (Japanese)
Currently translated at 96.0% (9090 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-06-07 12:02:11 +00:00
ewwww b7e27fa52a Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-06-05 21:10:08 -04:00
ewwww dc87ffd2a8 luvdisc faint fix 2026-06-05 21:09:49 -04:00
Polymeta d873399d05 Merge branch 'implement_pokemon' into 'main'
for merging when the last of the QA fixes are finished

See merge request cable-mc/cobblemon!2302
2026-06-05 08:28:27 +00:00
Jerzykv a7aab51e0d These didn't get in for some reason 2026-06-05 08:24:37 +02:00
ewwww e8e2057558 popplio t-pose fix 2026-06-04 23:51:06 -04:00
Polymeta 56b5dba911 Merge branch 'stoobid-aram' into 'main'
Stoobid Aram, Actually Fixed the Processor this time

See merge request cable-mc/cobblemon!2301
2026-06-04 22:51:01 +00:00
Aram f0a66458e5 Stoobid Aram, Actually Fixed the Processor this time 2026-06-05 00:31:55 +02:00
ewwww dba6a38f9e Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-06-04 13:07:42 -04:00
ewwww 342c0041e9 UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUGH 2026-06-04 13:07:27 -04:00
阿鱼andWeblate cbeda361d4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.3% (8835 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-04 15:12:59 +00:00
Hiroku a811b3347c Merge branch 'implement_pokemon' into 'main'
Implement pokemon

See merge request cable-mc/cobblemon!2300
2026-06-04 10:53:32 +00:00
Polymeta 80e593f5c6 Merge branch 'fix-/locate-lie' into 'main'
Fixed the HeightRangeProcessor

See merge request cable-mc/cobblemon!2297
2026-06-04 10:43:12 +00:00
ewwww ff617348fe implemented arbok remodel 2026-06-04 06:00:31 -04:00
ewwww 1adecbf5f6 fixed incorrect "Head" naming for gallade 2026-06-04 04:37:32 -04:00
ewwww 29dbb13a0e cramorant poser tweaks 2026-06-04 04:11:06 -04:00
ewwww 67e03ecebd ditto poser tweaks 2026-06-04 04:10:57 -04:00
ewwww 215f48bdc7 musharna placeholder sleep 2026-06-04 04:03:05 -04:00
ewwww d4beab1bfb jynx poser tweaks 2026-06-04 04:02:56 -04:00
ewwww f2c21ec902 smoochum remodel 2026-06-04 04:02:46 -04:00
ewwww c9f3912677 updated omanyte and omastar's posers 2026-06-03 22:39:36 -04:00
ewwww c21b7d1a7d marked cherubi line as implemented + tweaked changelog 2026-06-03 19:59:45 -04:00
ewwww 26068694ad grafaiai animations 2026-06-03 07:15:38 -04:00
Polymeta c86d8f0696 Merge branch '1.8-move-effects-funny' into 'main'
1.8-move-effects-funny

See merge request cable-mc/cobblemon!2299
2026-06-03 09:55:40 +00:00
ewwww 16468059e4 oopsies forgot a few 2026-06-03 03:57:22 -04:00
ewwww 54dbe4769e changelog 2026-06-03 03:51:33 -04:00
321RetroGamer 82019c3722 1.8 MOVE STUFF (real)
NEW MOVES:
- Blizzard
- Disarming Voice
- Dragon Breath
- Dragon Rage
- Drain Punch
- Fairy Wind
- Fire Fang
- Gust
- Horn Drill (effect by Gesteeyy)
- Hydro Pump
- Ice Fang
- Leafage
- Leaf Storm
- Light Screen
- Night Shade
- Play Rough
- Reflect
- Rock Slide
- Sonic Boom
- Sucker Punch
- Supersonic
- Thunder Fang

ANIMATION .JSONS:
- Play Rough

TWEAKS:
- Confusion
- Eruption
- Flamethrower
- Hypnosis
- Poison Fang
- Protect
- Psychic
- Sing
- Spore
- String Shot
- Tail Whip
- Thunder Wave
- Water Pulse

FIXES:
- Dragon Claw (Action Effect Tweaks)
- Fire Punch (Action Effect Tweaks)
- Flame Burst (Delta Fixes)
- Flame Charge (Action Effect Tweaks)
- Frost Breath (Glow Fixes)
- Ice Punch (Action Effect Tweaks, Glow Fixes)
- Icy Wind (Action Effect Tweaks, Glow Fixes)
- Mud Sport (Glow Fixes)
- Quick Attack (Glow Fixes)
- Rage Powder (Action Effect Tweaks, Fixed Missing Texture Directory)
- Razor Leaf (Glow Fixes)
- Sand Attack (Action Effect Tweaks)
- Scratch (Glow Fixes)
- Shadow Claw (Action Effect Tweaks)
- Tackle (Glow Fixes)
- Thunder (Fixed Missing Texture Directory)
- Thunder Punch (Action Effect Tweaks)
- Water Gun (Glow Fixes)
- Water Sport (Glow Fixes)

MISCELLANEOUS:
- Shellder Line Anim/Poser Edits (Protect Signature Showcase)
2026-06-03 01:40:41 -05:00
阿鱼andWeblate 079a2fb50d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 93.3% (8835 of 9467 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/zh_Hans/
2026-06-03 06:11:14 +00:00
ewwww 78f0951345 (proper) Ditto remodel 2026-06-03 00:27:04 -04:00
Paul 96aaab29e2 Changelog for lang 2026-06-03 11:55:47 +10:00
Paul b1def44953 Merge remote-tracking branch 'origin/implement_pokemon' 2026-06-03 11:55:30 +10:00
Paul e2e38add1d Merge remote-tracking branch 'origin/lang-updates' 2026-06-03 11:54:38 +10:00
ewwww 1db0b0709a animation tweaks 2026-06-02 05:41:51 -04:00
ewwww c3ce3db387 implemented Turtonator remodel 2026-06-02 05:41:38 -04:00
ewwww b5e6fd3816 e 2026-06-01 23:20:38 -04:00
MeAlam1 5b5dcddb25 Fixed the HeightRangeProcessor 2026-06-01 20:16:27 +02:00
ewwww 0158524bff oops. 2026-06-01 07:11:35 -04:00
ewwww 2611e311a7 luvdisc poser conversion + new animations 2026-06-01 06:47:42 -04:00
ewwww 17061691a1 corrected Feraligatr profile scale 2026-06-01 05:16:36 -04:00
ewwww 9c6d7ddfef implemented Tyranitar remodel 2026-06-01 05:16:23 -04:00
Polymeta e8119198c1 Merge branch 'type_alpha_drops' into 'main'
Alphas also drop items based on the pokemon types

See merge request cable-mc/cobblemon!2295
2026-05-31 08:58:53 +00:00
Hiroku 55c0e3e8a0 Merge branch 'IceTypeSnowImmunity' into 'main'
Added powdered snow immunity to ice types

Closes #1809

See merge request cable-mc/cobblemon!2293
2026-05-31 02:07:20 +00:00
PaulFreck 70443bc7b0 added optional tag for powdered snow immunity 2026-05-30 08:26:41 -05:00
Hiroku acb166b5b9 Merge branch 'implement_pokemon' into 'main'
Implement merge to main

See merge request cable-mc/cobblemon!2296
2026-05-30 06:17:46 +00:00
Carmendar 462c361998 No more eepy Seedot line in party/PC 2026-05-30 00:51:58 -05:00
Carmendar 76c90fb1ae Merge branch 'main' into implement_pokemon 2026-05-30 00:49:53 -05:00
Carmendar 27e11dee87 Gen3 alpha eyes 2026-05-30 00:40:24 -05:00
Paul d7c8b8dd62 Alphas also drop items based on the pokemon types 2026-05-30 14:15:00 +10:00
RedGenesectNinja eb12ccf6d0 Updated changelog 2026-05-29 18:52:22 -05:00
mystixmew e7b58edcd1 fix: resolve Linux compatibility issue in Getch class
msvcrt platform detection was broken - the try/except ImportError in
__init__ never triggered since the import attempt already happened at
module level. Replaced with a _has_msvcrt boolean flag set at import
time to correctly route Linux to _getch_unix. Also fixed _getch_unix
to return ch.encode() so key comparisons behave consistently across
platforms.
2026-05-28 17:43:18 -04:00
Polymeta ca5c2ba381 Merge branch 'shiny-volume-tweaks' into 'main'
Update sounds.json and changelog documentation

See merge request cable-mc/cobblemon!2294
2026-05-28 14:15:12 +00:00
SterrezoandPolymeta 8aa538d8e7 Update sounds.json and changelog documentation 2026-05-28 14:15:11 +00:00
Polymeta 1bd33a0635 Merge branch 'main' into implement_pokemon
# Conflicts:
#	common/src/main/resources/assets/cobblemon/lang/en_us.json
2026-05-28 15:13:23 +01:00
Polymeta ff9ca4ee09 Merge branch 'implementation-vibe-check' into 'main'
Added a script to automatically find implementation issues

See merge request cable-mc/cobblemon!2290
2026-05-28 14:10:57 +00:00
ewwww 1def8fcd1a oops 2026-05-28 06:14:50 -04:00
ewwww d53603ec49 futureproofing 2026-05-28 05:50:28 -04:00
Sterrezo 5362995fbb Added checks for wing flap sound keyframes 2026-05-27 14:23:26 +02:00
PaulFreck e2d0b12f94 small change to how freezing works 2026-05-26 20:01:58 -05:00
PaulFreck b32c2cb81c added powdered snow immunity to ice types 2026-05-26 19:48:29 -05:00
Sterrezo 98a7240191 Lenient spellcheck 2026-05-27 02:08:11 +02:00
Sterrezo 84adc0e1cb Minor oopsie 2026-05-27 01:55:55 +02:00
Sterrezo 3ab2dfa0b3 Anti-optimizations 2026-05-27 01:47:28 +02:00
Polymeta d67669a278 Merge branch 'smol-structure-crash-fix' into 'main'
Structure crash fix

See merge request cable-mc/cobblemon!2292
2026-05-26 22:12:37 +00:00
Sterrezo 2a85dee373 Fixed structure file names 2026-05-26 22:23:15 +02:00
Sterrezo 86e8238230 Grammar 2026-05-26 20:16:31 +02:00
Sterrezo bdc7b5a504 Small correction 2026-05-26 20:10:07 +02:00
Sterrezo f3c165d282 Added geo and detailed locator parity checks 2026-05-26 20:04:04 +02:00
Sterrezo 9caf8376bc Made this thing easier to use 2026-05-26 17:53:17 +02:00
Polymeta 8661f7a01e Merge branch 'z-fighting-b-gone' into 'main'
Pokedex Z-Fighting Begone

See merge request cable-mc/cobblemon!2289
2026-05-26 15:17:55 +00:00
Polymeta e933a03e92 Merge branch 'Habitat-Blocks-pt2' into 'main'
drifting icebergs, volcanic plumes, sketal falls, strange fungal dwellings,...

See merge request cable-mc/cobblemon!2291
2026-05-26 15:12:31 +00:00
Watuneni iteiteandWeblate 982fc054a9 Translated using Weblate (Japanese)
Currently translated at 98.5% (9183 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-26 07:06:18 +00:00
Watuneni iteiteandWeblate cb73bfb31b Translated using Weblate (Japanese)
Currently translated at 98.3% (9170 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-26 06:47:54 +00:00
Slippy 5b84c2c8a0 drifting icebergs, volcanic plumes, sketal falls, strange fungal dwellings, and lush cenotes have habitat blocks. Adjusted the rates of the nether habitats once again. 2026-05-25 12:28:04 -05:00
Sterrezo 9f998d92e6 Added a script to automatically find issues 2026-05-25 17:55:36 +02:00
Test b835bfe596 dex geo, deepslate texture 2026-05-25 03:10:46 -04:00
dhi_holo 757e3d48cb Update pokedex_red_model.json 2026-05-25 05:41:25 +10:00
dhi_holo 2fbf77dd65 Update pokedex_red_model.json 2026-05-25 05:22:41 +10:00
dhi_holo bd451bf951 Pokedex Z-Fighting Begone 2026-05-25 04:20:44 +10:00
geumuandWeblate d88a9dda92 Translated using Weblate (Korean)
Currently translated at 100.0% (9320 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-05-24 14:05:54 +00:00
Watuneni iteiteandWeblate 86c2282cf8 Translated using Weblate (Japanese)
Currently translated at 97.8% (9120 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-24 09:11:09 +00:00
Watuneni iteiteandWeblate 6ac8523cf5 Translated using Weblate (Japanese)
Currently translated at 97.2% (9060 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-23 17:05:17 +00:00
ManriqueandWeblate acb0aa854e Translated using Weblate (Spanish)
Currently translated at 99.8% (9310 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-23 17:05:16 +00:00
ewwww fdafb1e64a updated en_us 2026-05-22 21:35:48 -04:00
RedGenesectNinja bd525c8740 Implemented the rest of the Gen 4 alpha eyes 2026-05-21 04:30:28 -05:00
ewwww 209dee1d25 . 2026-05-21 03:48:37 -04:00
ewwww 1eedc4862a Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-21 00:17:40 -04:00
ewwww b1fbf9ca02 PYRO BALLING 2026-05-21 00:17:28 -04:00
ewwww 5fda445274 cinderace tweak 2026-05-20 23:08:09 -04:00
Jerzykv ce0265e954 Goodra animation tweaks 2026-05-20 22:38:56 +02:00
ManriqueandWeblate da1654d9aa Translated using Weblate (Spanish)
Currently translated at 99.7% (9293 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 16:10:05 +00:00
ManriqueandWeblate 27132031cd Translated using Weblate (Spanish)
Currently translated at 99.6% (9292 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 16:09:24 +00:00
GenotypeXD cdc4a571b6 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-20 06:26:07 -05:00
GenotypeXD e8bc138e5d Gen 6 Alphas 2026-05-20 06:25:27 -05:00
ManriqueandWeblate 038d239f95 Translated using Weblate (Spanish)
Currently translated at 98.7% (9208 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 11:20:21 +00:00
Watuneni iteiteandWeblate 9b2a1dc065 Translated using Weblate (Japanese)
Currently translated at 96.9% (9035 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-20 10:26:50 +00:00
ManriqueandWeblate 3c222a3349 Translated using Weblate (Spanish)
Currently translated at 97.1% (9052 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-20 10:26:49 +00:00
RedGenesectNinja a1035608c9 Merge remote-tracking branch 'origin/implement_pokemon' into implement_pokemon 2026-05-20 04:06:02 -05:00
RedGenesectNinja 2345565e38 Implemented more Gen 4 alpha eyes and a remodel for Chatot 2026-05-20 04:05:16 -05:00
ewwww 620002c165 chopped off gastly's tongue & poked zubat's eyes out 2026-05-20 01:45:14 -04:00
Sterrezo d89224a684 FIxed incorrectly named sound events for Galarian Ponyta and Rapidash cries 2026-05-19 14:15:05 +02:00
ewwww 856eb2a1bd pyro balling 2026-05-18 06:33:20 -04:00
TeggyandWeblate 136d7c08b8 Translated using Weblate (Spanish)
Currently translated at 94.2% (8786 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-17 16:28:35 +00:00
Jerzykv ddc03766bb Implemented alpha eyes/locators of Galar and Hisui 2026-05-17 17:08:25 +02:00
ewwww 81dccf9c07 various fixes 2026-05-17 08:05:04 -04:00
Watuneni iteiteandWeblate ea93b8c1d8 Translated using Weblate (Japanese)
Currently translated at 96.8% (9024 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-17 09:41:51 +00:00
Watuneni iteiteandWeblate 1abe39db3c Translated using Weblate (Japanese)
Currently translated at 96.6% (9012 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-17 02:13:26 +00:00
TeggyandWeblate 4e7cdb6266 Translated using Weblate (Spanish)
Currently translated at 94.2% (8786 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-17 02:13:25 +00:00
Carmendar 79b13acdc6 Gen7 alpha eyes 2026-05-16 20:43:04 -05:00
ewwww 0ffd6fad90 gen 2 locators wip, pushing for now 2026-05-16 01:47:17 -04:00
geumuandWeblate 3c9661dfd3 Translated using Weblate (Korean)
Currently translated at 100.0% (9320 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-05-16 04:58:00 +00:00
Watuneni iteiteandWeblate 520f522f3c Translated using Weblate (Japanese)
Currently translated at 96.6% (9012 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ja/
2026-05-16 04:58:00 +00:00
TeggyandWeblate 113ae1f749 Translated using Weblate (Spanish)
Currently translated at 94.2% (8785 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-16 04:57:58 +00:00
ewwww 61bf5ffab1 feraligatr poser update 2026-05-15 23:40:09 -04:00
Gustavo PuerariandWeblate 87da3e83a0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.5% (9090 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/pt_BR/
2026-05-15 14:36:53 +00:00
geumuandWeblate c325d0215a Translated using Weblate (Korean)
Currently translated at 99.6% (9290 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/ko/
2026-05-15 14:36:50 +00:00
TeggyandWeblate 8afb4e6d16 Translated using Weblate (Spanish)
Currently translated at 93.7% (8742 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-15 14:36:47 +00:00
ManriqueandWeblate 0ffff6f4af Translated using Weblate (Spanish)
Currently translated at 93.7% (8736 of 9320 strings)

Translation: Cobblemon/Mod
Translate-URL: https://lang.cobblemon.com/projects/cobblemon/mod/es/
2026-05-15 13:06:40 +00:00
1116 changed files with 48719 additions and 8569 deletions
+1
View File
@@ -24,6 +24,7 @@ eclipse
run
runClient
runServer
utilityscripts/implementation/*.txt
# Files from Forge MDK
forge*changelog.txt
+117 -27
View File
@@ -56,6 +56,7 @@
- Pressing the inventory key now closes the Pokémon interact wheel GUI
- Pokémon cries now play when clicking Pokémon in the summary screen.
- Pressing the Summary key while either the starter selection or summary screen are open now closes those screens
- Ice type Pokémon are now immune to Packed Snow
### New rideable Pokémon
- Drampa
@@ -67,6 +68,7 @@
- Milotic
### Pokémon Added
#### Generation 3
- Wurmple
- Silcoon
- Beautifly
@@ -74,59 +76,55 @@
- Dustox
- Skitty
- Delcatty
- Seviper
- Zangoose
#### Generation 4
- Cherubi
- Cherrim
- Stunky
- Skuntank
#### Generation 5
- Audino
- Pawniard
- Bisharp
- Kingambit
#### Generation 6
- Pancham (+ Cosmetic with Black Glasses)
- Pangoro (+ Cosmetic with Black Glasses)
#### Generation 7
- Rockruff
- Lycanroc
#### Generation 8
- Rolycoly
- Carkol
- Coalossal
- Runerigus
- Snom
- Frosmoth
- Indeedee
- Duraludon
- Archaludon
- Applin
- Flapple
- Appletun
- Dipplin
- Hydrapple
#### Generation 9
- Nymble
- Lokix
- Kingambit
- Dipplin
- Archaludon
- Hydrapple
#### Regional Forms
- Sandshrew (Alolan)
- Sandslash (Alolan)
- Avalugg (Hisuian)
### Model updates for the following Pokémon
- Goomy
- Sliggoo
- Goodra
- Porygon
- Porygon2
- Porygon-Z
- Zubat
- Golbat
- Crobat
- Sandshrew (Alolan Form)
- Sandslash (Alolan Form)
- Yamask (Galarian Form)
- Avalugg (Hisuian Form)
### Model updates for the following Pokémon
@@ -136,11 +134,12 @@
- Zubat
- Golbat
- Crobat
- Ditto
- Porygon
- Porygon2
- Porygon-Z
- Skarmory
- Smoochum
- Jynx
- Popplio
- Brionne
@@ -148,17 +147,22 @@
- Fletchling
- Fletchinder
- Talonflame
- Sableye
- Mawile
- Goomy
- Sliggoo
- Goodra
- Nacli
- Naclstack
- Garganacl
- Bidoof
- Cranidos
- Chatot
- Yamask
- Cofagrigus
- Tyranitar
- Turtonator
- Arbok (New Patterns: Angry, Cartoon, Clown, Comedic, Crow, Grin, Ink, Modern, Rain, Scribble, Silence, Sloth, Suspicious, Will)
#### Model changes to the regional bias resource pack:
@@ -192,6 +196,12 @@
- Shedinja
- Skwovet
- Greedent
- Bidoof
- Cranidos
- Chatot
- Yamask
- Cofagrigus
- Luvdisc
#### Added sounds to the following moves
- Absorb
@@ -288,6 +298,15 @@
- Lowered the volume of Blitzle and Zebstrika's cry
- Fixed Raichu (male) and Alolan Raichu (both genders) not displaying the correct Partner Cap when Pewter Crunchies are in the cosmetic slot.
- Regional Foods will now prioritize being eaten instead of used for healing Pokémon, shift clicking will use it as healing
- Resolved Z-Fighting on Pokédex Models
- Restored Ninjask's ability to do barrel rolls
- Fixed a crash caused by adding enchanted items to the Resurrection Machine
- Fixed a crash that could occur when starting a PvN battle with only fainted Pokémon.
- Fixed the Remember Riding Camera config not being respected when dismounting and resolved the incompatibility with the Auto Third Person mod
- Fixed Full Heal block not dropping Full Heals
- Fixed status cure items not returning an empty bottle when used
- Fixed Panpour consuming its held item when evolving with a Water Stone
- Fixed Smoked Tail Curry returning a Wooden Bowl when consumed despite it not being included in the recipe
### Fixes
- Fixed Croagunk's walkspeed
@@ -348,6 +367,8 @@
- Separated all the functions of MoLangFunctions.kt into their own files.
- Spawn buckets and their base weights are now provided by the spawner, with different base weights for world, fishing, snack, and habitat spawn buckets.
- Removed "SpawnBucket" class in favour of just storing maps of bucket names to weights.
- Fixed nicknames not being applied to Pokémon spawned from `spawn_pool_world` files.
- Added support for `profilePokedexScale`, `profilePokedexTranslation`, `profileSummaryScale`, and `profileSummaryTranslation` in poser files for finer control over profile displays.
### Molang & Datapacks
- Added `moveset_builders` datapack folder for different styles of movesets.
@@ -371,15 +392,84 @@
- Ride sounds no longer play when submerged unless specified with a new setting
- NPC Trainers can now call a `command` animation when issuing a command in battle.
- Added a q.failed function to move action effects.
- Herd spawned Pokémon have their levels controlled differently. The `levelRange` property now acts as a clamp instead of a filter, with a new `herdLevelRange` property to do the filter behaviour.
- Herd spawned Pokémon have their levels controlled differently. The `levelRange` property now acts as a clamp instead of a filter, with a new `herdLevelRange` property to do the filter behaviour.
- `q.sound` now accepts three parameters (sound event, volume and pitch) instead of just the sound event and pitch.
### Particles
#### New Move Animations
- Blizzard
- Disarming Voice
- Draco Meteor
- Dragon Breath
- Dragon Rage
- Drain Punch
- Fairy Wind
- Fire Fang
- Gust
- Horn Drill
- Hydro Pump
- Ice Fang
- Leafage
- Leaf Storm
- Light Screen
- Night Shade
- Play Rough
- Pyro Ball
- Reflect
- Rock Slide
- Sonic Boom
- Sucker Punch
- Supersonic
- Thunder Fang
#### Tweaks and Fixes (Moves)
- Confusion
- Dragon Claw
- Eruption
- Fire Punch
- Flame Burst
- Flame Charge
- Flamethrower
- Frost Breath
- Hypnosis
- Ice Punch
- Icy Wind
- Mud Sport
- Poison Fang
- Protect
- Psychic
- Quick Attack
- Rage Powder
- Razor Leaf
- Sand Attack
- Scratch
- Shadow Claw
- Sing
- Spore
- String Shot
- Tackle
- Tail Whip
- Thunder
- Thunder Punch
- Thunder Wave
- Water Gun
- Water Pulse
- Water Sport
#### Miscellaneous Particles
+ Added Wild Might particles for Alpha Pokémon
+ Updated stat increase and decrease particles
### Localization
- Updated translations for:
- Japanese
- German
- Spanish
- Ecuadorian Spanish
- Brazilian Portuguese
- Simplified Chinese
- Traditional Chinese
- Korean
@@ -0,0 +1,111 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin;
import com.cobblemon.mod.common.mixin.accessor.SinglePoolElementAccessor;
import com.cobblemon.mod.common.world.structureprocessors.HeightRangeStructureProcessor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.structure.Structure;
import net.minecraft.world.level.levelgen.structure.pools.*;
import net.minecraft.world.level.levelgen.structure.pools.alias.PoolAliasLookup;
import net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.Optional;
@Mixin(JigsawPlacement.class)
public class JigsawPlacementMixin {
@Inject(
method = "addPieces(Lnet/minecraft/world/level/levelgen/structure/Structure$GenerationContext;Lnet/minecraft/core/Holder;Ljava/util/Optional;ILnet/minecraft/core/BlockPos;ZLjava/util/Optional;ILnet/minecraft/world/level/levelgen/structure/pools/alias/PoolAliasLookup;Lnet/minecraft/world/level/levelgen/structure/pools/DimensionPadding;Lnet/minecraft/world/level/levelgen/structure/templatesystem/LiquidSettings;)Ljava/util/Optional;",
at = @At("RETURN"),
cancellable = true
)
private static void onAddPieces(
Structure.GenerationContext context,
Holder<StructureTemplatePool> startPool,
Optional<ResourceLocation> startJigsawName,
int maxDepth,
BlockPos pos,
boolean useExpansionHack,
Optional<Heightmap.Types> projectStartToHeightmap,
int maxDistanceFromCenter,
PoolAliasLookup aliasLookup,
DimensionPadding dimensionPadding,
LiquidSettings liquidSettings,
CallbackInfoReturnable<Optional<Structure.GenerationStub>> cir
) {
Optional<Structure.GenerationStub> result = cir.getReturnValue();
if (result.isEmpty()) {
return;
}
BlockPos spawnPos = result.get().position();
boolean canPlace = cobblemon$canAnyStartElementPlace(context, startPool, spawnPos);
if (canPlace) {
return;
}
cir.setReturnValue(Optional.empty());
}
@Unique
private static boolean cobblemon$canAnyStartElementPlace(
Structure.GenerationContext generationContext,
Holder<StructureTemplatePool> startPool,
BlockPos startPos
) {
for (StructurePoolElement element : startPool.value().templates) {
Optional<HeightRangeStructureProcessor> heightRangeProcessor = cobblemon$getHeightRangeProcessor(element);
if (heightRangeProcessor.isEmpty()) {
return true;
}
HeightRangeStructureProcessor processor = heightRangeProcessor.get();
boolean valid = processor.isValidPlacement(
generationContext.chunkGenerator(),
generationContext.heightAccessor(),
generationContext.randomState(),
startPos
);
if (valid) {
return true;
}
}
return false;
}
@Unique
private static Optional<HeightRangeStructureProcessor> cobblemon$getHeightRangeProcessor(StructurePoolElement element) {
if (!(element instanceof SinglePoolElement)) {
return Optional.empty();
}
StructureProcessorList processorList = ((SinglePoolElementAccessor) element).getProcessors().value();
for (StructureProcessor processor : processorList.list()) {
if (processor instanceof HeightRangeStructureProcessor heightRangeStructureProcessor) {
return Optional.of(heightRangeStructureProcessor);
}
}
return Optional.empty();
}
}
@@ -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.mixin.accessor;
import net.minecraft.core.Holder;
import net.minecraft.world.level.levelgen.structure.pools.SinglePoolElement;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(SinglePoolElement.class)
public interface SinglePoolElementAccessor {
@Accessor("processors")
Holder<StructureProcessorList> getProcessors();
}
@@ -10,11 +10,13 @@ package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
import com.cobblemon.mod.common.client.render.player.RecallArmAnimationTracker;
import com.cobblemon.mod.common.duck.RidePassenger;
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import org.spongepowered.asm.mixin.Final;
@@ -96,4 +98,26 @@ public class HumanoidModelMixin {
MountedPlayerRenderer.INSTANCE.animate((HumanoidModel<AbstractClientPlayer>)(Object)this, pokemonEntity, player, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
}
}
// Pose the right arm forward while recalling so the held Poké Ball sits out in front.
@Inject(method = "setupAnim*", at = @At("TAIL"))
public void cobblemon$poseRecallArm(
LivingEntity entity,
float limbSwing,
float limbSwingAmount,
float ageInTicks,
float netHeadYaw,
float headPitch,
CallbackInfo ci
) {
if (!(entity instanceof AbstractClientPlayer player)) return;
// Skip while riding so we don't override the mounted-riding arm animation.
if (entity.getVehicle() instanceof PokemonEntity) return;
float raise = RecallArmAnimationTracker.INSTANCE.raiseFactor(player.getUUID());
if (raise <= 0f) return;
float armForwardXRot = (float) (-Math.PI / 2.0);
this.rightArm.xRot = Mth.lerp(raise, this.rightArm.xRot, armForwardXRot);
this.rightArm.yRot = Mth.lerp(raise, this.rightArm.yRot, 0f);
this.rightArm.zRot = Mth.lerp(raise, this.rightArm.zRot, 0f);
}
}
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.client.render.player.RecallArmAnimationTracker;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.layers.ItemInHandLayer;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Hides the player's right-hand item while recalling so it doesn't overlap the recall Poké Ball
* drawn by PlayerRecallBallRenderer.
*/
@Mixin(ItemInHandLayer.class)
public class ItemInHandLayerMixin {
@Inject(method = "renderArmWithItem", at = @At("HEAD"), cancellable = true)
private void cobblemon$hideRecallHandItem(
LivingEntity entity,
ItemStack itemStack,
ItemDisplayContext itemDisplayContext,
HumanoidArm humanoidArm,
PoseStack poseStack,
MultiBufferSource multiBufferSource,
int light,
CallbackInfo ci
) {
if (humanoidArm == HumanoidArm.RIGHT && RecallArmAnimationTracker.INSTANCE.isRecalling(entity.getUUID())) {
ci.cancel();
}
}
}
@@ -9,6 +9,8 @@
package com.cobblemon.mod.common.mixin.client;
import com.cobblemon.mod.common.OrientationControllable;
import com.cobblemon.mod.common.client.render.player.FirstPersonRecallBallRenderer;
import com.cobblemon.mod.common.client.render.player.RecallArmAnimationTracker;
import com.cobblemon.mod.common.item.PokedexItem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
@@ -31,6 +33,12 @@ public class ItemInHandRendererMixin {
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
ci.cancel();
}
// While recalling, swap the main-hand item for the rising Poké Ball.
else if (interactionHand == InteractionHand.MAIN_HAND
&& RecallArmAnimationTracker.INSTANCE.isRecalling(abstractClientPlayer.getUUID())
&& FirstPersonRecallBallRenderer.INSTANCE.render(poseStack, multiBufferSource, j, f)) {
ci.cancel();
}
else if (abstractClientPlayer instanceof OrientationControllable controllable && controllable.getOrientationController().isActive()) {
}
@@ -308,7 +308,9 @@ object Cobblemon {
this.config.maxPokemonLevel,
this.config.maxPokemonFriendship,
this.config.maxDynamaxLevel,
this.config.unlockAllMoveDexMovesByDefault
this.config.unlockAllMoveDexMovesByDefault,
this.config.pokemonIntrinsicSizeMin,
this.config.pokemonIntrinsicSizeMax
).sendToPlayer(player)
}
@@ -405,7 +405,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
@JvmField
val BIG_MALASADA = regionalFoodItem("big_malasada", 64, 7, 0.3f, false)
@JvmField
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false, ItemStack(Items.BOWL, 1))
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false)
@JvmField
val JUBILIFE_MUFFIN = regionalFoodItem("jubilife_muffin", 64, 7, 0.3f, false)
@JvmField
@@ -131,6 +131,7 @@ import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangeP
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.tms.TechnicalMachineRegistrySyncPacket
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
@@ -439,6 +440,7 @@ object CobblemonNetwork {
list.add(PacketRegisterInfo(BehaviourSyncPacket.ID, BehaviourSyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
list.add(PacketRegisterInfo(RideSettingsSyncPacket.ID, RideSettingsSyncPacket::decode, RideSettingsSyncHandler))
list.add(PacketRegisterInfo(TechnicalMachineRegistrySyncPacket.ID, TechnicalMachineRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
// Effects
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
@@ -69,7 +69,7 @@ class HabitatPool {
pool.spawns = spawns
return pool
} else {
return HabitatPools.habitatPoolsById[poolId] ?: HabitatPool.default()
return HabitatPools.habitatPoolsById[poolId] ?: default()
}
}
}
@@ -94,6 +94,14 @@ class HabitatPool {
return spawns.mapNotNull { it.createSpawnDetail(habitatBlockEntity) }
}
fun getPhaseCount(): Int {
return spawns
.flatMap { it.phases?.ranges?.flatten() ?: emptySet() }
.toSet()
.count()
.coerceAtLeast(1)
}
fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeResourceLocation(id)
buffer.writeUtf(name)
@@ -17,7 +17,6 @@ import net.minecraft.network.RegistryFriendlyByteBuf
import net.minecraft.resources.ResourceLocation
class HabitatSettingsDTO() {
var numberOfPhases = 1
var phaseOrder = HabitatPhaseOrder.SIMPLE
lateinit var levelRange: IntRange
var modifiers: String = ""
@@ -28,7 +27,6 @@ class HabitatSettingsDTO() {
var naturalSettings: NaturalHabitatSettingsDTO? = null
constructor(habitatBlockEntity: HabitatBlockEntity) : this() {
this.numberOfPhases = habitatBlockEntity.numberOfPhases
this.phaseOrder = habitatBlockEntity.phaseOrder
this.levelRange = habitatBlockEntity.levelRange
this.modifiers = habitatBlockEntity.modifiers.asString()
@@ -44,7 +42,6 @@ class HabitatSettingsDTO() {
}
fun encode(buffer: RegistryFriendlyByteBuf) {
buffer.writeInt(numberOfPhases)
buffer.writeEnum(phaseOrder)
buffer.writeInt(levelRange.first)
buffer.writeInt(levelRange.last)
@@ -60,7 +57,6 @@ class HabitatSettingsDTO() {
}
fun decode(buffer: RegistryFriendlyByteBuf) {
this.numberOfPhases = buffer.readInt()
this.phaseOrder = buffer.readEnum(HabitatPhaseOrder::class.java)
val levelRangeStart = buffer.readInt()
val levelRangeEnd = buffer.readInt()
@@ -109,7 +109,7 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
DoubleValue(pokemon.species.nationalPokedexNumber.toDouble())
}
map["types"] = {
pokemon.form.types.map { it.toString() }.asArrayValue(::StringValue)
pokemon.form.types.map { it.showdownId }.asArrayValue(::StringValue)
}
map["gender_ratio"] = {
DoubleValue(pokemon.form.maleRatio.toDouble())
@@ -759,6 +759,7 @@ open class PokemonProperties {
shiny?.let { json.addProperty(DataKeys.POKEMON_SHINY, it) }
gender?.let { json.addProperty(DataKeys.POKEMON_GENDER, it.name) }
species?.let { json.addProperty(DataKeys.POKEMON_SPECIES_TEXT, it) }
nickname?.let { json.addProperty(DataKeys.POKEMON_NICKNAME, it.string) }
form?.let { json.addProperty(DataKeys.POKEMON_FORM_ID, it) }
friendship?.let { json.addProperty(DataKeys.POKEMON_FRIENDSHIP, it) }
fullness?.let { json.addProperty(DataKeys.POKEMON_FULLNESS, it) }
@@ -795,6 +796,7 @@ open class PokemonProperties {
shiny = json.get(DataKeys.POKEMON_SHINY)?.asBoolean
gender = json.get(DataKeys.POKEMON_GENDER)?.asString?.let { Gender.valueOf(it) }
species = json.get(DataKeys.POKEMON_SPECIES_TEXT)?.asString
nickname = json.get(DataKeys.POKEMON_NICKNAME)?.asString?.let(Component::literal)
form = json.get(DataKeys.POKEMON_FORM_ID)?.asString
friendship = json.get(DataKeys.POKEMON_FRIENDSHIP)?.asInt
fullness = json.get(DataKeys.POKEMON_FULLNESS)?.asInt
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.data.JsonDataRegistry
import com.cobblemon.mod.common.api.moves.MoveTemplate
import com.cobblemon.mod.common.api.moves.adapters.MoveTemplateAdapter
import com.cobblemon.mod.common.api.reactive.SimpleObservable
import com.cobblemon.mod.common.net.messages.client.tms.TechnicalMachineRegistrySyncPacket
import com.cobblemon.mod.common.util.adapters.TMObtainMethodAdapter
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
import com.cobblemon.mod.common.util.cobblemonResource
@@ -70,5 +71,7 @@ object TechnicalMachines : JsonDataRegistry<TechnicalMachine> {
fun getByResourceLocation(resourceLocation: ResourceLocation) = tmMap[resourceLocation]
fun getAllResourceLocations() = tmMap.keys.toSet()
override fun sync(player: ServerPlayer) {}
override fun sync(player: ServerPlayer) {
TechnicalMachineRegistrySyncPacket(tmMap.values.toList()).sendToPlayer(player)
}
}
@@ -349,11 +349,12 @@ object BattleBuilder {
npcPartyStores.add(npcParty)
}
if (playerActor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
val playerAvailablePokemon = playerActor.pokemonList.count { it.health > 0 }
if (playerAvailablePokemon < battleFormat.battleType.slotsPerActor) {
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
actorEntity = player,
requiredCount = battleFormat.battleType.slotsPerActor,
hadCount = playerActor.pokemonList.size
hadCount = playerAvailablePokemon
)
}
@@ -163,7 +163,8 @@ class TrackerActor(val uuid: UUID) {
//we assume that AI knows it all about our allies
trackerActor.party.addAll(actor.pokemonList.map { createAllied(it) })
actor.activePokemon.forEach {
val active = trackerActor.party.first { trackMon -> trackMon.id == it.battlePokemon!!.uuid }
val battlePokemon = it.battlePokemon ?: return@forEach
val active = trackerActor.party.first { trackMon -> trackMon.id == battlePokemon.uuid }
trackerActor.party.remove(active)
trackerActor.activePokemon.add(active)
}
@@ -176,7 +177,8 @@ class TrackerActor(val uuid: UUID) {
//only know basics of what we see right now
trackerActor.party.addAll(actor.pokemonList.map { createOpposing(it) })
actor.activePokemon.forEach {
val active = trackerActor.party.first { trackMon -> trackMon.id == it.battlePokemon!!.uuid }
val battlePokemon = it.battlePokemon ?: return@forEach
val active = trackerActor.party.first { trackMon -> trackMon.id == battlePokemon.uuid }
trackerActor.party.remove(active)
trackerActor.activePokemon.add(active)
}
@@ -16,24 +16,20 @@ import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList
import net.minecraft.core.component.DataComponents
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
import net.minecraft.sounds.SoundEvent
import net.minecraft.sounds.SoundSource
import net.minecraft.world.ContainerHelper
import net.minecraft.world.Containers
import net.minecraft.world.InteractionResult
import net.minecraft.world.ItemInteractionResult
import net.minecraft.world.WorldlyContainer
import net.minecraft.world.*
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.BlockHitResult
import net.minecraft.world.level.gameevent.GameEvent
import java.util.OptionalInt
import net.minecraft.world.phys.BlockHitResult
import java.util.*
import kotlin.math.pow
class DiscShelfBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(CobblemonBlockEntities.DISC_SHELF, pos, state), WorldlyContainer {
@@ -134,25 +130,7 @@ class DiscShelfBlockEntity(pos: BlockPos, state: BlockState) : BlockEntity(Cobbl
return stack.item is TechnicalMachineItem
|| stack.item == CobblemonItems.UPGRADE
|| stack.item == CobblemonItems.DUBIOUS_DISC
|| stack.item == Items.MUSIC_DISC_13
|| stack.item == Items.MUSIC_DISC_CAT
|| stack.item == Items.MUSIC_DISC_BLOCKS
|| stack.item == Items.MUSIC_DISC_CHIRP
|| stack.item == Items.MUSIC_DISC_FAR
|| stack.item == Items.MUSIC_DISC_MALL
|| stack.item == Items.MUSIC_DISC_MELLOHI
|| stack.item == Items.MUSIC_DISC_STAL
|| stack.item == Items.MUSIC_DISC_STRAD
|| stack.item == Items.MUSIC_DISC_WARD
|| stack.item == Items.MUSIC_DISC_11
|| stack.item == Items.MUSIC_DISC_WAIT
|| stack.item == Items.MUSIC_DISC_OTHERSIDE
|| stack.item == Items.MUSIC_DISC_5
|| stack.item == Items.MUSIC_DISC_RELIC
|| stack.item == Items.MUSIC_DISC_PRECIPICE
|| stack.item == Items.MUSIC_DISC_CREATOR
|| stack.item == Items.MUSIC_DISC_CREATOR_MUSIC_BOX
|| stack.item == Items.MUSIC_DISC_PIGSTEP
|| stack.has(DataComponents.JUKEBOX_PLAYABLE)
}
fun onNoteBlockPulse(level: Level, noteBlockPos: BlockPos, soundEvent: SoundEvent) {
@@ -60,10 +60,12 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
var spawningStyle: HabitatSpawningStyle = ActivatedHabitatSpawning(this)
var numberOfPhases: Int = 1
var phaseOrder = HabitatPhaseOrder.SIMPLE
var currentPhase = 1
val numberOfPhases: Int
get() = pool.getPhaseCount()
var levelRange: IntRange = 1..Cobblemon.config.maxPokemonLevel
var modifiers: PokemonProperties = PokemonProperties()
var pool: HabitatPool = HabitatPool.default()
@@ -139,7 +141,6 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
val activatedSettings = habitatSettingsDTO.activatedSettings
val naturalSettings = habitatSettingsDTO.naturalSettings
val isActivated = habitatSettingsDTO.isActivatedSpawning
this.numberOfPhases = habitatSettingsDTO.numberOfPhases
this.phaseOrder = habitatSettingsDTO.phaseOrder
this.levelRange = habitatSettingsDTO.levelRange
this.modifiers = PokemonProperties.parse(habitatSettingsDTO.modifiers)
@@ -169,7 +170,6 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
override fun saveAdditional(tag: CompoundTag, registryLookup: HolderLookup.Provider) {
super.saveAdditional(tag, registryLookup)
tag.putString(DataKeys.HABITAT_MIMIC, mimicId.toString())
tag.putInt(DataKeys.HABITAT_PHASE_COUNT, numberOfPhases)
tag.putString(DataKeys.HABITAT_PHASE_ORDER, phaseOrder.toString())
// Only save the level range when it's a non-trivial one
if (levelRange.first != 1 || levelRange.last != Cobblemon.config.maxPokemonLevel) {
@@ -201,7 +201,6 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
return // Client doesn't need to try loading the rest
}
numberOfPhases = tag.getInt(DataKeys.HABITAT_PHASE_COUNT)
phaseOrder = HabitatPhaseOrder.valueOf(tag.getString(DataKeys.HABITAT_PHASE_ORDER))
levelRange = tag.getString(DataKeys.HABITAT_LEVEL_RANGE).takeIf { it.isNotBlank() }?.let(IntRangeAdapter::deserialize) ?: 1..Cobblemon.config.maxPokemonLevel
modifiers = tag.getString(DataKeys.HABITAT_MODIFIERS).takeIf { it.isNotBlank() }?.let(PokemonProperties::parse) ?: PokemonProperties()
@@ -630,7 +630,8 @@ class FossilMultiblockStructure (
result.putInt(DataKeys.ORGANIC_MATERIAL, organicMaterialInside)
val fossilInv = ListTag()
fossilInventory.forEach { fossilInv.add(ItemStack.CODEC.encodeStart(NbtOps.INSTANCE, it).orThrow) }
val ops = registryLookup.createSerializationContext(NbtOps.INSTANCE)
fossilInventory.forEach { fossilInv.add(ItemStack.CODEC.encodeStart(ops, it).getOrThrow()) }
result.put(DataKeys.FOSSIL_INVENTORY, fossilInv)
result.putString(DataKeys.CONNECTOR_DIRECTION, tankConnectorDirection?.toString())
@@ -669,7 +670,10 @@ class FossilMultiblockStructure (
val fossilInv = if (nbt.contains(DataKeys.FOSSIL_INVENTORY)) { (nbt.get(DataKeys.FOSSIL_INVENTORY) as ListTag) } else ListTag()
val actualFossilList = mutableListOf<ItemStack>()
fossilInv.forEach { ItemStack.parse(registryLookup, it).ifPresent(actualFossilList::add) }
val ops = registryLookup.createSerializationContext(NbtOps.INSTANCE)
fossilInv.forEach { ItemStack.CODEC.parse(ops, it).result().ifPresent(actualFossilList::add) }
result.fossilInventory = actualFossilList
result.tankConnectorDirection = Direction.byName(nbt.getString(DataKeys.CONNECTOR_DIRECTION))
@@ -44,6 +44,7 @@ import com.cobblemon.mod.common.client.render.entity.PokeBobberEntityRenderer
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererRegistry
import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
import com.cobblemon.mod.common.client.render.layer.PlayerRecallBallRenderer
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
@@ -405,8 +406,10 @@ object CobblemonClient {
var renderer: LivingEntityRenderer<Player, PlayerModel<Player>>? =
skinMap?.get(PlayerSkin.Model.WIDE) as LivingEntityRenderer<Player, PlayerModel<Player>>
renderer?.addLayer(PokemonOnShoulderRenderer(renderer))
renderer?.addLayer(PlayerRecallBallRenderer(renderer))
renderer = skinMap[PlayerSkin.Model.SLIM] as LivingEntityRenderer<Player, PlayerModel<Player>>?
renderer?.addLayer(PokemonOnShoulderRenderer(renderer))
renderer?.addLayer(PlayerRecallBallRenderer(renderer))
}
private fun registerMenuScreens() {
@@ -49,7 +49,7 @@ object MountedCameraTypeHandler {
return
}
val currentCameraType = mc.options.cameraType
if (currentCameraType != unmountedCameraType) {
if (Cobblemon.config.rememberRidingCamera && currentCameraType != unmountedCameraType) {
mc.options.cameraType = unmountedCameraType
}
val data = ClientPersistedData.ridingPerspectives
@@ -32,6 +32,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.animation.ActiveAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PrimaryAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.client.render.player.RecallArmAnimationTracker
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer.Companion.ease
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
@@ -320,6 +321,13 @@ class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
ballOffset = 0f
ballRotOffset = 0f
sendOutPosition = null
// If a player is recalling, have them hold the matching Poké Ball out in their
// right hand for the duration of the beam (see ourRecallArmAnimationTracker class).
currentEntity.ownerUUID?.let { ownerId ->
if (currentEntity.level().getPlayerByUUID(ownerId) != null) {
RecallArmAnimationTracker.start(ownerId, currentEntity.exposedBall, emptySet())
}
}
afterOnClient(seconds = BEAM_EXTEND_TIME) {
activeSendoutScale = 1F
@@ -27,10 +27,18 @@ import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.world.phys.Vec3
import org.joml.Quaternionf
import org.joml.Vector3f
import kotlin.math.atan
enum class ProfileTransformType {
PROFILE,
NONE,
POKEDEX,
SUMMARY,
}
fun drawProfilePokemon(
renderablePokemon: RenderablePokemon,
matrixStack: PoseStack,
@@ -39,7 +47,7 @@ fun drawProfilePokemon(
state: PosableState,
partialTicks: Float,
scale: Float = 20F,
applyProfileTransform: Boolean = true,
profileTransformType: ProfileTransformType = ProfileTransformType.PROFILE,
applyBaseScale: Boolean = false,
r: Float = 1F,
g: Float = 1F,
@@ -56,7 +64,7 @@ fun drawProfilePokemon(
state = state.also { it.currentAspects = renderablePokemon.aspects },
partialTicks = partialTicks,
scale = scale,
applyProfileTransform = applyProfileTransform,
profileTransformType = profileTransformType,
applyBaseScale = applyBaseScale,
r = r,
g = g,
@@ -75,7 +83,7 @@ fun drawProfilePokemon(
state: PosableState,
partialTicks: Float,
scale: Float = 20F,
applyProfileTransform: Boolean = true,
profileTransformType: ProfileTransformType = ProfileTransformType.PROFILE,
applyBaseScale: Boolean = false,
doQuirks: Boolean = false,
r: Float = 1F,
@@ -114,18 +122,38 @@ fun drawProfilePokemon(
state.setPoseToFirstSuitable(poseType)
state.updatePartialTicks(partialTicks)
if (applyProfileTransform) {
matrixStack.translate(
model.profileTranslation.x,
model.profileTranslation.y + 1.5 * model.profileScale,
model.profileTranslation.z - 4.0
)
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)} else {
if (profileTransformType == ProfileTransformType.NONE) {
matrixStack.translate(0F, 0F, -4.0F)
if (applyBaseScale) {
matrixStack.scale(baseScale, baseScale, 1 / baseScale)
}
} else {
var profileScale: Float
var profileTranslation: Vec3
when (profileTransformType) {
ProfileTransformType.POKEDEX -> {
profileScale = model.profilePokedexScale ?: model.profileScale
profileTranslation = model.profilePokedexTranslation ?: model.profileTranslation
}
ProfileTransformType.SUMMARY -> {
profileScale = model.profileSummaryScale ?: model.profileScale
profileTranslation = model.profileSummaryTranslation ?: model.profileTranslation
}
else -> {
profileScale = model.profileScale
profileTranslation = model.profileTranslation
}
}
matrixStack.translate(
profileTranslation.x,
profileTranslation.y + 1.5 * profileScale,
profileTranslation.z - 4.0
)
matrixStack.scale(profileScale, profileScale, 1 / profileScale)
}
matrixStack.mulPose(rotation)
model.applyAnimations(null, state, 0F, 0F, 0F, headYaw, headPitch)
@@ -0,0 +1,97 @@
/*
* 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.gui
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.mojang.blaze3d.platform.InputConstants
import net.minecraft.client.Minecraft
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.phys.Vec3
fun handleProfileDebugKeys(keyCode: Int, poserResourceLocation: ResourceLocation, state: FloatingState) {
if (!Cobblemon.config.enableDebugKeys) {
return
}
val model = VaryingModelRepository.getPoser(poserResourceLocation, state)
val delta = when (keyCode) {
InputConstants.KEY_UP -> Vec3(0.0, -0.01, 0.0)
InputConstants.KEY_DOWN -> Vec3(0.0, 0.01, 0.0)
InputConstants.KEY_LEFT -> Vec3(-0.01, 0.0, 0.0)
InputConstants.KEY_RIGHT -> Vec3(0.01, 0.0, 0.0)
else -> null
}
if (delta != null) {
model.profileTranslation = model.profileTranslation.add(delta)
model.profileSummaryTranslation = model.profileSummaryTranslation?.add(delta)
model.profilePokedexTranslation = model.profilePokedexTranslation?.add(delta)
}
val scaleDelta = when (keyCode) {
InputConstants.KEY_EQUALS -> 0.01F
InputConstants.KEY_MINUS -> -0.01F
else -> null
}
if (scaleDelta != null) {
model.profileScale += scaleDelta
model.profileSummaryScale = model.profileSummaryScale?.plus(scaleDelta)
model.profilePokedexScale = model.profilePokedexScale?.plus(scaleDelta)
}
}
fun logProfileTranslations(poserResourceLocation: ResourceLocation, state: FloatingState) {
if (!Cobblemon.config.enableDebugKeys) {
return
}
val model = VaryingModelRepository.getPoser(poserResourceLocation, state)
val player = Minecraft.getInstance().player
fun Double.f2() = "%.2f".format(this)
fun Float.f2() = "%.2f".format(this)
fun sendTranslation(name: String, translation: Vec3) {
player?.sendSystemMessage(Component.literal("$name Translation: (${translation.x.f2()}, ${translation.y.f2()}, ${translation.z.f2()})"))
}
fun sendScale(name: String, scale: Float) {
player?.sendSystemMessage(Component.literal("$name Scale: ${scale.f2()}"))
}
fun logTranslation(name: String, translation: Vec3) {
Cobblemon.LOGGER.info("override var ${name.replaceFirstChar(Char::lowercase)}Translation = Vec3(${translation.x.f2()}, ${translation.y.f2()}, ${translation.z.f2()})")
}
fun logScale(name: String, scale: Float) {
Cobblemon.LOGGER.info("override var ${name.replaceFirstChar(Char::lowercase)}Scale = ${scale.f2()}F")
}
sendTranslation("Profile", model.profileTranslation)
sendScale("Profile", model.profileScale)
model.profileSummaryTranslation?.let { sendTranslation("Summary Profile", it) }
model.profileSummaryScale?.let { sendScale("Summary Profile", it) }
model.profilePokedexTranslation?.let { sendTranslation("Pokedex Profile", it) }
model.profilePokedexScale?.let { sendScale("Pokedex Profile", it) }
logTranslation("Profile", model.profileTranslation)
logScale("Profile", model.profileScale)
model.profileSummaryTranslation?.let { logTranslation("ProfileSummary", it) }
model.profileSummaryScale?.let { logScale("ProfileSummary", it) }
model.profilePokedexTranslation?.let { logTranslation("ProfilePokedex", it) }
model.profilePokedexScale?.let { logScale("ProfilePokedex", it) }
}
@@ -115,35 +115,19 @@ class HabitatEditGUI(
addOptionWidget(mimicInput)
y += spacing
labels.add(lang("ui.edit.habitat.phase_number") to (10 to y))
y += 12
val phasesInput = EditBox(font, 10, y, buttonWidth, 20, "Phases".text())
phasesInput.value = habitatSettingsDTO.numberOfPhases.toString()
phasesInput.setResponder { value ->
val phases = value.toIntOrNull()
val valid = phases != null && phases > 0
if (valid) {
habitatSettingsDTO.numberOfPhases = phases
}
phasesInput.setTextColor(if (valid) validTextColor else invalidTextColor)
setFieldValidity("phases", valid, "ui.edit.habitat.validation.phases")
// Phase setting only visible if there's more than one phase
val phaseCount = habitatSettingsDTO.pool.toHabitatPool()?.getPhaseCount() ?: 1
if (phaseCount > 1) {
phaseOrderButton = addOptionWidget(
Button.builder(getPhaseOrderText()) {
val orders = HabitatPhaseOrder.entries
val currentIndex = orders.indexOf(habitatSettingsDTO.phaseOrder)
habitatSettingsDTO.phaseOrder = orders[(currentIndex + 1) % orders.size]
refresh()
}.bounds(10, y, buttonWidth, 20).build()
)
y += spacing
}
val initialPhases = phasesInput.value.toIntOrNull()
val initialPhasesValid = initialPhases != null && initialPhases > 0
phasesInput.setTextColor(if (initialPhasesValid) validTextColor else invalidTextColor)
setFieldValidity("phases", initialPhasesValid, "ui.edit.habitat.validation.phases")
addOptionWidget(phasesInput)
y += spacing
phaseOrderButton = addOptionWidget(
Button.builder(getPhaseOrderText()) {
val orders = HabitatPhaseOrder.entries
val currentIndex = orders.indexOf(habitatSettingsDTO.phaseOrder)
habitatSettingsDTO.phaseOrder = orders[(currentIndex + 1) % orders.size]
refresh()
}.bounds(10, y, buttonWidth, 20).build()
)
y += spacing
labels.add(lang("ui.edit.habitat.level_range") to (10 to y))
y += 12
@@ -390,7 +374,10 @@ class HabitatEditGUI(
}
fun refresh() {
phaseOrderButton.message = getPhaseOrderText()
val phaseCount = habitatSettingsDTO.pool.toHabitatPool()?.getPhaseCount() ?: 1
if (phaseCount > 1 && ::phaseOrderButton.isInitialized) {
phaseOrderButton.message = getPhaseOrderText()
}
spawnModeButton.message = getSpawnModeText()
poolSelectorButton.message = getPoolText()
viewPoolButton.message = getViewPoolText()
@@ -439,6 +426,7 @@ class HabitatEditGUI(
}
habitatSettingsDTO.pool = newCustomPool
}
rebuildWidgets()
return
}
@@ -451,6 +439,7 @@ class HabitatEditGUI(
}
habitatSettingsDTO.pool = selectedPool
rebuildWidgets()
}
private fun validateLevelRangeInputs() {
@@ -45,7 +45,6 @@ class HabitatSpawnEditorGUI(
private val actionButtonBottomMargin = 10
private val validTextColor = 0xFFFFFF
private val invalidTextColor = 0xFF5555
private val moonPhaseRange = 0..7
private lateinit var positionTypeButton: Button
private lateinit var bucketButton: Button
private lateinit var timeOfDayButton: Button
@@ -185,7 +184,7 @@ class HabitatSpawnEditorGUI(
phasesInput.setTextColor(validTextColor)
setFieldValidity("phases_list", true, "ui.edit.habitat.validation.phases_list")
} else {
val parsed = parseMoonPhases(value)
val parsed = parsePhases(value)
val valid = parsed != null
if (valid) {
spawn.phases = parsed
@@ -194,7 +193,7 @@ class HabitatSpawnEditorGUI(
setFieldValidity("phases_list", valid, "ui.edit.habitat.validation.phases_list")
}
}
val initialPhasesValid = phasesInput.value.isBlank() || parseMoonPhases(phasesInput.value) != null
val initialPhasesValid = phasesInput.value.isBlank() || parsePhases(phasesInput.value) != null
phasesInput.setTextColor(if (initialPhasesValid) validTextColor else invalidTextColor)
setFieldValidity("phases_list", initialPhasesValid, "ui.edit.habitat.validation.phases_list")
addOptionWidget(phasesInput)
@@ -332,7 +331,7 @@ class HabitatSpawnEditorGUI(
return runCatching { PokemonSpecies.getByName(lowered) }.getOrNull()
}
private fun parseMoonPhases(raw: String): IntRanges? {
private fun parsePhases(raw: String): IntRanges? {
val ranges = mutableListOf<IntRange>()
val tokens = raw.split(",").map(String::trim)
if (tokens.isEmpty() || tokens.any { it.isEmpty() }) {
@@ -344,13 +343,12 @@ class HabitatSpawnEditorGUI(
val range = when (parts.size) {
1 -> {
val value = parts[0].toIntOrNull() ?: return null
if (value !in moonPhaseRange) return null
value..value
}
2 -> {
val start = parts[0].toIntOrNull() ?: return null
val end = parts[1].toIntOrNull() ?: return null
if (start !in moonPhaseRange || end !in moonPhaseRange || start > end) {
if (start > end) {
return null
}
start..end
@@ -32,6 +32,8 @@ import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
import com.cobblemon.mod.common.client.gui.handleProfileDebugKeys
import com.cobblemon.mod.common.client.gui.logProfileTranslations
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_HEIGHT
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_WIDTH
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
@@ -427,6 +429,11 @@ class PokedexGUI private constructor(
override fun onClose() {
if (blockPos != null) AdjustBlockEntityViewerCountPacket(blockPos, false).sendToServer()
playSound(CobblemonSounds.POKEDEX_CLOSE)
selectedEntry?.speciesId?.let { speciesId ->
logProfileTranslations(speciesId, pokemonInfoWidget.state)
}
super.onClose()
}
@@ -757,6 +764,12 @@ class PokedexGUI private constructor(
return true
}
if (!searchWidget.isFocused) {
selectedEntry?.speciesId?.let { speciesId ->
handleProfileDebugKeys(keyCode, speciesId, pokemonInfoWidget.state)
}
}
return super.keyPressed(keyCode, scanCode, modifiers)
}
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.api.types.ElementalType
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.ProfileTransformType
import com.cobblemon.mod.common.client.gui.TypeIcon
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
@@ -386,7 +387,8 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
partialTicks = delta,
rotation = Quaternionf().fromEulerXYZDegrees(rotationVector),
state = state,
blockLight = 15
blockLight = 15,
profileTransformType = ProfileTransformType.POKEDEX,
)
matrices.popPose()
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pokedex.widgets
import com.cobblemon.mod.common.api.gui.blitk
import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.ProfileTransformType
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_DESCRIPTION_HEIGHT
@@ -90,7 +91,7 @@ class SizeWidget(val pX: Int, val pY: Int) : SoundlessWidget(
rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(0F, 0F, 0F)),
state = FloatingState(),
scale = modelScale,
applyProfileTransform = false,
profileTransformType = ProfileTransformType.NONE,
applyBaseScale = true,
r = 0F,
g = 0F,
@@ -8,7 +8,6 @@
package com.cobblemon.mod.common.client.gui.summary
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.CobblemonItems
import com.cobblemon.mod.common.CobblemonNetwork.sendToServer
import com.cobblemon.mod.common.CobblemonSounds
@@ -21,14 +20,8 @@ import com.cobblemon.mod.common.api.text.bold
import com.cobblemon.mod.common.api.text.text
import com.cobblemon.mod.common.client.CobblemonClient
import com.cobblemon.mod.common.client.CobblemonResources
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
import com.cobblemon.mod.common.client.gui.ExitButton
import com.cobblemon.mod.common.client.gui.TypeIcon
import com.cobblemon.mod.common.client.gui.summary.widgets.EvolutionSelectScreen
import com.cobblemon.mod.common.client.gui.summary.widgets.MarkingsWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.ModelWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.NicknameEntryWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.PartyWidget
import com.cobblemon.mod.common.client.gui.*
import com.cobblemon.mod.common.client.gui.summary.widgets.*
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.SummaryTab
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.info.InfoWidget
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.marks.MarksWidget
@@ -37,7 +30,6 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MovesWi
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.StatWidget
import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
import com.cobblemon.mod.common.client.render.drawScaledText
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
@@ -715,27 +707,9 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
) {
this.focused = null
}
if (Cobblemon.config.enableDebugKeys) {
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
if (keyCode == InputConstants.KEY_UP) {
model.profileTranslation = model.profileTranslation.add(0.0, -0.01, 0.0)
}
if (keyCode == InputConstants.KEY_DOWN) {
model.profileTranslation = model.profileTranslation.add(0.0, 0.01, 0.0)
}
if (keyCode == InputConstants.KEY_LEFT) {
model.profileTranslation = model.profileTranslation.add(-0.01, 0.0, 0.0)
}
if (keyCode == InputConstants.KEY_RIGHT) {
model.profileTranslation = model.profileTranslation.add(0.01, 0.0, 0.0)
}
if (keyCode == InputConstants.KEY_EQUALS) {
model.profileScale += 0.01F
}
if (keyCode == InputConstants.KEY_MINUS) {
model.profileScale -= 0.01F
}
}
handleProfileDebugKeys(keyCode, selectedPokemon.species.resourceIdentifier, modelWidget.state)
return super.keyPressed(keyCode, scanCode, modifiers)
}
@@ -744,13 +718,8 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
}
override fun onClose() {
if (Cobblemon.config.enableDebugKeys) {
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Translation: ${model.profileTranslation}"))
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Scale: ${model.profileScale}"))
Cobblemon.LOGGER.info("override var profileTranslation = Vec3d(${model.profileTranslation.x}, ${model.profileTranslation.y}, ${model.profileTranslation.z})")
Cobblemon.LOGGER.info("override var profileScale = ${model.profileScale}F")
}
logProfileTranslations(selectedPokemon.species.resourceIdentifier, modelWidget.state)
super.onClose()
}
}
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets
import com.bedrockk.molang.runtime.value.DoubleValue
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
import com.cobblemon.mod.common.client.gui.ProfileTransformType
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
import com.cobblemon.mod.common.client.gui.calculateHeadYawAndPitch
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
@@ -116,7 +117,8 @@ class ModelWidget(
partialTicks = partialTicks,
headYaw = currentYawAndPitch.first,
headPitch = currentYawAndPitch.second,
blockLight = blockLight
blockLight = blockLight,
profileTransformType = ProfileTransformType.SUMMARY,
)
heldItemRenderer.renderOnModel(
@@ -22,6 +22,8 @@ object ServerSettingsPacketHandler : ClientNetworkPacketHandler<ServerSettingsPa
ServerSettings.maxPokemonFriendship = packet.maxPokemonFriendship
ServerSettings.maxDynamaxLevel = packet.maxDynamaxLevel
ServerSettings.unlockAllMoveDexMovesByDefault = packet.unlockAllMoveDexMovesByDefault
ServerSettings.pokemonIntrinsicSizeMin = packet.pokemonIntrinsicSizeMin
ServerSettings.pokemonIntrinsicSizeMax = packet.pokemonIntrinsicSizeMax
}
}
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.util.cobblemonResource
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexConsumer
import com.mojang.math.Axis
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.LevelRenderer
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderType
@@ -39,13 +40,13 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
private val leftMargin = 1f
private val rightMargin = 1f
private val topMargin = 1f
private val bottomMargin = 1f
private val interRowSpacing = 0f
private val tmOverlayDepthOffset = -0.0002f
private val slotBrightnessMultiplier = 0.65f
private val tmBaseTexture = cobblemonResource("textures/block/disc_shelf/technical_machine_base.png")
private val tmOverlayTexture = cobblemonResource("textures/block/disc_shelf/technical_machine_overlay.png")
private val musicDiscUnknownTexture = cobblemonResource("textures/block/disc_shelf/music_disc_unknown.png")
override fun render(
entity: DiscShelfBlockEntity,
@@ -77,7 +78,6 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
val slotWidth = slotWidthPixels / textureSize
val slotHeight = slotHeightPixels / textureSize
val verticalSpacing = (slotHeightPixels + interRowSpacing) / textureSize
val totalHeight = slotHeight * 7 + interRowSpacing * 6 / textureSize
val startY = topMargin / textureSize
for ((index, item) in entity.items.withIndex()) {
@@ -188,6 +188,13 @@ class DiscShelfBlockEntityRenderer(ctx: BlockEntityRendererProvider.Context) :
private fun getItemTexture(itemStack: ItemStack): ResourceLocation {
val id = BuiltInRegistries.ITEM.getKey(itemStack.item)
return cobblemonResource("textures/block/disc_shelf/${id.path}.png")
val resource = cobblemonResource("textures/block/disc_shelf/${id.path}.png")
val resourceManager = Minecraft.getInstance().resourceManager
if (resourceManager.getResource(resource).isEmpty) {
return musicDiscUnknownTexture
}
return resource
}
}
@@ -0,0 +1,127 @@
/*
* 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.layer
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.client.render.player.RecallArmAnimationTracker
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.Minecraft
import net.minecraft.client.model.PlayerModel
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.entity.ItemRenderer
import net.minecraft.client.renderer.entity.RenderLayerParent
import net.minecraft.client.renderer.entity.layers.RenderLayer
import net.minecraft.client.renderer.texture.OverlayTexture
import net.minecraft.world.entity.HumanoidArm
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec3
import org.joml.Vector3f
/**
* Draws the matching Poké Ball in a recalling player's right hand and records where the recall beam
* should start. Driven by [RecallArmAnimationTracker]; the right arm is posed forward in
* HumanoidModelMixin so [PlayerModel.translateToHand] lands on the extended hand.
*
* The local player in first person is handled by FirstPersonRecallBallRenderer instead, so it's
* skipped here.
*/
class PlayerRecallBallRenderer<T : Player>(
renderLayerParent: RenderLayerParent<T, PlayerModel<T>>
) : RenderLayer<T, PlayerModel<T>>(renderLayerParent) {
companion object {
private const val BALL_SCALE = 0.5F
private const val HAND_X = 0.0625
private const val HAND_Y = 0.125
private const val HAND_Z = -0.625
private const val BALL_YAW_SPIN = 180F
private const val BALL_INFLATE = 1.08F
private const val BEAM_X_OFFSET = 0F
private const val BEAM_Y_OFFSET = 0.18F
private const val BEAM_Z_OFFSET = -0.30F
}
private val ballContext = RenderContext().also {
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.WORLD)
}
override fun render(
matrixStack: PoseStack,
buffer: MultiBufferSource,
packedLight: Int,
player: T,
limbSwing: Float,
limbSwingAmount: Float,
partialTicks: Float,
ageInTicks: Float,
netHeadYaw: Float,
headPitch: Float
) {
val anim = RecallArmAnimationTracker.get(player.uuid) ?: return
val mc = Minecraft.getInstance()
if (player === mc.player && mc.options.cameraType.isFirstPerson) return
matrixStack.pushPose()
getParentModel().translateToHand(HumanoidArm.RIGHT, matrixStack)
matrixStack.mulPose(Axis.XP.rotationDegrees(-90F))
matrixStack.mulPose(Axis.YP.rotationDegrees(180F))
matrixStack.translate(HAND_X, HAND_Y, HAND_Z)
renderBall(anim, matrixStack, buffer, packedLight, partialTicks)
matrixStack.popPose()
}
private fun renderBall(
anim: RecallArmAnimationTracker.RecallAnim,
matrixStack: PoseStack,
buffer: MultiBufferSource,
packedLight: Int,
partialTicks: Float
) {
val state = anim.ballState
val ball = anim.ball
matrixStack.pushPose()
matrixStack.scale(BALL_INFLATE, BALL_INFLATE, BALL_INFLATE)
matrixStack.translate(0.0, (-8.0 / 16.0) * BALL_SCALE, 0.0)
matrixStack.scale(BALL_SCALE, -BALL_SCALE, -BALL_SCALE)
matrixStack.mulPose(Axis.YP.rotationDegrees(BALL_YAW_SPIN))
val model = VaryingModelRepository.getPoser(ball.name, state)
val texture = VaryingModelRepository.getTexture(ball.name, state)
state.updatePartialTicks(partialTicks)
model.context = ballContext
ballContext.put(RenderContext.ASPECTS, state.aspects)
ballContext.put(RenderContext.POSABLE_STATE, state)
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
state.locatorStates["beam"]?.let { beamLocator ->
matrixStack.pushPose()
matrixStack.mulPose(beamLocator.matrix)
val camRelative = matrixStack.last().pose().transformPosition(Vector3f(BEAM_X_OFFSET, BEAM_Y_OFFSET, BEAM_Z_OFFSET))
matrixStack.popPose()
val camera = Minecraft.getInstance().gameRenderer.mainCamera.position
anim.beamOrigin = Vec3(camera.x + camRelative.x, camera.y + camRelative.y, camera.z + camRelative.z)
}
val consumer = ItemRenderer.getFoilBufferDirect(buffer, RenderType.entityCutout(texture), false, false)
model.render(ballContext, matrixStack, consumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
model.red = 1F
model.green = 1F
model.blue = 1F
model.resetLayerContext()
matrixStack.popPose()
}
}
@@ -134,6 +134,11 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
*/
open var profileTranslation = Vec3(0.0, 0.0, 0.0)
open var profilePokedexScale: Float? = null
open var profilePokedexTranslation: Vec3? = null
open var profileSummaryScale: Float? = null
open var profileSummaryTranslation: Vec3? = null
var red = 1F
var green = 1F
var blue = 1F
@@ -1,121 +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.gen1
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WaveAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WaveSegment
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.client.render.models.blockbench.wavefunction.sineFunction
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class ArbokModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("arbok")
override val head = getPart("head_ai")
override var portraitScale = 1.5F
override var portraitTranslation = Vec3(-0.4, 1.0, 0.0)
override var profileScale = 0.67F
override var profileTranslation = Vec3(0.0, 0.7, 0.0)
lateinit var sleep: Pose
lateinit var standing: Pose
lateinit var walk: Pose
lateinit var summary: Pose
val tail = getPart("tail")
val tail2 = getPart("tail2")
val tail3 = getPart("tail3")
val tail4 = getPart("tail4")
val tail5 = getPart("tail5")
val tailWaveSegment = WaveSegment(modelPart = tail, length = 11F)
val tail2WaveSegment = WaveSegment(modelPart = tail2, length = 11F)
val tail3WaveSegment = WaveSegment(modelPart = tail3, length = 11F)
val tail4WaveSegment = WaveSegment(modelPart = tail4, length = 11F)
val tail5WaveSegment = WaveSegment(modelPart = tail5, length = 11F)
override val cryAnimation = CryProvider { bedrockStateful("arbok", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("arbok", "blink") }
// TODO tongue_flick
val wave = WaveAnimation(
waveFunction = sineFunction(
period = 10F,
amplitude = 0.5F
),
basedOnLimbSwing = true,
oscillationsScalar = 8F,
head = tail,
rotationAxis = ModelPartTransformation.Y_AXIS,
motionAxis = ModelPartTransformation.X_AXIS,
headLength = 0.1F,
segments = arrayOf(
tailWaveSegment,
tail2WaveSegment,
tail3WaveSegment,
tail4WaveSegment,
tail5WaveSegment
)
)
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("arbok", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("arbok", "summary_idle"),
wave
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("arbok", "ground_walk"),
wave
)
)
summary = registerPose(
poseName = "summary",
poseTypes = UI_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("arbok", "summary_idle")
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("arbok", "faint") else null
}
@@ -1,74 +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.gen1
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
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.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class DittoModel(root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("ditto")
override var portraitScale = 3.2F
override var portraitTranslation = Vec3(0.0, -2.2, 0.0)
override var profileScale = 1.4F
override var profileTranslation = Vec3(0.0, -0.34, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
lateinit var sleep: Pose
override val cryAnimation = CryProvider { bedrockStateful("ditto", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("ditto", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
// singleBoneLook()
bedrock("ditto", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
// singleBoneLook()
bedrock("ditto", "ground_walk")
)
)
sleep = registerPose(
poseName = "sleep",
poseType = PoseType.SLEEP,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
// singleBoneLook()
bedrock("ditto", "sleep")
)
)
}
override fun getFaintAnimation(state: PosableState) = bedrockStateful("ditto", "faint")
}
@@ -1,103 +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.gen1
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.CobblemonPose
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 OmanyteModel(root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("omanyte")
override var portraitScale = 3.15F
override var portraitTranslation = Vec3(-0.06, -3.18, 0.0)
override var profileScale = 1.13F
override var profileTranslation = Vec3(0.0, -0.02, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var float: CobblemonPose
lateinit var swim: CobblemonPose
lateinit var sleep: CobblemonPose
lateinit var battleidle: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("omanyte", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("omanyte", "blink") }
sleep = registerPose(
poseName = "sleep",
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("omanyte", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STANDING_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink),
transformTicks = 10,
condition = { !it.isBattling},
animations = arrayOf(
bedrock("omanyte", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES - PoseType.SWIM,
quirks = arrayOf(blink),
transformTicks = 10,
animations = arrayOf(
bedrock("omanyte", "ground_walk")
)
)
float = registerPose(
poseName = "float",
poseTypes = setOf(PoseType.FLOAT, PoseType.HOVER),
quirks = arrayOf(blink),
transformTicks = 10,
animations = arrayOf(
bedrock("omanyte", "water_idle")
)
)
swim = registerPose(
poseName = "swim",
poseTypes = setOf(PoseType.SWIM, PoseType.FLY),
quirks = arrayOf(blink),
transformTicks = 10,
animations = arrayOf(
bedrock("omanyte", "water_swim")
)
)
battleidle = registerPose(
poseName = "battle-standing",
poseTypes = PoseType.STATIONARY_POSES,
quirks = arrayOf(blink),
transformTicks = 10,
condition = { it.isBattling},
animations = arrayOf(
bedrock("omanyte", "battle_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("omanyte", "faint") else null
}
@@ -1,102 +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.gen1
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.CobblemonPose
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 OmastarModel(root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("omastar")
override var portraitTranslation = Vec3(0.02, -2.20, 0.0)
override var portraitScale = 2.4F
override var profileTranslation = Vec3(0.0, 0.066, 0.0)
override var profileScale = 1.1F
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var float: CobblemonPose
lateinit var swim: CobblemonPose
lateinit var sleep: CobblemonPose
lateinit var battleidle: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("omastar", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("omastar", "blink") }
sleep = registerPose(
poseName = "sleep",
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("omastar", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STANDING_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink),
transformTicks = 10,
condition = { !it.isBattling},
animations = arrayOf(
bedrock("omastar", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES - PoseType.SWIM,
quirks = arrayOf(blink),
transformTicks = 10,
animations = arrayOf(
bedrock("omastar", "ground_walk")
)
)
float = registerPose(
poseName = "float",
poseTypes = setOf(PoseType.FLOAT, PoseType.HOVER),
quirks = arrayOf(blink),
transformTicks = 10,
animations = arrayOf(
bedrock("omastar", "water_idle")
)
)
swim = registerPose(
poseName = "swim",
poseTypes = setOf(PoseType.SWIM, PoseType.FLY),
quirks = arrayOf(blink),
transformTicks = 10,
animations = arrayOf(
bedrock("omastar", "water_swim")
)
)
battleidle = registerPose(
poseName = "battle-standing",
poseTypes = PoseType.STATIONARY_POSES,
quirks = arrayOf(blink),
transformTicks = 10,
condition = { it.isBattling},
animations = arrayOf(
bedrock("omastar", "battle_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("omastar", "faint") else null
}
@@ -1,155 +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.gen2
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.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 com.cobblemon.mod.common.util.isUnderWater
import com.cobblemon.mod.common.util.isInWater
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class FeraligatrModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame {
override val rootPart = root.registerChildWithAllChildren("feraligatr")
override val head = getPart("head_ai")
override val leftLeg = getPart("leg_left")
override val rightLeg = getPart("leg_right")
override var portraitScale = 1.3F
override var portraitTranslation = Vec3(-0.7, 1.1, 0.0)
override var profileScale = 0.6F
override var profileTranslation = Vec3(0.0, 0.8, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
lateinit var floating: Pose
lateinit var swimming: Pose
lateinit var sleep: Pose
lateinit var watersleep: Pose
lateinit var battleidle: Pose
lateinit var water_surface_idle: Pose
lateinit var water_surface_swim: Pose
val wateroffset = -10
override val cryAnimation = CryProvider { bedrockStateful("feraligatr", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("feraligatr", "blink")}
sleep = registerPose(
poseName = "sleeping",
poseType = PoseType.SLEEP,
condition = { !it.isInWater },
animations = arrayOf(bedrock("feraligatr", "sleep"))
)
watersleep = registerPose(
poseName = "water_sleeping",
poseType = PoseType.SLEEP,
condition = { it.isInWater },
animations = arrayOf(bedrock("feraligatr", "water_sleep"))
)
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.UI_POSES + PoseType.STAND,
transformTicks = 10,
condition = { !it.isBattling && !it.isInWater && !it.isUnderWater },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("feraligatr", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
transformTicks = 10,
poseType = PoseType.WALK,
condition = { !it.isInWater && !it.isUnderWater },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("feraligatr", "ground_walk")
)
)
floating = registerPose(
poseName = "floating",
transformTicks = 10,
poseType = PoseType.FLOAT,
condition = { it.isUnderWater },
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("feraligatr", "water_idle")
)
)
swimming = registerPose(
poseName = "swimming",
transformTicks = 10,
condition = { it.isUnderWater },
poseType = PoseType.SWIM,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("feraligatr", "water_swim"),
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling && !it.isInWater },
animations = arrayOf(
singleBoneLook(),
bedrock("feraligatr", "battle_idle")
)
)
water_surface_idle = registerPose(
poseName = "surface_idle",
poseTypes = PoseType.STATIONARY_POSES,
quirks = arrayOf(blink),
condition = { !it.isUnderWater && it.isInWater },
animations = arrayOf(
singleBoneLook(),
bedrock("feraligatr", "watersurface_idle"),
),
transformedParts = arrayOf(rootPart.createTransformation().addPosition(ModelPartTransformation.Y_AXIS, wateroffset))
)
water_surface_swim = registerPose(
poseName = "surface_swim",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
condition = { !it.isUnderWater && it.isInWater },
animations = arrayOf(
singleBoneLook(),
bedrock("feraligatr", "watersurface_swim"),
),
transformedParts = arrayOf(rootPart.createTransformation().addPosition(ModelPartTransformation.Y_AXIS, wateroffset))
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, battleidle, sleep)) bedrockStateful("feraligatr", "faint") else if (state.isPosedIn(water_surface_idle, water_surface_swim, watersleep )) bedrockStateful("feraligatr", "faint") else null
}
@@ -1,91 +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.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
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.entity.PoseType.Companion.MOVING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class SmoochumModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("smoochum")
override val head = getPart("head")
override var portraitScale = 2.3F
override var portraitTranslation = Vec3(-0.14, -1.0, 0.0)
override var profileScale = 0.8F
override var profileTranslation = Vec3(0.0, 0.55, 0.0)
lateinit var standing: Pose
lateinit var walk: Pose
lateinit var shoulderLeft: Pose
lateinit var shoulderRight: Pose
val shoulderOffset = 1
override fun registerPoses() {
// val blink = quirk { bedrockStateful("smoochum", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = STATIONARY_POSES + UI_POSES,
// quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("smoochum", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = MOVING_POSES,
// quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("smoochum", "ground_idle")
)
)
shoulderLeft = registerPose(
poseType = PoseType.SHOULDER_LEFT,
//quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("smoochum", "ground_idle")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, shoulderOffset)
)
)
shoulderRight = registerPose(
poseType = PoseType.SHOULDER_RIGHT,
//quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("smoochum", "ground_idle")
),
transformedParts = arrayOf(
rootPart.createTransformation().addPosition(ModelPartTransformation.X_AXIS, -shoulderOffset)
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("smoochum", "faint") else null
}
@@ -19,7 +19,7 @@ import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class TyphlosionHisuianModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("typhlosion_hisui")
override val rootPart = root.registerChildWithAllChildren("typhlosion")
override val head = getPart("head")
override var portraitScale = 1.4F
@@ -1,67 +0,0 @@
/*
* Copyright (C) 2023 Cobblemon Contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen2
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
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.CobblemonPose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class TyranitarModel(root: ModelPart) : PokemonPosableModel(root), BipedFrame, BimanualFrame, HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("tyranitar")
override val head = getPart("head")
override val leftArm = getPart("arm_left")
override val rightArm = getPart("arm_right")
override val leftLeg = getPart("leg_left")
override val rightLeg = getPart("leg_right")
override var portraitScale = 1.21F
override var portraitTranslation = Vec3(-0.43, 3.73, 0.0)
override var profileScale = 0.33F
override var profileTranslation = Vec3(0.02, 1.31, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
override val cryAnimation = CryProvider { bedrockStateful("tyranitar", "cry") }
override fun registerPoses() {
val blink = quirk { bedrockStateful("tyranitar", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(pitchMultiplier = 0.2F, yawMultiplier = 0.4F),
bedrock("tyranitar", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(pitchMultiplier = 0.2F, yawMultiplier = 0.4F),
bedrock("tyranitar", "ground_idle"),
BipedWalkAnimation(this, periodMultiplier = 0.6F, amplitudeMultiplier = 0.9F),
BimanualSwingAnimation(this, swingPeriodMultiplier = 0.6F, amplitudeMultiplier = 0.9F)
)
)
}
}
@@ -23,7 +23,7 @@ import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class WooperPaldeanModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
override val rootPart = root.registerChildWithAllChildren("wooper_paldean")
override val rootPart = root.registerChildWithAllChildren("wooper")
override val head = getPart("head")
override var portraitScale = 2.0F
@@ -1,78 +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.gen3
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
import com.cobblemon.mod.common.entity.PoseType
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class LuvdiscModel (root: ModelPart) : PokemonPosableModel(root) {
override val rootPart = root.registerChildWithAllChildren("luvdisc")
override var portraitScale = 6.0F
override var portraitTranslation = Vec3(0.15, -6.5, 0.0)
override var profileScale = 2.0F
override var profileTranslation = Vec3(0.0, -1.3, 0.0)
lateinit var standing: Pose
lateinit var sleep: Pose
lateinit var walk: Pose
lateinit var float: Pose
lateinit var swim: Pose
override fun registerPoses() {
val blink = quirk { bedrockStateful("luvdisc", "blink")}
sleep = registerPose(
poseType = PoseType.SLEEP,
animations = arrayOf(bedrock("luvdisc", "sleep"))
)
standing = registerPose(
poseName = "standing",
poseType = PoseType.STAND,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("luvdisc", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseType = PoseType.WALK,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("luvdisc", "ground_walk")
)
)
float = registerPose(
poseName = "float",
poseTypes = PoseType.UI_POSES + PoseType.FLOAT,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("luvdisc", "water_idle")
)
)
swim = registerPose(
poseName = "swim",
poseType = PoseType.SWIM,
quirks = arrayOf(blink),
animations = arrayOf(
bedrock("luvdisc", "water_swim")
)
)
}
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("luvdisc", "ground_faint") else null
}
@@ -1,170 +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.gen4
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.frame.BiWingedFrame
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.client.render.models.blockbench.wavefunction.parabolaFunction
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.sineFunction
import com.cobblemon.mod.common.entity.PoseType
import com.cobblemon.mod.common.entity.PoseType.Companion.FLYING_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.SHOULDER_POSES
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
import com.cobblemon.mod.common.util.math.geometry.toRadians
import net.minecraft.client.model.geom.ModelPart
import net.minecraft.world.phys.Vec3
class ChatotModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BiWingedFrame{
override val rootPart = root.registerChildWithAllChildren("chatot")
override val leftWing = getPart("wing_left")
override val rightWing = getPart("wing_right")
override val leftLeg = getPart("leg_left")
override val rightLeg = getPart("leg_right")
override val head = getPart("head")
private val tail = getPart("tail")
override var portraitScale = 3.5F
override var portraitTranslation = Vec3(-0.1, -2.1, 0.0)
override var profileScale = 1.2F
override var profileTranslation = Vec3(0.0, -0.01, 0.0)
lateinit var sleep: Pose
lateinit var stand: Pose
lateinit var walk: Pose
lateinit var fly: Pose
override val cryAnimation = CryProvider { bedrockStateful("chatot", "cry") }
override fun registerPoses() {
// no sleep anim yet
// sleep = registerPose(
// poseType = PoseType.SLEEP,
// animations = arrayOf(bedrock("chatot", "sleep"))
// )
val blink = quirk { bedrockStateful("chatot", "blink") }
stand = registerPose(
poseName = "standing",
poseTypes = SHOULDER_POSES + UI_POSES + PoseType.STAND,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("chatot", "ground_idle")
)
)
fly = registerPose(
poseName = "hover",
poseTypes = FLYING_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("chatot", "air_idle"),
WingFlapIdleAnimation(this,
flapFunction = sineFunction(verticalShift = -10F.toRadians(), period = 0.9F, amplitude = 0.6F),
timeVariable = { state, _, _ -> state.animationSeconds },
axis = ModelPartTransformation.Z_AXIS
)
)
)
walk = registerPose(
poseName = "walking",
poseType = PoseType.WALK,
transformTicks = 10,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("chatot", "ground_idle"),
rootPart.translation(
function = parabolaFunction(
peak = -4F,
period = 0.4F
),
timeVariable = { state, _, _ -> state.animationSeconds },
axis = ModelPartTransformation.Y_AXIS
),
head.translation(
function = sineFunction(
amplitude = (-20F).toRadians(),
period = 1F,
verticalShift = (-10F).toRadians()
),
axis = ModelPartTransformation.X_AXIS,
timeVariable = { state, _, _ -> state.animationSeconds }
),
leftLeg.rotation(
function = parabolaFunction(
tightness = -20F,
phaseShift = 0F,
verticalShift = (30F).toRadians()
),
axis = ModelPartTransformation.X_AXIS,
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
),
rightLeg.rotation(
function = parabolaFunction(
tightness = -20F,
phaseShift = 0F,
verticalShift = (30F).toRadians()
),
axis = ModelPartTransformation.X_AXIS,
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
),
tail.rotation(
function = sineFunction(
amplitude = (-5F).toRadians(),
period = 1F
),
axis = ModelPartTransformation.X_AXIS,
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
),
wingFlap(
flapFunction = sineFunction(
amplitude = (-5F).toRadians(),
period = 0.4F,
phaseShift = 0.00F,
verticalShift = (-20F).toRadians()
),
timeVariable = { state, _, _ -> state.animationSeconds },
axis = ModelPartTransformation.Z_AXIS
),
rightWing.translation(
function = parabolaFunction(
tightness = -10F,
phaseShift = 30F,
verticalShift = (25F).toRadians()
),
axis = ModelPartTransformation.Y_AXIS,
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
),
leftWing.translation(
function = parabolaFunction(
tightness = -10F,
phaseShift = 30F,
verticalShift = (25F).toRadians()
),
axis = ModelPartTransformation.Y_AXIS,
timeVariable = { _, _, ageInTicks -> ageInTicks / 20 },
),
)
)
}
}
@@ -1,86 +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.gen7
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BimanualSwingAnimation
import com.cobblemon.mod.common.client.render.models.blockbench.animation.BipedWalkAnimation
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.PokemonPosableModel
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
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 TurtonatorModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BimanualFrame {
override val rootPart = root.registerChildWithAllChildren("turtonator")
override val head = getPart("head")
override val leftArm = getPart("arm_left")
override val rightArm = getPart("arm_right")
override val leftLeg = getPart("leg_left")
override val rightLeg = getPart("leg_right")
override var portraitScale = 1.62F
override var portraitTranslation = Vec3(-1.14, 1.92, 0.0)
override var profileScale = 0.54F
override var profileTranslation = Vec3(-0.08, 0.87, 0.0)
lateinit var standing: CobblemonPose
lateinit var walk: CobblemonPose
lateinit var battleidle: CobblemonPose
override fun registerPoses() {
val blink = quirk { bedrockStateful("turtonator", "blink") }
standing = registerPose(
poseName = "standing",
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
quirks = arrayOf(blink),
condition = { !it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("turtonator", "ground_idle")
)
)
walk = registerPose(
poseName = "walk",
poseTypes = PoseType.MOVING_POSES,
quirks = arrayOf(blink),
animations = arrayOf(
singleBoneLook(),
bedrock("turtonator", "ground_idle"),
BipedWalkAnimation(this, periodMultiplier = 0.6F, amplitudeMultiplier = 0.9F),
BimanualSwingAnimation(this, swingPeriodMultiplier = 0.6F, amplitudeMultiplier = 0.9F)
//bedrock("turtonator", "ground_walk")
)
)
battleidle = registerPose(
poseName = "battle_idle",
poseTypes = PoseType.STATIONARY_POSES,
transformTicks = 10,
quirks = arrayOf(blink),
condition = { it.isBattling },
animations = arrayOf(
singleBoneLook(),
bedrock("turtonator", "battle_idle")
)
)
}
// override fun getFaintAnimation(
// pokemonEntity: PokemonEntity,
// state: PosableState<PokemonEntity>
// ) = if (state.isPosedIn(standing, walk)) bedrockStateful("turtonator", "faint") else null
}
@@ -248,10 +248,8 @@ object VaryingModelRepository {
inbuilt("machop", ::MachopModel)
inbuilt("machoke", ::MachokeModel)
inbuilt("machamp", ::MachampModel)
inbuilt("arbok", ::ArbokModel)
inbuilt("chansey", ::ChanseyModel)
inbuilt("cubone", ::CuboneModel)
inbuilt("ditto", ::DittoModel)
inbuilt("dodrio", ::DodrioModel)
inbuilt("doduo", ::DoduoModel)
inbuilt("electabuzz", ::ElectabuzzModel)
@@ -278,8 +276,6 @@ object VaryingModelRepository {
inbuilt("nidoranm", ::NidoranmModel)
inbuilt("nidorina", ::NidorinaModel)
inbuilt("nidorino", ::NidorinoModel)
inbuilt("omanyte", ::OmanyteModel)
inbuilt("omastar", ::OmastarModel)
inbuilt("persian", ::PersianModel)
inbuilt("pinsir", ::PinsirModel)
inbuilt("poliwag", ::PoliwagModel)
@@ -293,7 +289,6 @@ object VaryingModelRepository {
inbuilt("venomoth", ::VenomothModel)
inbuilt("venonat", ::VenonatModel)
inbuilt("elekid", ::ElekidModel)
inbuilt("smoochum", ::SmoochumModel)
inbuilt("hitmontop", ::HitmontopModel)
inbuilt("electivire", ::ElectivireModel)
inbuilt("tangrowth", ::TangrowthModel)
@@ -355,7 +350,6 @@ object VaryingModelRepository {
inbuilt("whismur", :: WhismurModel)
inbuilt("loudred", :: LoudredModel)
inbuilt("exploud", :: ExploudModel)
inbuilt("luvdisc", :: LuvdiscModel)
inbuilt("cryogonal", :: CryogonalModel)
inbuilt("pumpkaboo", :: PumpkabooModel)
inbuilt("gourgeist", :: GourgeistModel)
@@ -397,7 +391,6 @@ object VaryingModelRepository {
inbuilt("tandemaus", ::TandemausModel)
inbuilt("fidough", ::FidoughModel)
inbuilt("dachsbun", ::DachsbunModel)
inbuilt("chatot", ::ChatotModel)
inbuilt("gligar", ::GligarModel)
inbuilt("gliscor", ::GliscorModel)
inbuilt("poochyena", ::PoochyenaModel)
@@ -487,7 +480,6 @@ object VaryingModelRepository {
inbuilt("phantump", ::PhantumpModel)
inbuilt("totodile", ::TotodileModel)
inbuilt("croconaw", ::CroconawModel)
inbuilt("feraligatr", ::FeraligatrModel)
inbuilt("cyndaquil", ::CyndaquilModel)
inbuilt("quilava", ::QuilavaModel)
inbuilt("typhlosion", ::TyphlosionModel)
@@ -544,7 +536,6 @@ object VaryingModelRepository {
inbuilt("petilil_hisui_bias", ::PetililHisuiBiasModel)
inbuilt("lilligant_hisuian", ::LilligantHisuianModel)
inbuilt("darumaka", ::DarumakaModel)
inbuilt("turtonator", ::TurtonatorModel)
inbuilt("cufant", ::CufantModel)
inbuilt("copperajah", ::CopperajahModel)
inbuilt("budew", ::BudewModel)
@@ -574,7 +565,6 @@ object VaryingModelRepository {
inbuilt("vibrava", ::VibravaModel)
inbuilt("larvitar", ::LarvitarModel)
inbuilt("pupitar", ::PupitarModel)
inbuilt("tyranitar", ::TyranitarModel)
inbuilt("impidimp", ::ImpidimpModel)
inbuilt("morgrem", ::MorgremModel)
inbuilt("grimmsnarl", ::GrimmsnarlModel)
@@ -0,0 +1,76 @@
/*
* 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.player
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.math.Axis
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.MultiBufferSource
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.entity.ItemRenderer
import net.minecraft.client.renderer.texture.OverlayTexture
/**
* Draws the recalling player's Poké Ball in first person, rising into view from the bottom of the
* screen in place of their held item. The world-space beam still starts near the hand (the eye/look
* fallback in PokemonRenderer), so this is cosmetic only.
*
* Called from ItemInHandRendererMixin, which cancels the vanilla main-hand item while recalling.
*/
object FirstPersonRecallBallRenderer {
/** Resting position of the ball in view space (right, up, forward). */
private const val REST_X = 0.45
private const val REST_Y = -0.55
private const val REST_Z = -.6
/** How far below REST_Y the ball starts before rising into view. */
private const val RISE_DISTANCE = 0.6
private const val BALL_SCALE = 0.45F
private val ballContext = RenderContext().also {
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.WORLD)
}
/**
* @return true if a recall ball was rendered (so the caller should cancel the vanilla item).
*/
fun render(poseStack: PoseStack, buffer: MultiBufferSource, packedLight: Int, partialTicks: Float): Boolean {
val player = Minecraft.getInstance().player ?: return false
val anim = RecallArmAnimationTracker.get(player.uuid) ?: return false
val rise = RecallArmAnimationTracker.raiseFactor(player.uuid)
poseStack.pushPose()
poseStack.translate(REST_X, REST_Y - RISE_DISTANCE * (1.0 - rise), REST_Z)
poseStack.scale(BALL_SCALE, -BALL_SCALE, -BALL_SCALE)
poseStack.mulPose(Axis.YP.rotationDegrees(180F))
poseStack.mulPose(Axis.XP.rotationDegrees(15F))
val state = anim.ballState
val ball = anim.ball
val model = VaryingModelRepository.getPoser(ball.name, state)
val texture = VaryingModelRepository.getTexture(ball.name, state)
state.updatePartialTicks(partialTicks)
model.context = ballContext
ballContext.put(RenderContext.ASPECTS, state.aspects)
ballContext.put(RenderContext.POSABLE_STATE, state)
model.applyAnimations(null, state, 0F, 0F, 0F, 0F, 0F)
val consumer = ItemRenderer.getFoilBufferDirect(buffer, RenderType.entityCutout(texture), false, false)
model.render(ballContext, poseStack, consumer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
model.red = 1F
model.green = 1F
model.blue = 1F
model.resetLayerContext()
poseStack.popPose()
return true
}
}
@@ -0,0 +1,73 @@
/*
* 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.player
import com.cobblemon.mod.common.client.battle.ClientBallDisplay
import com.cobblemon.mod.common.pokeball.PokeBall
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import net.minecraft.util.Mth
import net.minecraft.world.phys.Vec3
/**
* Tracks which players are recalling a Pokémon so we can pose their arm, draw the Poké Ball in their
* hand, and start the recall beam from it.
*
* Keyed by player UUID. Entries time out on their own once the beam is done, and a new recall resets
* the timer, so nothing has to clear them.
*
* Written by PokemonClientDelegate on recall (beamMode 3); read by HumanoidModelMixin, the ball
* renderers, and PokemonRenderer.
*/
object RecallArmAnimationTracker {
// How long the arm stays raised, in seconds.
const val ARM_HOLD_SECONDS = 0.8
// Fraction of the hold spent easing the arm up at the start and down at the end.
private const val EASE_SECONDS = 0.15
class RecallAnim(
val ball: PokeBall,
val aspects: Set<String>,
val startTimeMs: Long
) {
val ballState = ClientBallDisplay(ball, aspects)
var beamOrigin: Vec3? = null
}
private val activeRecalls = ConcurrentHashMap<UUID, RecallAnim>()
fun start(playerUuid: UUID, ball: PokeBall, aspects: Set<String>) {
activeRecalls[playerUuid] = RecallAnim(ball, aspects, System.currentTimeMillis())
}
/** Returns the active recall for the player, or null if there is none or if it has expired. */
fun get(playerUuid: UUID): RecallAnim? {
val anim = activeRecalls[playerUuid] ?: return null
if (secondsSince(anim) > ARM_HOLD_SECONDS) {
activeRecalls.remove(playerUuid)
return null
}
return anim
}
fun isRecalling(playerUuid: UUID): Boolean = get(playerUuid) != null
private fun secondsSince(anim: RecallAnim) = (System.currentTimeMillis() - anim.startTimeMs) / 1000.0
/** 0..1 ramp: eases in at the start, holds at 1, eases out at the end. 0 when not recalling. */
fun raiseFactor(playerUuid: UUID): Float {
val anim = get(playerUuid) ?: return 0F
val elapsed = secondsSince(anim)
val riseIn = Mth.clamp((elapsed / EASE_SECONDS).toFloat(), 0F, 1F)
val fallOut = Mth.clamp(((ARM_HOLD_SECONDS - elapsed) / EASE_SECONDS).toFloat(), 0F, 1F)
return minOf(riseIn, fallOut)
}
}
@@ -26,6 +26,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PosableP
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
import com.cobblemon.mod.common.client.render.player.RecallArmAnimationTracker
import com.cobblemon.mod.common.client.render.pokeball.PokeBallPosableState
import com.cobblemon.mod.common.client.render.renderBeaconBeam
import com.cobblemon.mod.common.client.settings.ServerSettings
@@ -60,6 +61,7 @@ import net.minecraft.network.chat.Style
import net.minecraft.resources.ResourceLocation
import net.minecraft.util.Mth
import net.minecraft.world.entity.Entity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.phys.Vec3
import org.joml.*
import kotlin.math.*
@@ -69,6 +71,9 @@ class PokemonRenderer(
) : MobRenderer<PokemonEntity, PosablePokemonEntityModel>(context, PosablePokemonEntityModel(), 0.5f) {
companion object {
val recallBeamColour = Vector4f(1F, 0.1F, 0.1F, 1F)
private const val CAPTURE_BEAM_X_OFFSET = 0.0
private const val CAPTURE_BEAM_Y_OFFSET = 0.2
private const val CAPTURE_BEAM_Z_OFFSET = 0.45
fun ease(x: Double): Double {
return 1 - (1 - x).pow(3)
}
@@ -142,8 +147,6 @@ class PokemonRenderer(
}
modelNow.setLayerContext(buffer, clientDelegate, VaryingModelRepository.getLayers(entity.pokemon.species.resourceIdentifier, clientDelegate))
if (entity.passengers.isNotEmpty()) {
renderRiding(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
} else {
@@ -316,8 +319,15 @@ class PokemonRenderer(
fun renderBeam(matrixStack: PoseStack, partialTicks: Float, entity: PokemonEntity, beamTarget: Entity, buffer: MultiBufferSource, offset: Vec3) {
val clientDelegate = entity.delegate as PokemonClientDelegate
val pokemonPosition = entity.position().add(0.0, entity.bbHeight / 2.0 * clientDelegate.activeSendoutScale.toDouble(), 0.0)
var beamSourcePosition = if (beamTarget is EmptyPokeBallEntity) {
(beamTarget.delegate as PokeBallPosableState).locatorStates["beam"]?.getOrigin() ?: beamTarget.position()
// If a player is recalling, start the beam from the Poké Ball held in their hand
val recallBallOrigin = (beamTarget as? Player)?.let { RecallArmAnimationTracker.get(it.uuid)?.beamOrigin }
var beamSourcePosition = if (recallBallOrigin != null) {
recallBallOrigin
} else if (beamTarget is EmptyPokeBallEntity) {
(beamTarget.delegate as PokeBallPosableState).locatorStates["beam"]
?.transformPosition(Vec3(CAPTURE_BEAM_X_OFFSET, CAPTURE_BEAM_Y_OFFSET, CAPTURE_BEAM_Z_OFFSET))
?: beamTarget.position()
} else {
if (beamTarget.uuid == Minecraft.getInstance().player?.uuid) {
val lookVec = beamTarget.lookAngle.yRot((PI / 2).toFloat()).multiply(1.0, 0.0, 1.0).normalize()
@@ -28,5 +28,7 @@ object ServerSettings {
var maxPokemonFriendship = Cobblemon.config.maxPokemonFriendship
var maxDynamaxLevel = Cobblemon.config.maxDynamaxLevel
var unlockAllMoveDexMovesByDefault = Cobblemon.config.unlockAllMoveDexMovesByDefault
var pokemonIntrinsicSizeMin = Cobblemon.config.pokemonIntrinsicSizeMin
var pokemonIntrinsicSizeMax = Cobblemon.config.pokemonIntrinsicSizeMax
}
@@ -243,18 +243,6 @@ class CobblemonConfig {
@CobblemonConfigField(Category.Pokemon, lang = "pokemon_intrinsic_size_max", SERVER)
var pokemonIntrinsicSizeMax = 1.05F
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_small_multiplier", SERVER)
var alphaPokemonSizeSmallMultiplier = 1.70F
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_medium_multiplier", SERVER)
var alphaPokemonSizeMediumMultiplier = 1.55F
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_large_multiplier", SERVER)
var alphaPokemonSizeLargeMultiplier = 1.40F
@CobblemonConfigField(Category.Pokemon, lang = "alpha_pokemon_size_extra_large_multiplier", SERVER)
var alphaPokemonSizeExtraLargeMultiplier = 1.25F
@CobblemonConfigField(Category.Pokemon, lang = "baby_pokemon_level_duration", SERVER)
var babyPokemonLevelDuration = 9
@@ -347,9 +335,6 @@ class CobblemonConfig {
// @CobblemonConfigField(Category.Riding, lang = "third_person_view_bobbing", CLIENT)
var thirdPersonViewBobbing = true
@CobblemonConfigField(Category.Riding, lang = "invert_roll", CLIENT)
var invertRoll = false
@CobblemonConfigField(Category.Riding, lang = "invert_pitch", CLIENT)
var invertPitch = false
@@ -365,9 +350,6 @@ class CobblemonConfig {
@CobblemonConfigField(Category.Riding, lang = "swap_x_and_y_axes", CLIENT)
var swapXAndYAxes = false
@CobblemonConfigField(Category.Riding, lang = "automatic_righting_delay", CLIENT)
var rightingDelay = -1.0
@CobblemonConfigField(Category.Riding, lang = "disable_roll", CLIENT)
var disableRoll = false
@@ -798,6 +798,13 @@ open class PokemonEntity(
return pokemon.isFireImmune()
}
/**
* Prevents ice type Pokémon from freezing (from powered snow)
*/
override fun canFreeze(): Boolean {
return !pokemon.isFreezeImmune() && super.canFreeze()
}
/**
* Prevents flying type Pokémon from taking fall damage.
*/
@@ -36,7 +36,7 @@ import net.minecraft.world.level.block.Block
class StatusCureItem(val itemName: String, vararg val status: Status, block: Block) : ItemNameBlockItem(block, Properties()), PokemonSelectingItem {
override val bagItem = object : BagItem {
override val itemName = this@StatusCureItem.itemName
override val returnItem = Items.AIR
override val returnItem = Items.GLASS_BOTTLE
override fun canUse(stack: ItemStack, battle: PokemonBattle, target: BattlePokemon) = canUseOnPokemon(stack, target.effectedPokemon)
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "cure_status${status.takeIf { it.isNotEmpty() }?.let { " ${it.joinToString(separator = " ") { it.showdownName } }" } ?: "" }"
}
@@ -26,7 +26,9 @@ class ServerSettingsPacket internal constructor(
val maxPokemonLevel: Int,
val maxPokemonFriendship: Int,
val maxDynamaxLevel: Int,
val unlockAllMoveDexMovesByDefault: Boolean
val unlockAllMoveDexMovesByDefault: Boolean,
val pokemonIntrinsicSizeMin: Float,
val pokemonIntrinsicSizeMax: Float
) : NetworkPacket<ServerSettingsPacket> {
override val id = ID
override fun encode(buffer: RegistryFriendlyByteBuf) {
@@ -37,9 +39,14 @@ class ServerSettingsPacket internal constructor(
buffer.writeInt(Cobblemon.config.maxPokemonFriendship)
buffer.writeInt(Cobblemon.config.maxDynamaxLevel)
buffer.writeBoolean(Cobblemon.config.unlockAllMoveDexMovesByDefault)
buffer.writeFloat(Cobblemon.config.pokemonIntrinsicSizeMin)
buffer.writeFloat(Cobblemon.config.pokemonIntrinsicSizeMax)
}
companion object {
val ID = cobblemonResource("server_settings")
fun decode(buffer: RegistryFriendlyByteBuf) = ServerSettingsPacket(buffer.readBoolean(), buffer.readBoolean(), buffer.readBoolean(), buffer.readInt(), buffer.readInt(), buffer.readInt(), buffer.readBoolean())
fun decode(buffer: RegistryFriendlyByteBuf) = ServerSettingsPacket(buffer.readBoolean(),
buffer.readBoolean(), buffer.readBoolean(),
buffer.readInt(), buffer.readInt(), buffer.readInt(),
buffer.readBoolean(), buffer.readFloat(), buffer.readFloat())
}
}
@@ -1037,6 +1037,10 @@ open class Pokemon : ShowdownIdentifiable {
return ElementalTypes.FIRE in types || form.behaviour.moving.swim.canSwimInLava || form.behaviour.fireImmune
}
fun isFreezeImmune(): Boolean {
return ElementalTypes.ICE in types || form.behaviour.freezeImmune
}
fun dampensVibrations(): Boolean = form.behaviour.dampensVibrations
// function to return the max hunger for the pokemon
@@ -8,7 +8,7 @@
package com.cobblemon.mod.common.pokemon
import com.cobblemon.mod.common.Cobblemon
import com.cobblemon.mod.common.client.settings.ServerSettings
enum class PokemonSizeCategory {
XS,
@@ -21,7 +21,7 @@ enum class PokemonSizeCategory {
// Find which size category corresponds to the given scale modifier.
// The scale modifier should be between the intrinsic min and max size.
fun fromScale(scaleModifier: Float): PokemonSizeCategory {
val config = Cobblemon.config
val config = ServerSettings //Don't use cobblemon config here as it will be used by server AND client
val minScale = config.pokemonIntrinsicSizeMin
val maxScale = config.pokemonIntrinsicSizeMax
val range = (maxScale - minScale).coerceAtLeast(0.0001F)
@@ -35,6 +35,9 @@ class FormPokemonBehaviour {
@SerializedName("fireImmune")
private val _fireImmune: Boolean? = null
@SerializedName("freezeImmune")
private val _freezeImmune: Boolean? = null
@SerializedName("dampensVibrations")
private val _dampensVibrations: Boolean? = null
@@ -72,6 +75,9 @@ class FormPokemonBehaviour {
val fireImmune: Boolean
get() = _fireImmune ?: parent.fireImmune
val freezeImmune: Boolean
get() = _freezeImmune ?: parent.freezeImmune
val entityInteract: EntityBehaviour
get() = _entityInteract ?: parent.entityInteract
@@ -318,7 +318,7 @@ class OmniPathNodeMaker : NodeEvaluator() {
// Hitbox thing looks confusing but if the hitbox volume is more than like, 5, it starts getting pretty
// fucking slow to use the findAcceptedNodeWalk function
val strictlyWalkPathing = !canFly() && !mob.isInWater && mob.boundingBox.size < MAX_HITBOX_SIZE_FOR_WALKING
val strictlyWalkPathing = !canFly() && !mob.isInWater
val doVerticalNeighbourChecks = (canFly() || mob.isInWater) && mob.boundingBox.size < MAX_HITBOX_FOR_VERTICAL_NEIGHBOURS
// Non-diagonal surroundings in 3d space
@@ -623,9 +623,11 @@ class OmniPathNodeMaker : NodeEvaluator() {
override fun getPathTypeOfMob(pfContext: PathfindingContext, x: Int, y: Int, z: Int, mob: Mob): PathType {
val set = EnumSet.noneOf(PathType::class.java)
val sizeX = (mob.boundingBox.maxX - mob.boundingBox.minX).toInt() + 1
val sizeY = (mob.boundingBox.maxY - mob.boundingBox.minY).toInt() + 1
val sizeZ = (mob.boundingBox.maxZ - mob.boundingBox.minZ).toInt() + 1
// Capping the observed size of hitboxes here to put an upper limit on the cost of larger hitbox mobs
// Mobs larger than these caps will inevitably become stuck on obstacles as their pathing will be flawed
val sizeX = ((mob.boundingBox.maxX - mob.boundingBox.minX).toInt() + 1).coerceAtMost(2)
val sizeY = ((mob.boundingBox.maxY - mob.boundingBox.minY).toInt() + 1).coerceAtMost(3)
val sizeZ = ((mob.boundingBox.maxZ - mob.boundingBox.minZ).toInt() + 1).coerceAtMost(2)
// TODO -- This is experimental code to see if this is meaningful. We should clean this up later when time permits.
val returnedEarlyPathType = mutableListOf<PathType>()
@@ -31,6 +31,7 @@ open class PokemonBehaviour(
val herd: HerdBehaviour = HerdBehaviour(),
val characteristicRainbow: Boolean = false,
val itemInteract: ItemBehavior = ItemBehavior(),
val freezeImmune: Boolean = false,
) {
@Transient
val struct = ObjectValue<PokemonBehaviour>(this).also {
@@ -274,11 +274,9 @@ object DataKeys {
// Habitat Blocks
const val HABITAT_SPAWNING_STYLE = "SpawningStyle"
const val HABITAT_MIMIC = "MimicId"
const val HABITAT_PHASE_COUNT = "PhaseCount"
const val HABITAT_PHASE_ORDER = "PhaseOrder"
const val HABITAT_LEVEL_RANGE = "LevelRange"
const val HABITAT_MODIFIERS = "Modifiers"
const val HABITAT_POOL = "Pool"
// --- Pools
const val HABITAT_POOL_ID = "PoolId"
@@ -92,7 +92,9 @@ object CobblemonPlacedFeatures {
@JvmField
val SKELETAL_FALL = of("habitats/skeletal_fall")
@JvmField
val STRANGE_FUNGAL_DWELLINGS = of("habitats/strange_fungal_dwellings")
val STRANGE_CRIMSON_FUNGAL_DWELLINGS = of("habitats/strange_crimson_fungal_dwellings")
@JvmField
val STRANGE_WARPED_FUNGAL_DWELLINGS = of("habitats/strange_warped_fungal_dwellings")
@JvmField
val VOLCANIC_PLUMES = of("habitats/volcanic_plumes")
@@ -177,7 +179,8 @@ object CobblemonPlacedFeatures {
Cobblemon.implementation.addFeatureToWorldGen(ROOT_NURSERIES, GenerationStep.Decoration.LOCAL_MODIFICATIONS, CobblemonBiomeTags.IS_SWAMP)
Cobblemon.implementation.addFeatureToWorldGen(SANDY_TIDEPOOLS, GenerationStep.Decoration.LOCAL_MODIFICATIONS, CobblemonBiomeTags.IS_BEACH)
Cobblemon.implementation.addFeatureToWorldGen(SKELETAL_FALL, GenerationStep.Decoration.LOCAL_MODIFICATIONS, CobblemonBiomeTags.IS_SOUL_SAND)
Cobblemon.implementation.addFeatureToWorldGen(STRANGE_FUNGAL_DWELLINGS, GenerationStep.Decoration.LOCAL_MODIFICATIONS, CobblemonBiomeTags.IS_WASTELAND)
Cobblemon.implementation.addFeatureToWorldGen(STRANGE_CRIMSON_FUNGAL_DWELLINGS, GenerationStep.Decoration.LOCAL_MODIFICATIONS, CobblemonBiomeTags.IS_WASTELAND)
Cobblemon.implementation.addFeatureToWorldGen(STRANGE_WARPED_FUNGAL_DWELLINGS, GenerationStep.Decoration.LOCAL_MODIFICATIONS, CobblemonBiomeTags.IS_WASTELAND)
Cobblemon.implementation.addFeatureToWorldGen(VOLCANIC_PLUMES, GenerationStep.Decoration.LOCAL_MODIFICATIONS, BiomeTags.IS_NETHER)
Cobblemon.implementation.addFeatureToWorldGen(PREHISTORIC_BIRCH_TREE, GenerationStep.Decoration.LAKES, CobblemonBiomeTags.HAS_BIRCH_LOG)
Cobblemon.implementation.addFeatureToWorldGen(PREHISTORIC_DRIPSTONE_OASIS, GenerationStep.Decoration.LAKES, CobblemonBiomeTags.IS_DRIPSTONE)
@@ -13,7 +13,10 @@ import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.BlockPos
import net.minecraft.world.level.LevelReader
import net.minecraft.world.level.LevelHeightAccessor
import net.minecraft.world.level.chunk.ChunkGenerator
import net.minecraft.world.level.levelgen.Heightmap
import net.minecraft.world.level.levelgen.RandomState
import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessor
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate
@@ -24,6 +27,25 @@ class HeightRangeStructureProcessor(
val reference: HeightReference = HeightReference.SEA_LEVEL
) : StructureProcessor() {
fun isValidPlacement(world: LevelReader, pos: BlockPos): Boolean {
val referenceY = reference.getY(world, pos)
val minY = referenceY + minOffset
val maxY = referenceY + maxOffset
return pos.y in minY..maxY
}
fun isValidPlacement(
chunkGenerator: ChunkGenerator,
heightAccessor: LevelHeightAccessor,
randomState: RandomState,
pos: BlockPos
): Boolean {
val referenceY = reference.getY(chunkGenerator, heightAccessor, randomState, pos)
val minY = referenceY + minOffset
val maxY = referenceY + maxOffset
return pos.y in minY..maxY
}
override fun processBlock(
world: LevelReader,
pos: BlockPos,
@@ -32,11 +54,7 @@ class HeightRangeStructureProcessor(
currentBlockInfo: StructureTemplate.StructureBlockInfo,
data: StructurePlaceSettings
): StructureTemplate.StructureBlockInfo? {
val referenceY = reference.getY(world, pos)
val minY = referenceY + minOffset
val maxY = referenceY + maxOffset
return if (pos.y in minY..maxY) {
return if (isValidPlacement(world, pos)) {
currentBlockInfo
} else {
null
@@ -65,6 +83,19 @@ class HeightRangeStructureProcessor(
}
}
fun getY(
chunkGenerator: ChunkGenerator,
heightAccessor: LevelHeightAccessor,
randomState: RandomState,
pos: BlockPos
): Int {
return if (this == SEA_LEVEL) {
chunkGenerator.seaLevel
} else {
chunkGenerator.getBaseHeight(pos.x, pos.z, type ?: Heightmap.Types.WORLD_SURFACE_WG, heightAccessor, randomState)
}
}
companion object {
val CODEC: Codec<HeightReference> = Codec.STRING.xmap(
{ serialized -> entries.firstOrNull { it.id == serialized } ?: SEA_LEVEL },
@@ -0,0 +1,39 @@
{
"format_version": "1.8.0",
"animations": {
"animation.playrough.actor": {
"animation_length": 3,
"bones": {
"root_part": {
"position": {
"0.0": [0, 0, 0],
"0.0417": [0, 0, -3],
"0.0833": [0, 0, -6],
"0.125": [0, 0, -16],
"0.2917": [0, 0, -26],
"1.2083": [0, 0, -10],
"1.2917": [0, 0, -4],
"1.4167": [0, 0, 0]
},
"scale": {
"0.0": [1, 1, 1],
"0.0417": [1, 1, 1.05],
"0.0833": [1, 1, 1.2],
"0.125": {"pre": [0.9841, 0.9841, 1.6], "post": [0, 0, 0]},
"1.2083": {"pre": [0, 0, 0], "post": [1, 1, 1]}
}
}
},
"particle_effects": {
"0.0": {
"effect": "closecombat_actor",
"locator": "middle"
},
"0.0417": {
"effect": "closecombat_dashlines",
"locator": "middle"
}
}
}
}
}
@@ -0,0 +1,72 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:blizzard_actor",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/impact/impact_ice"
}
},
"curves": {
"variable.bsizing": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.69, 0.96, 1, 1, 1, 1, 1, 1, 0.96, 0.82, 0]
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 900,
"max_particles": 10000
},
"minecraft:emitter_lifetime_once": {
"active_time": 1.1
},
"minecraft:emitter_shape_box": {
"offset": [0, 4, 2],
"half_dimensions": [10, 4, 10],
"direction": ["(v.particle_random_1-0.5)*0.5", "(v.target_deltay/v.target_distance)+((v.particle_random_2-0.5)*0.5)", -1]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.9,1.4)*1.1"
},
"minecraft:particle_initial_speed": "(v.particle_random_4+1)*16",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["math.sin(v.particle_age*((v.particle_random_2-0.5)*(360+(v.particle_random_2*180))))*1.5", "math.cos(v.particle_age*((v.particle_random_4-0.5)*(360+(v.particle_random_2*180))))*2", "math.sin(v.particle_age*((v.particle_random_1-0.5)*(360+(v.particle_random_2*180))))*1.5"],
"linear_drag_coefficient": 1.5
},
"minecraft:particle_appearance_billboard": {
"size": ["0.1*v.bsizing", "0.1*v.bsizing"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 56,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [8, 8],
"step_UV": [0, 8],
"frames_per_second": 10,
"max_frame": 7,
"loop": true
}
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 0.2,
"coefficient_of_restitution": 0.05,
"collision_radius": 0.1
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFFFFF",
"1.0": "#FFAAD4FF"
}
}
}
}
}
}
@@ -0,0 +1,73 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:blizzard_target",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/impact/impact_ice"
}
},
"curves": {
"variable.dfd": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.69, 0.96, 1, 1, 1, 0.96, 0.82, 0]
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.entity_height=1;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 1000,
"max_particles": 10000
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.1
},
"minecraft:emitter_shape_point": {
"direction": ["(v.particle_random_1-0.5)*3", "(v.particle_random_2-0.5)*3", "(v.particle_random_3-0.5)*3"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "0.6+(v.particle_random_4*0.4)"
},
"minecraft:particle_initial_speed": "math.random(1.25,4.75)*7",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_3-0.5)*16", "(v.particle_random_4-0.5)*16", "(v.particle_random_2-0.5)*16"],
"linear_drag_coefficient": 4
},
"minecraft:particle_appearance_billboard": {
"size": ["0.1*v.dfd", "0.1*v.dfd"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 56,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [8, 8],
"step_UV": [0, 8],
"frames_per_second": 10,
"max_frame": 7,
"stretch_to_lifetime": true
}
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 0.2,
"coefficient_of_restitution": 0.6,
"collision_radius": 0.1
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFFFFF",
"1.0": "#FFAAD4FF"
}
}
}
}
}
}
@@ -0,0 +1,64 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:blizzard_targetswirl",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/impact/impact_ice"
}
},
"curves": {
"variable.dfd": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.69, 0.96, 1, 1, 1, 0.96, 0.82, 0]
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.entity_height=1;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 200,
"max_particles": 10000
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.7
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "0.6+(v.particle_random_4*0.4)"
},
"minecraft:particle_motion_parametric": {
"relative_position": ["(math.sin((v.particle_age*420)+(v.particle_random_1*360))*(math.clamp(v.entity_radius*1.04,0.65,4)+(v.particle_age*1.7)))", "(math.cos((v.particle_age*410)+(v.particle_random_1*360))*0.25)+((((v.particle_random_2-0.5)*2)*(v.entity_height*0.65))+((v.particle_age+v.particle_age)*(v.particle_random_4-0.5)))", "(math.cos((v.particle_age*410)+(v.particle_random_1*360))*(math.clamp(v.entity_radius*1.04,0.65,4)+(v.particle_age*1.7)))"]
},
"minecraft:particle_appearance_billboard": {
"size": ["0.1*v.dfd", "0.1*v.dfd"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 56,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [8, 8],
"step_UV": [0, 8],
"frames_per_second": 10,
"max_frame": 7,
"loop": true
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFFFFF",
"1.0": "#FFAAD4FF"
}
}
}
}
}
}
@@ -37,7 +37,7 @@
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["0.35+(v.particle_age*0.175)", "0.35+(v.particle_age*0.175)"],
"facing_camera_mode": "rotate_xyz",
"facing_camera_mode": "emitter_transform_xy",
"uv": {
"texture_width": 117,
"texture_height": 13,
@@ -48,7 +48,7 @@
0.55,
0.55
],
"facing_camera_mode": "rotate_xyz",
"facing_camera_mode": "emitter_transform_xy",
"uv": {
"texture_width": 68,
"texture_height": 17,
@@ -0,0 +1,60 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:disarmingvoice_actor1",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/ring/largering"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.target_deltaz=5;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 8,
"max_particles": 7
},
"minecraft:emitter_lifetime_once": {
"active_time": 1.1
},
"minecraft:emitter_shape_point": {
"offset": ["v.target_deltax*(v.emitter_age/v.emitter_lifetime)", "v.target_deltay*(v.emitter_age/v.emitter_lifetime)", "-(v.target_deltaz*(v.emitter_age/v.emitter_lifetime))"],
"direction": [0, "(v.target_deltay/v.target_distance)", -1]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.43
},
"minecraft:particle_initial_speed": "math.clamp(v.target_deltaz,1,12)",
"minecraft:particle_motion_dynamic": {
"linear_drag_coefficient": "math.clamp(v.target_deltaz*1.5,3,10)"
},
"minecraft:particle_appearance_billboard": {
"size": [0.75, 0.75],
"facing_camera_mode": "emitter_transform_xy",
"uv": {
"texture_width": 160,
"texture_height": 20,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [20, 20],
"step_UV": [20, 0],
"frames_per_second": 20,
"max_frame": 8
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFECFE",
"0.47": "#FFFF89E8",
"1.0": "#FFE600BA"
}
}
}
}
}
}
@@ -0,0 +1,60 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:disarmingvoice_actor2",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/ring/mediumring"
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.target_deltaz=5;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 8,
"max_particles": 7
},
"minecraft:emitter_lifetime_once": {
"active_time": 1.1
},
"minecraft:emitter_shape_point": {
"offset": ["v.target_deltax*(v.emitter_age/v.emitter_lifetime)", "v.target_deltay*(v.emitter_age/v.emitter_lifetime)", "-(v.target_deltaz*(v.emitter_age/v.emitter_lifetime))"],
"direction": [0, "(v.target_deltay/v.target_distance)", -1]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.3
},
"minecraft:particle_initial_speed": "math.clamp(v.target_deltaz,1,12)",
"minecraft:particle_motion_dynamic": {
"linear_drag_coefficient": "math.clamp(v.target_deltaz*1.5,3,10)"
},
"minecraft:particle_appearance_billboard": {
"size": [0.55, 0.55],
"facing_camera_mode": "emitter_transform_xy",
"uv": {
"texture_width": 90,
"texture_height": 15,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [15, 15],
"step_UV": [15, 0],
"frames_per_second": 20,
"max_frame": 6
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFECFE",
"0.47": "#FFFF89E8",
"1.0": "#FFE600BA"
}
}
}
}
}
}
@@ -0,0 +1,63 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:disarmingvoice_actorhearts",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/status/infatuation_heart"
}
},
"curves": {
"variable.d": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.93, 1, 1, 1, 0.93, 0.61, 0]
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.target_deltaz=5;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 25,
"max_particles": 2000
},
"minecraft:emitter_lifetime_once": {
"active_time": 1.1
},
"minecraft:emitter_shape_point": {
"offset": ["(v.target_deltax*(v.emitter_age/v.emitter_lifetime))+math.sin(v.emitter_age*360*7.5)*0.7", "(v.target_deltay*(v.emitter_age/v.emitter_lifetime))+math.cos(v.emitter_age*360*7.5)*0.7", "-(v.target_deltaz*(v.emitter_age/v.emitter_lifetime))"],
"direction": [0, "(v.target_deltay/v.target_distance)", -1]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.45
},
"minecraft:particle_initial_speed": "v.target_deltaz*0.5",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)", "(v.particle_random_2-0.5)", "(v.particle_random_3-0.5)"],
"linear_drag_coefficient": 4
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.1-(v.particle_random_4*0.04))*v.d", "(0.1-(v.particle_random_4*0.04))*v.d"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 90,
"texture_height": 9,
"uv": [3, 3],
"uv_size": [3, 3]
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFF89E8",
"1.0": "#FFE600BA"
}
}
}
}
}
}
@@ -0,0 +1,70 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:disarmingvoice_target",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/ring/xlring"
}
},
"curves": {
"variable.s": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0.24, 0.69, 0.9, 0.98, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}
},
"events": {
"event": {
"particle_effect": {
"effect": "cobblemon:disarmingvoice_targetsparks",
"type": "emitter"
}
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 1.1
},
"minecraft:emitter_lifetime_events": {
"creation_event": "event"
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.43
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["1*v.s", "1*v.s"],
"facing_camera_mode": "emitter_transform_xy",
"uv": {
"texture_width": 160,
"texture_height": 20,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [20, 20],
"step_UV": [20, 0],
"frames_per_second": 20,
"max_frame": 8
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFECFE",
"0.47": "#FFFF89E8",
"1.0": "#FFE600BA"
}
}
}
}
}
}
@@ -0,0 +1,64 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:disarmingvoice_targetsparks",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/orb/scaling"
}
},
"curves": {
"variable.size": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 1, 0.98, 0.86, 0.6, 0]
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 10
},
"minecraft:emitter_lifetime_once": {
"active_time": 1
},
"minecraft:emitter_shape_point": {
"direction": ["math.random(-0.91,0.91)", "math.random(-0.81, 1.01)", "math.random(-0.91,0.91)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.45, 0.6)"
},
"minecraft:particle_initial_speed": "(0.8+(v.particle_random_4*0.6))*10",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*7", "(v.particle_random_2-0.5)*7", "(v.particle_random_3-0.5)*7"],
"linear_drag_coefficient": 5
},
"minecraft:particle_appearance_billboard": {
"size": ["0.11*v.size", "0.11*v.size"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 32,
"flipbook": {
"base_UV": [0, 16],
"size_UV": [8, 8],
"step_UV": [0, -8],
"frames_per_second": 12,
"max_frame": 3,
"stretch_to_lifetime": true
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFECFE",
"0.93": "#FFE600BA"
}
}
}
}
}
}
@@ -0,0 +1,77 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:dragonbreath_actor",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/fire/cloudyfire_white"
}
},
"curves": {
"variable.fun": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [1, 1, 1, 1, 0.99, 0.97, 0.91, 0.77, 0.54, -0.1]
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.target_deltaz=5;v.target_deltax=0;v.target_deltay=0;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": "30*(math.clamp(v.target_deltaz,1,4))",
"max_particles": 1000
},
"minecraft:emitter_lifetime_once": {
"active_time": 1
},
"minecraft:emitter_shape_point": {
"direction": ["(-v.target_deltax+((v.particle_random_1-0.5)*1.05))+(math.sin(v.emitter_age*360)*0.25)", "(v.target_deltay+((v.particle_random_2-0.5)*1.05))+(math.sin(v.emitter_age*540)*0.2)", "-v.target_deltaz*1.05"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.75,1.0)*1.4"
},
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_4*3)*90"
},
"minecraft:particle_initial_speed": "(v.target_deltaz*((v.particle_random_4+0.75)*1.15))*(math.clamp(v.target_deltaz,3,24)/1.7)",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_3-0.5)*4", "3+(v.particle_random_1-0.5)*2", "(v.particle_random_2-0.5)*1"],
"linear_drag_coefficient": "math.clamp(v.target_deltaz,1,20)*(0.5+(math.clamp(v.target_deltaz,1,5)*0.05))"
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.5-(v.particle_random_4*0.15))*v.fun", "(0.5-(v.particle_random_4*0.15))*v.fun"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 160,
"texture_height": 16,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [16, 16],
"step_UV": [16, 0],
"frames_per_second": 12,
"max_frame": 10
}
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 10,
"collision_radius": 0.01
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "(v.particle_age / v.particle_lifetime) * (v.particle_random_4+0.75)",
"gradient": {
"0.0": "#FFFFE6A1",
"0.05": "#FFFFE6A1",
"0.2": "#FFFF3B8F",
"0.6": "#FFA300FF",
"1.0": "#FF3E00C7"
}
}
}
}
}
}
@@ -0,0 +1,71 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:dragonbreath_target",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/fire/cloudyfire_white"
}
},
"curves": {
"variable.dorasize": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0.42, 0.77, 0.91, 0.98, 1, 1, 1, 1, 1, 0.86, 0.55, 0]
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 250,
"max_particles": 150
},
"minecraft:emitter_lifetime_looping": {
"active_time": 0.3
},
"minecraft:emitter_shape_point": {
"offset": [0, 0, "math.random(0.15,-0.05)"],
"direction": ["math.random(-2,2)*1.1", "math.random(-2,2)*1.1", "math.random(-2,2)*0.45"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.65,1.0)*1.4"
},
"minecraft:particle_initial_speed": "math.random(1.25,4.75)*1.25",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, "math.random(1.5,3.5)", 0],
"linear_drag_coefficient": "math.random(1.25,1.5)*2"
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.5-(v.particle_random_4*0.15))*v.dorasize", "(0.5-(v.particle_random_4*0.15))*v.dorasize"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 160,
"texture_height": 16,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [16, 16],
"step_UV": [16, 0],
"frames_per_second": 12,
"max_frame": 10
}
}
},
"minecraft:particle_motion_collision": {
"coefficient_of_restitution": 0.1,
"collision_radius": 0.1
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFE6A1",
"0.35": "#FFFF3B8F",
"0.7": "#FFA300FF",
"1.0": "#FF3E00C7"
}
}
}
}
}
}
@@ -0,0 +1,74 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:dragonrage_actor",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/fire/cloudyfire_white"
}
},
"curves": {
"variable.fun": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [1, 1, 1, 0.99, 0.95, 0.8, 0.5, 0.05]
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.target_deltaz=5;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 60,
"max_particles": 300
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.65
},
"minecraft:emitter_shape_point": {
"offset": ["-v.target_deltax*(v.emitter_age/v.emitter_lifetime)", "v.target_deltay*(v.emitter_age/v.emitter_lifetime)", "-v.target_deltaz*(v.emitter_age/v.emitter_lifetime)"],
"direction": ["math.random(-0.45,0.45)", "math.random(-0.45,0.45)-(v.target_deltay/v.target_deltaz)", "math.random(-2.05,-0.55)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.7
},
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_4*3)*90"
},
"minecraft:particle_initial_speed": "math.random(2.75,3.25)*(v.target_deltaz*0.5)",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*4", "1.5+(v.particle_random_1-0.5)*3", "(v.particle_random_1-0.5)*3"],
"linear_drag_coefficient": 4
},
"minecraft:particle_appearance_billboard": {
"size": ["0.45*v.fun", "0.45*v.fun"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 160,
"texture_height": 16,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [16, 16],
"step_UV": [16, 0],
"frames_per_second": 20,
"max_frame": 10
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFA1A1",
"0.05": "#FFFFA1A1",
"0.2": "#FFFF3BF2",
"0.6": "#FF7C00FF",
"1.0": "#FF3E00C7"
}
}
}
}
}
}
@@ -0,0 +1,85 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:dragonrage_actorburst",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/fire/cloudyfire_white"
}
},
"curves": {
"variable.fun": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [1, 1, 1, 1, 0.97, 0.87, 0.54, 0]
}
},
"events": {
"ring": {
"particle_effect": {
"effect": "cobblemon:dragonrage_actorring",
"type": "emitter"
}
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 200,
"max_particles": 1000
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.1
},
"minecraft:emitter_lifetime_events": {
"creation_event": "ring"
},
"minecraft:emitter_shape_point": {
"direction": ["math.random(-1.05,1.05)*1.25", "math.random(-1.05,1.05)*1.25", "math.random(-1.25,-0.05)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.4,0.8)"
},
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_4*3)*90"
},
"minecraft:particle_initial_speed": "math.random(2.5,7.5)*2",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*4", "3+(v.particle_random_1-0.5)*3", "(v.particle_random_1-0.5)*1"],
"linear_drag_coefficient": 4
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.5-(v.particle_random_4*0.15))*v.fun", "(0.5-(v.particle_random_4*0.15))*v.fun"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 160,
"texture_height": 16,
"flipbook": {
"base_UV": [16, 0],
"size_UV": [16, 16],
"step_UV": [16, 0],
"frames_per_second": 20,
"max_frame": 9
}
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 10,
"collision_radius": 0.01
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFA1A1",
"0.05": "#FFFFA1A1",
"0.2": "#FFFF3BF2",
"0.6": "#FF7C00FF",
"1.0": "#FF3E00C7"
}
}
}
}
}
}
@@ -0,0 +1,63 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:dragonrage_actorring",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/ring/xlring"
}
},
"curves": {
"variable.s": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.57, 0.84, 0.96, 1, 1, 1, 1, 1, 1, 1]
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.05
},
"minecraft:emitter_shape_point": {
"offset": [0, 0, -0.1]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.45
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["1.2*v.s", "1.2*v.s"],
"facing_camera_mode": "emitter_transform_xy",
"uv": {
"texture_width": 200,
"texture_height": 25,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [25, 25],
"step_UV": [25, 0],
"frames_per_second": 20,
"max_frame": 8
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFA1A1",
"0.05": "#FFFFA1A1",
"0.2": "#FFFF3BF2",
"0.78": "#FF6600C7",
"1.0": "#003E00C7"
}
}
}
}
}
}
@@ -0,0 +1,84 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:dragonrage_target",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/fire/cloudyfire_white"
}
},
"curves": {
"variable.fun": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [1, 1, 1, 1, 1, 1, 0.96, 0.85, 0.6, -0.05]
}
},
"events": {
"cover": {
"particle_effect": {
"effect": "cobblemon:dragonrage_targetcover",
"type": "emitter_bound"
}
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": "30*math.clamp(v.entity_height,1,2)"
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.05
},
"minecraft:emitter_lifetime_events": {
"creation_event": "cover"
},
"minecraft:emitter_shape_point": {
"direction": ["math.random(-1.55,1.55)", "math.random(-1.55,1.55)", "math.random(-1.55,1.55)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.35,0.95)"
},
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_4*3)*90"
},
"minecraft:particle_initial_speed": "math.random(3,8.5)*math.clamp(v.entity_height,1,1.5)",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*5", "4+(v.particle_random_2-0.5)*3", "(v.particle_random_3-0.5)*5"],
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.5-(v.particle_random_4*0.15))*v.fun", "(0.5-(v.particle_random_4*0.15))*v.fun"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 160,
"texture_height": 16,
"flipbook": {
"base_UV": [16, 0],
"size_UV": [16, 16],
"step_UV": [16, 0],
"frames_per_second": 20,
"max_frame": 9
}
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 10,
"collision_radius": 0.01
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFA1A1",
"0.05": "#FFFFA1A1",
"0.2": "#FFFF3BF2",
"0.6": "#FF7C00FF",
"1.0": "#FF3E00C7"
}
}
}
}
}
}
@@ -0,0 +1,78 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:dragonrage_targetcover",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/fire/cloudyfire_white"
}
},
"curves": {
"variable.burstarc": {
"type": "linear",
"input": "v.emitter_age",
"horizontal_range": "v.emitter_lifetime",
"nodes": [0.06, 0.5, 0.78, 0.91, 0.97, 0.99, 0.96, 0.83, 0.55, 0.06]
},
"variable.fun": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [1, 1, 1, 1, 1, 1, 0.96, 0.85, 0.6, -0.05]
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": "25*math.clamp(v.entity_height,1,2)",
"max_particles": 1000
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.75
},
"minecraft:emitter_shape_sphere": {
"radius": "(v.entity_height*(0.7-(v.particle_random_4*0.15)))*math.clamp(v.entity_scale,0.5,1))",
"surface_only": true,
"direction": ["math.random(-0.45,0.45)", "math.random(-0.15,0.35)", "math.random(-0.45,0.45)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.45,0.75)"
},
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_4*3)*90"
},
"minecraft:particle_initial_speed": 1,
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*4", "3+(v.particle_random_1-0.5)*2", "(v.particle_random_1-0.5)*4"],
"linear_drag_coefficient": 2
},
"minecraft:particle_appearance_billboard": {
"size": ["0.4*v.fun", "0.4*v.fun"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 160,
"texture_height": 16,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [16, 16],
"step_UV": [16, 0],
"frames_per_second": 20,
"max_frame": 10
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFA1A1",
"0.05": "#FFFFA1A1",
"0.2": "#FFFF3BF2",
"0.6": "#FF7C00FF",
"1.0": "#FF3E00C7"
}
}
}
}
}
}
@@ -0,0 +1,78 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:drainpunch_actor",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/orb/xsfadeorblite"
}
},
"curves": {
"variable.drainopen": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0.35, 0.8, 0.98, 1, 1, 1, 1, 0.98, 0.9, 0.65, 0.01]
}
},
"events": {
"sparkle": {
"particle_effect": {
"effect": "cobblemon:megadrain_actortrail",
"type": "particle"
}
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 15,
"max_particles": 32
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1.3
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.7
},
"minecraft:particle_lifetime_events": {
"timeline": {
"0.05": "sparkle",
"0.15": "sparkle",
"0.33": "sparkle",
"0.45": "sparkle"
}
},
"minecraft:particle_motion_parametric": {
"relative_position": ["(math.sin((v.particle_age*65)+(v.emitter_age*1523))*(0.75-(v.particle_age*(v.particle_age*1.7)))*v.drainopen)-(v.target_deltax*0.9)+((v.target_deltax * (v.particle_age / v.particle_lifetime))*0.95)", "(math.cos((v.particle_age*65)+(v.emitter_age*1523))*(0.75-(v.particle_age*(v.particle_age*1.7)))*v.drainopen)+(v.target_deltay*0.9)-((v.target_deltay * (v.particle_age / v.particle_lifetime))*0.95)", "-(v.target_deltaz*0.9)+((v.target_deltaz*(v.particle_age / v.particle_lifetime))*0.95)"]
},
"minecraft:particle_appearance_billboard": {
"size": [0.135, 0.135],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 45,
"texture_height": 5,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [5, 5],
"step_UV": [5, 0],
"frames_per_second": 12,
"max_frame": 9
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#8FC48F00",
"0.25": "#DFFFE74E",
"0.85": "#DFBDF700",
"1.0": "#4F65D000"
}
}
}
}
}
}
@@ -0,0 +1,81 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:drainpunch_target",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/bigfist"
}
},
"curves": {
"variable.punch": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0.54, 0.27, 0, 0.06, 0.1, 0.13, 0.15, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16]
}
},
"events": {
"burst": {
"particle_effect": {
"effect": "cobblemon:drainpunch_targetburst",
"type": "emitter"
}
},
"ring": {
"particle_effect": {
"effect": "cobblemon:drainpunch_targetring",
"type": "emitter"
}
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1
},
"minecraft:emitter_lifetime_events": {
"timeline": {
"0.05": ["burst", "ring"]
}
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.65
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["0.6+v.punch", "0.6+v.punch"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 270,
"texture_height": 30,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [30, 30],
"step_UV": [30, 0],
"frames_per_second": 14,
"max_frame": 9
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFF7A00",
"0.2": "#FFFFA700",
"0.25": "#FFFFF390",
"0.43": "#FFFF7A00",
"0.65": "#FFB84100",
"1.0": "#005F1D00"
}
}
}
}
}
}
@@ -0,0 +1,73 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:drainpunch_targetburst",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/orb/xsfadeorblite"
}
},
"curves": {
"variable.scale": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 1, 0.97, 0.94, 0.89, 0.83, 0.68, 0.52, 0.26, 0]
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 300,
"max_particles": 10000
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.05
},
"minecraft:emitter_shape_point": {
"direction": ["(v.particle_random_1-0.5)*6", "(v.particle_random_2-0.5)*6", "(v.particle_random_3-0.5)*4"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.5,0.8)"
},
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_2*3)*90"
},
"minecraft:particle_initial_speed": "(3+(v.particle_random_4*5))*3.5",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*12", "(v.particle_random_2-0.5)*12", "(v.particle_random_3-0.5)*12"],
"linear_drag_coefficient": 8
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.1-(v.particle_random_4*0.06))*variable.scale", "(0.1-(v.particle_random_4*0.06))*variable.scale"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 45,
"texture_height": 5,
"flipbook": {
"base_UV": [10, 0],
"size_UV": [5, 5],
"step_UV": [5, 0],
"frames_per_second": 16,
"max_frame": 7
}
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 1,
"collision_radius": 0.01,
"expire_on_contact": true
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age/v.particle_lifetime",
"gradient": {
"0.0": "#FFFF7A00",
"0.2": "#FFFFF390",
"1.0": "#FFFF7A00"
}
}
}
}
}
}
@@ -0,0 +1,59 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:drainpunch_targetring",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/ring/xlring"
}
},
"curves": {
"variable.s": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.56, 0.88, 0.98, 1, 1, 1, 1, 1]
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.5
},
"minecraft:emitter_shape_point": {},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.4
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": ["1.05*v.s", "1.05*v.s"],
"facing_camera_mode": "emitter_transform_xy",
"uv": {
"texture_width": 200,
"texture_height": 25,
"flipbook": {
"base_UV": [50, 0],
"size_UV": [25, 25],
"step_UV": [25, 0],
"frames_per_second": 16,
"max_frame": 6
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFF390",
"0.79": "#FFFF7A00",
"1.0": "#FFBA3800"
}
}
}
}
}
}
@@ -5,7 +5,7 @@
"identifier": "cobblemon:eruption_target",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/vanilla/lava"
"texture": "textures/particles/generic/burning_rock"
}
},
"curves": {
@@ -19,7 +19,7 @@
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [1, 1, 0.99, 0.97, 0.93, 0.83, 0.54, 0]
"nodes": [-0.04, 0.46, 0.8, 0.96, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}
},
"events": {
@@ -47,7 +47,7 @@
"creation_expression": "v.target_deltaz=10;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 25,
"spawn_rate": 10,
"max_particles": 1000
},
"minecraft:emitter_lifetime_once": {
@@ -55,7 +55,7 @@
},
"minecraft:emitter_shape_disc": {
"offset": [0, 9, "-v.target_deltaz*0.33"],
"radius": "math.clamp(v.entity_width,1.5,10)",
"radius": "math.clamp(v.entity_width,2,10)",
"direction": ["(v.particle_random_1-0.5)*0.3", "(-v.particle_random_2-0.55)*0.9", "(v.target_deltaz*0.05)+(v.particle_random_3-0.5)*0.3"]
},
"minecraft:particle_lifetime_expression": {
@@ -87,18 +87,18 @@
"linear_drag_coefficient": 1
},
"minecraft:particle_appearance_billboard": {
"size": ["((0.3-(v.particle_random_4*0.125))*v.quiver)*v.shrink", "((0.3-(v.particle_random_4*0.125))*v.quiver)*v.shrink"],
"size": ["((0.8-(v.particle_random_4*0.125))*v.quiver)*v.shrink", "((0.8-(v.particle_random_4*0.125))*v.quiver)*v.shrink"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
"texture_width": 32,
"texture_height": 192,
"uv": [0, "math.round(v.particle_random_4*5)*32"],
"uv_size": [32, 32]
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 20,
"collision_radius": 0.1
"collision_radius": 0.2
},
"minecraft:particle_appearance_tinting": {
"color": {
@@ -38,7 +38,7 @@
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 400,
"spawn_rate": 600,
"max_particles": 10000
},
"minecraft:emitter_lifetime_once": {
@@ -18,13 +18,13 @@
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
"num_particles": 2
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.4
},
"minecraft:emitter_shape_point": {
"offset": [0, 0, 0],
"offset": [0, -0.5, 0.25],
"direction": ["math.random(-1.55,1.55)*0.7", "math.random(-1.55,-0.55)", "math.random(-1.55,1.55)*0.7"]
},
"minecraft:particle_lifetime_expression": {
@@ -0,0 +1,84 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:fairywind_actor",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/vanilla/generic"
}
},
"curves": {
"variable.debrissize": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 1, 1, 0.89, 0.59, 0]
}
},
"events": {
"sparkle": {
"particle_effect": {
"effect": "cobblemon:fairywind_actorspark",
"type": "particle"
}
}
},
"components": {
"minecraft:emitter_initialization": {
"creation_expression": "v.target_deltaz=5;"
},
"minecraft:emitter_rate_steady": {
"spawn_rate": 30,
"max_particles": 1000
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.4
},
"minecraft:emitter_shape_sphere": {
"offset": ["-((v.target_deltax*0.8)*(v.emitter_age/v.emitter_lifetime))", "((v.target_deltay*0.8)*(v.emitter_age/v.emitter_lifetime))", "-((v.target_deltaz*0.8)*(v.emitter_age/v.emitter_lifetime))"],
"radius": "0.1+(v.emitter_age*2)",
"surface_only": true,
"direction": ["(math.random(-0.4,0.4))/((v.emitter_age+0.25)*5)", "(math.random(-0.3,0.3))+((v.target_deltay/v.target_deltaz)*1.1)", "math.random(-1.15, -0.95)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.6,0.7)*1.2"
},
"minecraft:particle_lifetime_events": {
"timeline": {
"0.07": "sparkle"
}
},
"minecraft:particle_initial_spin": {
"rotation": "math.random_integer(0,3)*90"
},
"minecraft:particle_initial_speed": "4-(v.emitter_age*4)",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 2, 0],
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": ["0.15*v.debrissize", "0.15*v.debrissize"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 64,
"texture_height": 8,
"flipbook": {
"base_UV": [56, 0],
"size_UV": [8, 8],
"step_UV": [-8, 0],
"frames_per_second": 12,
"max_frame": 8
}
}
},
"minecraft:particle_motion_collision": {
"collision_radius": 0.01,
"expire_on_contact": true
},
"minecraft:particle_appearance_tinting": {
"color": [1, 0.75686, 0.97647, 0.62745]
}
}
}
}
@@ -0,0 +1,65 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:fairywind_actorspark",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/impact/impact_fairy"
}
},
"curves": {
"variable.scale": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.73, 1, 0.96, 0.87, 0.61, 0]
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.5
},
"minecraft:emitter_shape_sphere": {
"radius": 0.2,
"surface_only": true,
"direction": ["math.random(-0.4,0.4)", "(math.random(-0.2,0.2))+((v.target_deltay/v.target_deltaz)*1.1)", "math.random(-1.15, -0.95)"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "0.5-(v.particle_random_4*0.1)"
},
"minecraft:particle_initial_speed": "math.clamp(v.target_deltaz*4,0,4)",
"minecraft:particle_motion_dynamic": {
"linear_drag_coefficient": 5
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.125*v.scale)-(v.particle_random_4*0.075)", "(0.125*v.scale)-(v.particle_random_4*0.075)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 56,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [8, 8],
"step_UV": [0, 8],
"frames_per_second": 16,
"max_frame": 7
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFFFFF",
"0.33": "#ffffffff",
"1.0": "#FFFF80E7"
}
}
}
}
}
}
@@ -0,0 +1,68 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:fairywind_target",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/vanilla/generic"
}
},
"curves": {
"variable.debrissize": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 1, 0.69, 0.35, 0]
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 200,
"max_particles": 100
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.1
},
"minecraft:emitter_shape_sphere": {
"offset": [0, 0, "-0.4/math.clamp(q.entity_scale*1.1-0.1,1,9)"],
"radius": 0.1,
"surface_only": true,
"direction": "outwards"
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.6,0.7)"
},
"minecraft:particle_initial_spin": {
"rotation": "math.random_integer(0,3)*90"
},
"minecraft:particle_initial_speed": "math.random(1.5,2.75)*2.85",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 3, 0],
"linear_drag_coefficient": 4
},
"minecraft:particle_appearance_billboard": {
"size": ["0.2*v.debrissize", "0.2*v.debrissize"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 64,
"texture_height": 8,
"flipbook": {
"base_UV": [56, 0],
"size_UV": [8, 8],
"step_UV": [-8, 0],
"frames_per_second": 12,
"max_frame": 8
}
}
},
"minecraft:particle_motion_collision": {
"collision_radius": 0.01,
"expire_on_contact": true
},
"minecraft:particle_appearance_tinting": {
"color": [1, 0.75686, 0.97647, 0.62745]
}
}
}
}
@@ -0,0 +1,67 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:fairywind_targethit",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/impact/impact_fairy"
}
},
"curves": {
"variable.scale": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.73, 1, 0.96, 0.87, 0.61, 0]
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 20,
"max_particles": 8
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.7
},
"minecraft:emitter_shape_sphere": {
"radius": 0.8,
"surface_only": true,
"direction": "outwards"
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "0.5-(v.particle_random_4*0.1)"
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 2, 0],
"linear_drag_coefficient": 5
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.125*v.scale)-(v.particle_random_4*0.075)", "(0.125*v.scale)-(v.particle_random_4*0.075)"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 56,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [8, 8],
"step_UV": [0, 8],
"frames_per_second": 16,
"max_frame": 7
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFFFFFF",
"0.33": "#ffffffff",
"1.0": "#FFFF80E7"
}
}
}
}
}
}
@@ -0,0 +1,67 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:firefang_target",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/generic/bite"
}
},
"events": {
"event_sound": {
"sound_effect": {
"event_name": "cobblemon:move.bite.target"
}
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 1
},
"minecraft:emitter_lifetime_once": {
"active_time": 1
},
"minecraft:emitter_lifetime_events": {
"creation_event": "event_sound"
},
"minecraft:emitter_shape_point": {
"offset": [0, 0, -0.25]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.55
},
"minecraft:particle_initial_speed": 0,
"minecraft:particle_motion_dynamic": {},
"minecraft:particle_appearance_billboard": {
"size": [0.9, 0.9],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 32,
"texture_height": 320,
"flipbook": {
"base_UV": [0, 0],
"size_UV": [32, 32],
"step_UV": [0, 32],
"frames_per_second": 18,
"max_frame": 10
}
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#00570000",
"0.12": "#FFFF3A00",
"0.38": "#FFFF3A00",
"0.44": "#FFFFD600",
"0.63": "#FFFF7400",
"0.82": "#E0C30000",
"1.0": "#003E0C00"
}
}
}
}
}
}
@@ -0,0 +1,76 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:firefang_targetburst",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particles/generic/fire/cloudyfire_white"
}
},
"curves": {
"variable.fun": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [1, 1, 1, 1, 1, 0.96, 0.85, 0.6, -0.05]
}
},
"components": {
"minecraft:emitter_rate_steady": {
"spawn_rate": 150,
"max_particles": 10000
},
"minecraft:emitter_lifetime_once": {
"active_time": 0.1
},
"minecraft:emitter_shape_point": {
"direction": ["math.random(-1.75,1.75)", "math.random(-1.15,0.85)", "math.random(-0.65,0.65)*1.15"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.65,0.95)"
},
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_4*3)*90"
},
"minecraft:particle_initial_speed": "(math.random(2,5.25)*math.clamp(v.entity_height,1,1.5))*1.85",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*5", "4+(v.particle_random_2-0.5)*3", "(v.particle_random_3-0.5)*5"],
"linear_drag_coefficient": 4
},
"minecraft:particle_appearance_billboard": {
"size": ["(0.5-(v.particle_random_4*0.15))*v.fun", "(0.5-(v.particle_random_4*0.15))*v.fun"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 160,
"texture_height": 16,
"flipbook": {
"base_UV": [16, 0],
"size_UV": [16, 16],
"step_UV": [16, 0],
"frames_per_second": 20,
"max_frame": 9
}
}
},
"minecraft:particle_motion_collision": {
"collision_drag": 10,
"collision_radius": 0.01
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#ffffffff",
"0.2": "#FFFFE872",
"0.4": "#FFFFCC00",
"0.55": "#FFFF9400",
"0.75": "#FFFF4700",
"0.9": "#FFFF4700",
"1.0": "#FF531C0E"
}
}
}
}
}
}
@@ -0,0 +1,67 @@
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "cobblemon:firefang_targetspark",
"basic_render_parameters": {
"material": "particles_blend",
"texture": "textures/particles/vanilla/critical_hit"
}
},
"curves": {
"variable.bitespark": {
"type": "linear",
"input": "v.particle_age",
"horizontal_range": "v.particle_lifetime",
"nodes": [0, 0.87, 1, 0.5, 0]
}
},
"components": {
"minecraft:emitter_rate_instant": {
"num_particles": 10
},
"minecraft:emitter_lifetime_looping": {
"active_time": 1
},
"minecraft:emitter_shape_sphere": {
"offset": [0, 0, -0.25],
"radius": 0.025,
"surface_only": true,
"direction": "outwards"
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": 0.35
},
"minecraft:particle_initial_speed": "math.random(1.75,4.55)*3",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, -5, 0],
"linear_drag_coefficient": 4
},
"minecraft:particle_appearance_billboard": {
"size": ["0.1*v.bitespark", "0.1*v.bitespark"],
"facing_camera_mode": "rotate_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [7, 7]
}
},
"minecraft:particle_motion_collision": {
"collision_radius": 0.01,
"expire_on_contact": true
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"gradient": {
"0.0": "#FFFF3A00",
"0.23": "#FFFFAD00",
"0.6": "#FFFF3A00",
"1.0": "#FF9D2300"
}
}
}
}
}
}
@@ -25,7 +25,7 @@
"active_time": 0.9
},
"minecraft:emitter_shape_point": {
"offset": ["-v.target_deltax*(v.emitter_age/v.emitter_lifetime)", "v.target_deltay*(v.emitter_age/v.emitter_lifetime)+(v.burstarc*0.7)", "-v.target_deltaz*(v.emitter_age/v.emitter_lifetime)"],
"offset": ["v.target_deltax*(v.emitter_age/v.emitter_lifetime)", "v.target_deltay*(v.emitter_age/v.emitter_lifetime)+(v.burstarc*0.7)", "-v.target_deltaz*(v.emitter_age/v.emitter_lifetime)"],
"direction": ["math.random(-0.45,0.45)", "(v.burstarc/math.clamp(v.target_deltaz*0.5,1,4))+math.random(-0.45,0.45)-(v.target_deltay/v.target_deltaz)", "math.random(-2.05,-0.55)"]
},
"minecraft:particle_lifetime_expression": {
@@ -28,7 +28,8 @@
"active_time": 1
},
"minecraft:emitter_shape_point": {
"direction": ["(-v.target_deltax+((v.particle_random_1-0.5)*1.05))+(math.sin(v.emitter_age*360)*0.25)", "(v.target_deltay+((v.particle_random_2-0.5)*0.95))+(math.sin(v.emitter_age*540)*0.2)", "-v.target_deltaz*1.05"]
"offset": [0, 0, 0],
"direction": ["(-v.target_deltax+((v.particle_random_1-0.5)*1.15))+(math.sin(v.emitter_age*360)*0.35)", "(v.target_deltay+((v.particle_random_2-0.5)*1.05))+(math.sin(v.emitter_age*540)*0.3)", "-v.target_deltaz"]
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.65,1.0)*1.4"
@@ -36,9 +37,9 @@
"minecraft:particle_initial_spin": {
"rotation": "math.round(v.particle_random_4*3)*90"
},
"minecraft:particle_initial_speed": "(v.target_deltaz*math.random(0.65,2.05))*(math.clamp(v.target_deltaz,3,24)/2)",
"minecraft:particle_initial_speed": "(v.target_deltaz*((v.particle_random_4+0.75)*1.25))*(math.clamp(v.target_deltaz,3,24)/2)",
"minecraft:particle_motion_dynamic": {
"linear_acceleration": ["(v.particle_random_1-0.5)*4", "3+(v.particle_random_2-0.5)*2", "(v.particle_random_3-0.5)*1"],
"linear_acceleration": ["(v.particle_random_3-0.5)*4", "3+(v.particle_random_4-0.5)*2", "(v.particle_random_2-0.5)*1"],
"linear_drag_coefficient": "math.clamp(v.target_deltaz,1,20)*(0.5+(math.clamp(v.target_deltaz,1,5)*0.05))"
},
"minecraft:particle_appearance_billboard": {
@@ -62,15 +63,15 @@
},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",
"interpolant": "(v.particle_age / v.particle_lifetime) * (v.particle_random_4+0.75)",
"gradient": {
"0.0": "#ffffffff",
"0.2": "#FFFFE872",
"0.4": "#FFFFCC00",
"0.55": "#FFFF9400",
"0.0": "#FFB3F6FF",
"0.05": "#FFFFFFFF",
"0.15": "#FFFFE872",
"0.3": "#FFFFCC00",
"0.5": "#FFFF8700",
"0.75": "#FFFF4700",
"0.9": "#FFFF4700",
"1.0": "#FF531C0E"
"1.0": "#FFA31F00"
}
}
}
@@ -60,7 +60,6 @@
"minecraft:particle_motion_collision": {
"collision_radius": 0.1
},
"minecraft:particle_appearance_lighting": {},
"minecraft:particle_appearance_tinting": {
"color": {
"interpolant": "v.particle_age / v.particle_lifetime",

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